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

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-SJPRTSGY.js";
61
+ } from "./chunk-HBDGUVUH.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 defineCommand227, runMain } from "citty";
111
+ import { defineCommand as defineCommand229, runMain } from "citty";
112
112
 
113
113
  // src/cache-flag.ts
114
114
  var NO_CACHE_ARG = {
@@ -3936,10 +3936,35 @@ 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
+ });
3939
3958
  var capabilitiesResponseSchema = z9.object({
3940
3959
  ok: z9.literal(true),
3941
3960
  data: z9.object({
3942
- surfaces: z9.array(capabilitySurfaceReportSchema)
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)
3943
3968
  })
3944
3969
  });
3945
3970
 
@@ -3986,6 +4011,8 @@ var chatChangeTypeSchema = z10.enum([
3986
4011
  // what the edge captures and one held until Publish would not measure the
3987
4012
  // campaign it was written for.
3988
4013
  "analytics-mapping",
4014
+ // An A/B test between a landing and its alternative. Staged, not immediate.
4015
+ "experiment",
3989
4016
  "briefs"
3990
4017
  ]);
3991
4018
  var chatChangeActionSchema = z10.enum(["created", "updated", "deleted"]);
@@ -9780,11 +9807,11 @@ function rawTextEntries(value) {
9780
9807
  const values = Array.isArray(value) ? value : typeof value === "string" ? [value] : [];
9781
9808
  return values.filter((v) => typeof v === "string").flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
9782
9809
  }
9783
- function rawFileEntries(path38) {
9784
- if (typeof path38 !== "string" || path38.length === 0) {
9810
+ function rawFileEntries(path41) {
9811
+ if (typeof path41 !== "string" || path41.length === 0) {
9785
9812
  return [];
9786
9813
  }
9787
- return readFileSync2(path38, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
9814
+ return readFileSync2(path41, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
9788
9815
  }
9789
9816
  function keywordEntries(args) {
9790
9817
  const defaultMatch = typeof args["match-type"] === "string" ? args["match-type"].toUpperCase() : void 0;
@@ -9807,19 +9834,19 @@ function keywordEntries(args) {
9807
9834
  }
9808
9835
  return entries;
9809
9836
  }
9810
- function loadJsonFileArg(path38) {
9811
- if (typeof path38 !== "string" || path38.length === 0) {
9837
+ function loadJsonFileArg(path41) {
9838
+ if (typeof path41 !== "string" || path41.length === 0) {
9812
9839
  return {};
9813
9840
  }
9814
9841
  try {
9815
- const parsed = JSON.parse(readFileSync2(path38, "utf8"));
9842
+ const parsed = JSON.parse(readFileSync2(path41, "utf8"));
9816
9843
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
9817
- failWriteValidation(`${path38} must contain a JSON object`);
9844
+ failWriteValidation(`${path41} must contain a JSON object`);
9818
9845
  }
9819
9846
  return parsed;
9820
9847
  } catch (err) {
9821
9848
  if (err instanceof SyntaxError) {
9822
- failWriteValidation(`${path38} is not valid JSON: ${err.message}`);
9849
+ failWriteValidation(`${path41} is not valid JSON: ${err.message}`);
9823
9850
  }
9824
9851
  throw err;
9825
9852
  }
@@ -9949,10 +9976,10 @@ async function stageUpdate(kind, customerId, target, payload, hints) {
9949
9976
  async function stageTarget(kind, customerId, target, hints) {
9950
9977
  await stageGoogleOp({ kind, customerId, target }, hints);
9951
9978
  }
9952
- async function draftAction(path38, body, chat) {
9979
+ async function draftAction(path41, body, chat) {
9953
9980
  try {
9954
9981
  const chatId = resolveChatId(chat);
9955
- const response = await apiPost(path38, { chatId, ...body });
9982
+ const response = await apiPost(path41, { chatId, ...body });
9956
9983
  writeJsonEnvelope(response);
9957
9984
  } catch (err) {
9958
9985
  handleGoogleError(err);
@@ -15166,19 +15193,19 @@ function failWriteValidation2(message) {
15166
15193
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
15167
15194
  process.exit(1);
15168
15195
  }
15169
- function loadJsonFileArg2(path38) {
15170
- if (typeof path38 !== "string" || path38.length === 0) {
15196
+ function loadJsonFileArg2(path41) {
15197
+ if (typeof path41 !== "string" || path41.length === 0) {
15171
15198
  return {};
15172
15199
  }
15173
15200
  try {
15174
- const parsed = JSON.parse(readFileSync4(path38, "utf8"));
15201
+ const parsed = JSON.parse(readFileSync4(path41, "utf8"));
15175
15202
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
15176
- failWriteValidation2(`${path38} must contain a JSON object`);
15203
+ failWriteValidation2(`${path41} must contain a JSON object`);
15177
15204
  }
15178
15205
  return parsed;
15179
15206
  } catch (err) {
15180
15207
  if (err instanceof SyntaxError) {
15181
- failWriteValidation2(`${path38} is not valid JSON: ${err.message}`);
15208
+ failWriteValidation2(`${path41} is not valid JSON: ${err.message}`);
15182
15209
  }
15183
15210
  throw err;
15184
15211
  }
@@ -15263,15 +15290,15 @@ function parseLocaleFlag(value) {
15263
15290
  }
15264
15291
  return { language: match[1], country: match[2].toUpperCase() };
15265
15292
  }
15266
- function loadTargetingFileArg(path38) {
15267
- if (typeof path38 !== "string" || path38.length === 0) {
15293
+ function loadTargetingFileArg(path41) {
15294
+ if (typeof path41 !== "string" || path41.length === 0) {
15268
15295
  return void 0;
15269
15296
  }
15270
- const parsed = loadJsonFileArg2(path38);
15297
+ const parsed = loadJsonFileArg2(path41);
15271
15298
  const criteria = parsed.targetingCriteria ?? parsed;
15272
15299
  if (!criteria.include) {
15273
15300
  failWriteValidation2(
15274
- `${path38} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
15301
+ `${path41} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
15275
15302
  );
15276
15303
  }
15277
15304
  return criteria;
@@ -15306,14 +15333,14 @@ function parseCsvLine(line) {
15306
15333
  cells.push(current);
15307
15334
  return cells.map((cell2) => cell2.trim());
15308
15335
  }
15309
- function parseListFileArg(path38, maxRows) {
15310
- if (typeof path38 !== "string" || path38.length === 0) {
15336
+ function parseListFileArg(path41, maxRows) {
15337
+ if (typeof path41 !== "string" || path41.length === 0) {
15311
15338
  return void 0;
15312
15339
  }
15313
- const raw = readFileSync4(path38, "utf8");
15340
+ const raw = readFileSync4(path41, "utf8");
15314
15341
  const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
15315
15342
  if (lines.length < 2) {
15316
- failWriteValidation2(`${path38} needs a header row and at least one data row`);
15343
+ failWriteValidation2(`${path41} needs a header row and at least one data row`);
15317
15344
  }
15318
15345
  const columns = parseCsvLine(lines[0]).map((column) => column.trim());
15319
15346
  const rows = [];
@@ -15332,7 +15359,7 @@ function parseListFileArg(path38, maxRows) {
15332
15359
  }
15333
15360
  }
15334
15361
  if (rows.length > maxRows) {
15335
- failWriteValidation2(`${path38} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
15362
+ failWriteValidation2(`${path41} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
15336
15363
  }
15337
15364
  return { columns, rows };
15338
15365
  }
@@ -15428,11 +15455,11 @@ function readPositionals(args) {
15428
15455
  function splitIdList(raw) {
15429
15456
  return raw.split(",").map((id) => id.trim()).filter(Boolean);
15430
15457
  }
15431
- function idsFileEntries(path38) {
15432
- if (typeof path38 !== "string" || path38.length === 0) {
15458
+ function idsFileEntries(path41) {
15459
+ if (typeof path41 !== "string" || path41.length === 0) {
15433
15460
  return [];
15434
15461
  }
15435
- return readFileSync4(path38, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).flatMap(splitIdList);
15462
+ return readFileSync4(path41, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).flatMap(splitIdList);
15436
15463
  }
15437
15464
  function requireTargets(args, entity) {
15438
15465
  const positionals = readPositionals(args);
@@ -18053,9 +18080,9 @@ function compactRow(row) {
18053
18080
  ...destination.postUrn ? { postUrn: destination.postUrn } : {}
18054
18081
  };
18055
18082
  }
18056
- function readPath(row, path38) {
18083
+ function readPath(row, path41) {
18057
18084
  let current = row;
18058
- for (const segment of path38.split(".")) {
18085
+ for (const segment of path41.split(".")) {
18059
18086
  const record = asRecord2(current);
18060
18087
  if (!record) return void 0;
18061
18088
  current = record[segment];
@@ -18065,10 +18092,10 @@ function readPath(row, path38) {
18065
18092
  function projectFields(rows, paths) {
18066
18093
  return rows.map((row) => {
18067
18094
  const projected = {};
18068
- for (const path38 of paths) {
18069
- const value = readPath(row, path38);
18095
+ for (const path41 of paths) {
18096
+ const value = readPath(row, path41);
18070
18097
  if (value !== void 0) {
18071
- projected[path38] = value;
18098
+ projected[path41] = value;
18072
18099
  }
18073
18100
  }
18074
18101
  return projected;
@@ -19368,11 +19395,11 @@ var updateStatusSchema = z25.enum(UPDATE_STATUSES);
19368
19395
  function currencyMinimums2(currencyCode) {
19369
19396
  return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
19370
19397
  }
19371
- function validateDailyBudgetFloor(money, ctx, path38) {
19398
+ function validateDailyBudgetFloor(money, ctx, path41) {
19372
19399
  if (money?.currencyCode) {
19373
19400
  const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
19374
19401
  if (Number(money.amount) < min) {
19375
- ctx.addIssue({ code: "custom", path: path38, message: `below the ${min} ${money.currencyCode} daily minimum` });
19402
+ ctx.addIssue({ code: "custom", path: path41, message: `below the ${min} ${money.currencyCode} daily minimum` });
19376
19403
  }
19377
19404
  }
19378
19405
  }
@@ -20041,19 +20068,19 @@ function failWriteValidation3(message) {
20041
20068
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
20042
20069
  process.exit(1);
20043
20070
  }
20044
- function loadJsonFileArg3(path38) {
20045
- if (typeof path38 !== "string" || path38.length === 0) {
20071
+ function loadJsonFileArg3(path41) {
20072
+ if (typeof path41 !== "string" || path41.length === 0) {
20046
20073
  return {};
20047
20074
  }
20048
20075
  try {
20049
- const parsed = JSON.parse(readFileSync8(path38, "utf8"));
20076
+ const parsed = JSON.parse(readFileSync8(path41, "utf8"));
20050
20077
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
20051
- failWriteValidation3(`${path38} must contain a JSON object`);
20078
+ failWriteValidation3(`${path41} must contain a JSON object`);
20052
20079
  }
20053
20080
  return parsed;
20054
20081
  } catch (err) {
20055
20082
  if (err instanceof SyntaxError) {
20056
- failWriteValidation3(`${path38} is not valid JSON: ${err.message}`);
20083
+ failWriteValidation3(`${path41} is not valid JSON: ${err.message}`);
20057
20084
  }
20058
20085
  throw err;
20059
20086
  }
@@ -24654,11 +24681,11 @@ function unwrap(response) {
24654
24681
  }
24655
24682
  return response.data;
24656
24683
  }
24657
- async function readAvatars(path38, params) {
24658
- return unwrap(await apiGet(path38, params));
24684
+ async function readAvatars(path41, params) {
24685
+ return unwrap(await apiGet(path41, params));
24659
24686
  }
24660
- async function writeAvatars(path38, body) {
24661
- return unwrap(await apiPost(path38, body));
24687
+ async function writeAvatars(path41, body) {
24688
+ return unwrap(await apiPost(path41, body));
24662
24689
  }
24663
24690
 
24664
24691
  // src/commands/avatars/create.ts
@@ -25492,12 +25519,12 @@ function missingFontFiles(urls, available) {
25492
25519
  function planFontAdoption(sources, families) {
25493
25520
  const wanted = new Map(families.map((family) => [normalizeFamily(family), family]));
25494
25521
  const byFamily = /* @__PURE__ */ new Map();
25495
- for (const { path: path38, source } of sources) {
25496
- const dir = posix.dirname(path38);
25522
+ for (const { path: path41, source } of sources) {
25523
+ const dir = posix.dirname(path41);
25497
25524
  for (const face of declaredFontFaces(source)) {
25498
25525
  if (!wanted.has(face.family)) continue;
25499
25526
  const perFile = byFamily.get(face.family) ?? /* @__PURE__ */ new Map();
25500
- perFile.set(path38, [...perFile.get(path38) ?? [], rebaseFontFaceSrc(face.block, dir)]);
25527
+ perFile.set(path41, [...perFile.get(path41) ?? [], rebaseFontFaceSrc(face.block, dir)]);
25501
25528
  byFamily.set(face.family, perFile);
25502
25529
  }
25503
25530
  }
@@ -26521,10 +26548,10 @@ import { defineCommand as defineCommand100 } from "citty";
26521
26548
  import { existsSync as existsSync3, realpathSync } from "fs";
26522
26549
  import { writeFile as writeFile2 } from "fs/promises";
26523
26550
  import path5 from "path";
26524
- function findWorkspaceRoot(startDir, exists = existsSync3, maxDepth = 12) {
26551
+ function findWorkspaceRoot(startDir, exists2 = existsSync3, maxDepth = 12) {
26525
26552
  let dir = path5.resolve(startDir);
26526
26553
  for (let i = 0; i < maxDepth; i++) {
26527
- if (exists(path5.join(dir, "package.json"))) return dir;
26554
+ if (exists2(path5.join(dir, "package.json"))) return dir;
26528
26555
  const parent = path5.dirname(dir);
26529
26556
  if (parent === dir) break;
26530
26557
  dir = parent;
@@ -30471,10 +30498,10 @@ function runDirsToPrune(entries, keep, currentRunId) {
30471
30498
  return runs.slice(0, Math.max(0, runs.length - keep));
30472
30499
  }
30473
30500
  async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
30474
- const { readdir: readdir10 } = await import("fs/promises");
30501
+ const { readdir: readdir11 } = await import("fs/promises");
30475
30502
  let entries;
30476
30503
  try {
30477
- entries = await readdir10(outputsDir);
30504
+ entries = await readdir11(outputsDir);
30478
30505
  } catch {
30479
30506
  return;
30480
30507
  }
@@ -32266,12 +32293,12 @@ async function detectSceneCutsPySceneDetect(filePath, opts = {}) {
32266
32293
  // src/commands/canvas/composition-path.ts
32267
32294
  import { existsSync as existsSync4 } from "fs";
32268
32295
  import path21 from "path";
32269
- function resolveShippedCanvasDir(name, startDir, exists = existsSync4, maxDepth = 8) {
32296
+ function resolveShippedCanvasDir(name, startDir, exists2 = existsSync4, maxDepth = 8) {
32270
32297
  const rel = path21.join("canvas", name);
32271
32298
  let dir = startDir;
32272
32299
  for (let i = 0; i < maxDepth; i++) {
32273
32300
  const candidate = path21.join(dir, rel);
32274
- if (exists(path21.join(candidate, "meta.json"))) return candidate;
32301
+ if (exists2(path21.join(candidate, "meta.json"))) return candidate;
32275
32302
  const parent = path21.dirname(dir);
32276
32303
  if (parent === dir) break;
32277
32304
  dir = parent;
@@ -33097,7 +33124,7 @@ registerSchema({
33097
33124
  }
33098
33125
  }
33099
33126
  });
33100
- function capabilityHints(surfaces) {
33127
+ function capabilityHints(surfaces, tools = []) {
33101
33128
  const hints = [];
33102
33129
  const immediate = surfaces.filter((surface) => surface.writeMode === "applies-at-publish");
33103
33130
  if (immediate.length > 0) {
@@ -33120,6 +33147,18 @@ function capabilityHints(surfaces) {
33120
33147
  "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."
33121
33148
  );
33122
33149
  }
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
+ }
33123
33162
  return hints;
33124
33163
  }
33125
33164
  var runCapabilities = defineCommand108({
@@ -33129,6 +33168,8 @@ var runCapabilities = defineCommand108({
33129
33168
 
33130
33169
  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.
33131
33170
 
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
+
33132
33173
  Examples:
33133
33174
  baker capabilities
33134
33175
  baker capabilities google-ads
@@ -33164,7 +33205,7 @@ Full guide: __tooling__/docs/tools/baker/capabilities.md`
33164
33205
  body.full = true;
33165
33206
  }
33166
33207
  const response = await apiPost("/api/capabilities", body);
33167
- const hints = capabilityHints(response.data.surfaces);
33208
+ const hints = capabilityHints(response.data.surfaces, response.data.tools);
33168
33209
  writeJson({
33169
33210
  ...response,
33170
33211
  meta: { count: response.data.surfaces.length },
@@ -33634,12 +33675,793 @@ Full guide: __tooling__/docs/tools/baker/creatives.md`
33634
33675
  }
33635
33676
  });
33636
33677
 
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
+
33637
34459
  // src/commands/flows/index.ts
33638
- import { defineCommand as defineCommand116 } from "citty";
34460
+ import { defineCommand as defineCommand117 } from "citty";
33639
34461
 
33640
34462
  // src/commands/flows/add.ts
33641
34463
  import { randomUUID } from "crypto";
33642
- import { defineCommand as defineCommand112 } from "citty";
34464
+ import { defineCommand as defineCommand113 } from "citty";
33643
34465
 
33644
34466
  // src/commands/flows/shared.ts
33645
34467
  import { existsSync as existsSync5, readdirSync as readdirSync2, readFileSync as readFileSync9, writeFileSync as writeFileSync3 } from "fs";
@@ -33692,12 +34514,12 @@ function collectSideEffects(tree) {
33692
34514
  );
33693
34515
  }
33694
34516
  function readFlowTree(slug) {
33695
- const path38 = join3(flowsDir(), slug, "_data.json");
33696
- if (!existsSync5(path38)) {
34517
+ const path41 = join3(flowsDir(), slug, "_data.json");
34518
+ if (!existsSync5(path41)) {
33697
34519
  failLocal(`No form "${slug}". Run "baker flows list" to see the forms in this workspace.`);
33698
34520
  }
33699
34521
  try {
33700
- return JSON.parse(readFileSync9(path38, "utf-8"));
34522
+ return JSON.parse(readFileSync9(path41, "utf-8"));
33701
34523
  } catch (error) {
33702
34524
  failLocal(`Could not read form "${slug}": ${error instanceof Error ? error.message : String(error)}`);
33703
34525
  }
@@ -33849,7 +34671,7 @@ registerSchema({
33849
34671
  parent: { type: "string", description: "Parent node id. Omit to append to the root's children.", required: false }
33850
34672
  }
33851
34673
  });
33852
- var addNodeCommand = defineCommand112({
34674
+ var addNodeCommand = defineCommand113({
33853
34675
  meta: {
33854
34676
  name: "add-node",
33855
34677
  description: 'Add a step to a form, with the skeleton its type requires. Example: baker flows add-node contact --type customForm --name "Contact Info"'
@@ -33945,7 +34767,7 @@ registerSchema({
33945
34767
  }
33946
34768
  }
33947
34769
  });
33948
- var addSideEffectCommand = defineCommand112({
34770
+ var addSideEffectCommand = defineCommand113({
33949
34771
  meta: {
33950
34772
  name: "add-side-effect",
33951
34773
  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"
@@ -34027,7 +34849,7 @@ var addSideEffectCommand = defineCommand112({
34027
34849
 
34028
34850
  // src/commands/flows/map.ts
34029
34851
  import { readFileSync as readFileSync11 } from "fs";
34030
- import { defineCommand as defineCommand113 } from "citty";
34852
+ import { defineCommand as defineCommand114 } from "citty";
34031
34853
 
34032
34854
  // src/commands/flows/value-expression.ts
34033
34855
  import { existsSync as existsSync6, readFileSync as readFileSync10 } from "fs";
@@ -34089,10 +34911,10 @@ function parseValueExpression(raw) {
34089
34911
  return parts.map(parsePart);
34090
34912
  }
34091
34913
  function trackingFieldIds() {
34092
- const path38 = join4(flowsDir(), "..", "tracking.ts");
34093
- if (!existsSync6(path38)) return null;
34914
+ const path41 = join4(flowsDir(), "..", "tracking.ts");
34915
+ if (!existsSync6(path41)) return null;
34094
34916
  try {
34095
- const source = readFileSync10(path38, "utf-8");
34917
+ const source = readFileSync10(path41, "utf-8");
34096
34918
  const block2 = source.match(/TRACKING_FIELD_IDS\s*=\s*\[([\s\S]*?)\]\s*as const/)?.[1];
34097
34919
  if (!block2) return null;
34098
34920
  const ids = [...block2.matchAll(/"(tracking\.[a-z0-9_]+)"/g)].map((match) => match[1]);
@@ -34644,13 +35466,13 @@ function specsFromFile(parsed) {
34644
35466
  return `${destField}${type}=${entry?.value ?? ""}`;
34645
35467
  });
34646
35468
  }
34647
- function readSpecFile(path38) {
35469
+ function readSpecFile(path41) {
34648
35470
  let raw;
34649
35471
  try {
34650
- raw = path38 === "-" ? readFileSync11(0, "utf-8") : readFileSync11(path38, "utf-8");
35472
+ raw = path41 === "-" ? readFileSync11(0, "utf-8") : readFileSync11(path41, "utf-8");
34651
35473
  } catch (error) {
34652
35474
  refuse(
34653
- `Could not read ${path38 === "-" ? "the mapping from stdin" : `"${path38}"`}: ${error instanceof Error ? error.message : String(error)}`
35475
+ `Could not read ${path41 === "-" ? "the mapping from stdin" : `"${path41}"`}: ${error instanceof Error ? error.message : String(error)}`
34654
35476
  );
34655
35477
  }
34656
35478
  let parsed;
@@ -34658,7 +35480,7 @@ function readSpecFile(path38) {
34658
35480
  parsed = JSON.parse(raw);
34659
35481
  } catch (error) {
34660
35482
  refuse(
34661
- `${path38 === "-" ? "stdin" : `"${path38}"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
35483
+ `${path41 === "-" ? "stdin" : `"${path41}"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
34662
35484
  'Expected { "map": { "<destField>": "<value>", \u2026 } }'
34663
35485
  );
34664
35486
  }
@@ -34800,7 +35622,7 @@ async function mapOptions(args, fromFile, into) {
34800
35622
  destinationFields: hubspotForm ? await hubspotFieldCatalog(hubspotForm) : void 0
34801
35623
  };
34802
35624
  }
34803
- var mapCommand2 = defineCommand113({
35625
+ var mapCommand2 = defineCommand114({
34804
35626
  meta: {
34805
35627
  name: "map",
34806
35628
  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"
@@ -34898,7 +35720,7 @@ var mapCommand2 = defineCommand113({
34898
35720
  });
34899
35721
 
34900
35722
  // src/commands/flows/normalize.ts
34901
- import { defineCommand as defineCommand114 } from "citty";
35723
+ import { defineCommand as defineCommand115 } from "citty";
34902
35724
  var OPTIONAL_STRINGS = ["oauthProviderId"];
34903
35725
  var ARRAY_FIELDS = [
34904
35726
  "fieldMapping",
@@ -34912,18 +35734,18 @@ var ARRAY_FIELDS = [
34912
35734
  "tagIds"
34913
35735
  ];
34914
35736
  var ARRAY_OWNERS = ["", "body"];
34915
- function dropUnsetOptionals(sideEffect, path38) {
35737
+ function dropUnsetOptionals(sideEffect, path41) {
34916
35738
  return OPTIONAL_STRINGS.flatMap((key) => {
34917
35739
  if (!(key in sideEffect) || sideEffect[key] !== null && sideEffect[key] !== "") return [];
34918
35740
  delete sideEffect[key];
34919
- return [{ path: path38, change: `dropped \`${key}\` (an optional string is absent, never null)` }];
35741
+ return [{ path: path41, change: `dropped \`${key}\` (an optional string is absent, never null)` }];
34920
35742
  });
34921
35743
  }
34922
- function fillNulledArrays(target, prefix, path38) {
35744
+ function fillNulledArrays(target, prefix, path41) {
34923
35745
  return ARRAY_FIELDS.flatMap((key) => {
34924
35746
  if (!(key in target) || target[key] !== null) return [];
34925
35747
  target[key] = [];
34926
- return [{ path: path38, change: `\`${prefix}${key}: null\` \u2192 \`[]\`` }];
35748
+ return [{ path: path41, change: `\`${prefix}${key}: null\` \u2192 \`[]\`` }];
34927
35749
  });
34928
35750
  }
34929
35751
  function sideEffectsOf(node) {
@@ -34933,13 +35755,13 @@ function sideEffectsOf(node) {
34933
35755
  );
34934
35756
  }
34935
35757
  function normalizeSideEffect(sideEffect, where) {
34936
- const path38 = `${where} \u2192 ${String(sideEffect.id ?? "side effect")}`;
35758
+ const path41 = `${where} \u2192 ${String(sideEffect.id ?? "side effect")}`;
34937
35759
  const arrays = ARRAY_OWNERS.flatMap((owner) => {
34938
35760
  const target = owner ? sideEffect[owner] : sideEffect;
34939
35761
  if (!target || typeof target !== "object") return [];
34940
- return fillNulledArrays(target, owner ? `${owner}.` : "", path38);
35762
+ return fillNulledArrays(target, owner ? `${owner}.` : "", path41);
34941
35763
  });
34942
- return [...dropUnsetOptionals(sideEffect, path38), ...arrays];
35764
+ return [...dropUnsetOptionals(sideEffect, path41), ...arrays];
34943
35765
  }
34944
35766
  function normalizeFlowTree(tree) {
34945
35767
  const changes = [];
@@ -34967,7 +35789,7 @@ registerSchema({
34967
35789
  }
34968
35790
  }
34969
35791
  });
34970
- var normalizeCommand = defineCommand114({
35792
+ var normalizeCommand = defineCommand115({
34971
35793
  meta: {
34972
35794
  name: "normalize",
34973
35795
  description: "Repair the shapes a form file is allowed to get slightly wrong. Example: baker flows normalize contact --write"
@@ -34998,7 +35820,7 @@ var normalizeCommand = defineCommand114({
34998
35820
  });
34999
35821
 
35000
35822
  // src/commands/flows/schema.ts
35001
- import { defineCommand as defineCommand115 } from "citty";
35823
+ import { defineCommand as defineCommand116 } from "citty";
35002
35824
  registerSchema({
35003
35825
  command: "flows.schema",
35004
35826
  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.",
@@ -35023,7 +35845,7 @@ function triggerHints(triggers) {
35023
35845
  `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(", ")}.` : "")
35024
35846
  ];
35025
35847
  }
35026
- var schemaCommand = defineCommand115({
35848
+ var schemaCommand = defineCommand116({
35027
35849
  meta: {
35028
35850
  name: "schema",
35029
35851
  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)"
@@ -35157,7 +35979,7 @@ function displayName(slug) {
35157
35979
  const name = tree.displayName;
35158
35980
  return typeof name === "string" && name.trim() ? name.trim() : slug;
35159
35981
  }
35160
- var listCommand12 = defineCommand116({
35982
+ var listCommand12 = defineCommand117({
35161
35983
  meta: {
35162
35984
  name: "list",
35163
35985
  description: "List Forms in this workspace with the count of confidential fields still needing setup. Example: baker flows list"
@@ -35178,7 +36000,7 @@ var listCommand12 = defineCommand116({
35178
36000
  });
35179
36001
  }
35180
36002
  });
35181
- var showCommand3 = defineCommand116({
36003
+ var showCommand3 = defineCommand117({
35182
36004
  meta: {
35183
36005
  name: "show",
35184
36006
  description: "Show a Form's confidential fields and their configuration status (never secret values). Example: baker flows show contact"
@@ -35206,7 +36028,7 @@ var showCommand3 = defineCommand116({
35206
36028
  });
35207
36029
  }
35208
36030
  });
35209
- var flowsCommand = defineCommand116({
36031
+ var flowsCommand = defineCommand117({
35210
36032
  meta: {
35211
36033
  name: "flows",
35212
36034
  description: `Read and shape this workspace's Forms (flows).
@@ -35240,10 +36062,10 @@ Full guide: __tooling__/docs/tools/baker/flows.md`
35240
36062
  });
35241
36063
 
35242
36064
  // src/commands/ga4/index.ts
35243
- import { defineCommand as defineCommand123 } from "citty";
36065
+ import { defineCommand as defineCommand124 } from "citty";
35244
36066
 
35245
36067
  // src/commands/ga4/audit.ts
35246
- import { defineCommand as defineCommand117 } from "citty";
36068
+ import { defineCommand as defineCommand118 } from "citty";
35247
36069
 
35248
36070
  // src/commands/ga4/resolve.ts
35249
36071
  async function fetchProperties(useCache = true) {
@@ -35309,7 +36131,7 @@ registerSchema({
35309
36131
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
35310
36132
  }
35311
36133
  });
35312
- var auditCommand2 = defineCommand117({
36134
+ var auditCommand2 = defineCommand118({
35313
36135
  meta: {
35314
36136
  name: "audit",
35315
36137
  description: `Run all GA4 admin health checks. Returns property config with playbook warnings.
@@ -35364,7 +36186,7 @@ Examples:
35364
36186
  });
35365
36187
 
35366
36188
  // src/commands/ga4/config.ts
35367
- import { defineCommand as defineCommand118 } from "citty";
36189
+ import { defineCommand as defineCommand119 } from "citty";
35368
36190
 
35369
36191
  // src/commands/ga4/shared.ts
35370
36192
  import { readFileSync as readFileSync12 } from "fs";
@@ -35477,10 +36299,10 @@ async function stageOps(ops) {
35477
36299
  handleError2(err);
35478
36300
  }
35479
36301
  }
35480
- async function draftAction2(path38, body, chat) {
36302
+ async function draftAction2(path41, body, chat) {
35481
36303
  const chatId = resolveChatId(chat);
35482
36304
  try {
35483
- const data = await apiPost(path38, { chatId, ...body });
36305
+ const data = await apiPost(path41, { chatId, ...body });
35484
36306
  writeJsonEnvelope({ ok: true, data });
35485
36307
  return data;
35486
36308
  } catch (err) {
@@ -35560,7 +36382,7 @@ function configHints(config) {
35560
36382
  }
35561
36383
  return hints;
35562
36384
  }
35563
- var configCommand = defineCommand118({
36385
+ var configCommand = defineCommand119({
35564
36386
  meta: {
35565
36387
  name: "config",
35566
36388
  description: `Read how the property is configured to measure \u2014 key events, custom definitions, custom events, retention
@@ -35592,7 +36414,7 @@ Examples:
35592
36414
  });
35593
36415
 
35594
36416
  // src/commands/ga4/draft.ts
35595
- import { defineCommand as defineCommand119 } from "citty";
36417
+ import { defineCommand as defineCommand120 } from "citty";
35596
36418
  registerSchema({
35597
36419
  command: "ga4.draft",
35598
36420
  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.",
@@ -35601,13 +36423,13 @@ registerSchema({
35601
36423
  chat: { type: "string", description: CHAT_READ_ARG.description, required: false }
35602
36424
  }
35603
36425
  });
35604
- var draftCommand3 = defineCommand119({
36426
+ var draftCommand3 = defineCommand120({
35605
36427
  meta: {
35606
36428
  name: "draft",
35607
36429
  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."
35608
36430
  },
35609
36431
  subCommands: {
35610
- list: defineCommand119({
36432
+ list: defineCommand120({
35611
36433
  meta: { name: "list", description: "Review everything staged on this chat (--json for the raw envelope)" },
35612
36434
  args: {
35613
36435
  json: { type: "boolean", description: "Print the raw JSON envelope", required: false },
@@ -35617,7 +36439,7 @@ var draftCommand3 = defineCommand119({
35617
36439
  await draftList(args.json === true, args.chat);
35618
36440
  }
35619
36441
  }),
35620
- show: defineCommand119({
36442
+ show: defineCommand120({
35621
36443
  meta: {
35622
36444
  name: "show",
35623
36445
  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)."
@@ -35634,7 +36456,7 @@ var draftCommand3 = defineCommand119({
35634
36456
  );
35635
36457
  }
35636
36458
  }),
35637
- amend: defineCommand119({
36459
+ amend: defineCommand120({
35638
36460
  meta: {
35639
36461
  name: "amend",
35640
36462
  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."
@@ -35651,7 +36473,7 @@ var draftCommand3 = defineCommand119({
35651
36473
  });
35652
36474
  }
35653
36475
  }),
35654
- remove: defineCommand119({
36476
+ remove: defineCommand120({
35655
36477
  meta: { name: "remove", description: "Remove one staged change" },
35656
36478
  args: { ref: { type: "positional", description: "Staged ref or target id", required: false } },
35657
36479
  run: async ({ args }) => {
@@ -35660,7 +36482,7 @@ var draftCommand3 = defineCommand119({
35660
36482
  });
35661
36483
  }
35662
36484
  }),
35663
- clear: defineCommand119({
36485
+ clear: defineCommand120({
35664
36486
  meta: { name: "clear", description: "Discard all Google Analytics changes staged on this chat" },
35665
36487
  run: async () => {
35666
36488
  await draftAction2("/api/ga4/draft/clear", {});
@@ -35670,7 +36492,7 @@ var draftCommand3 = defineCommand119({
35670
36492
  });
35671
36493
 
35672
36494
  // src/commands/ga4/properties.ts
35673
- import { defineCommand as defineCommand120 } from "citty";
36495
+ import { defineCommand as defineCommand121 } from "citty";
35674
36496
  registerSchema({
35675
36497
  command: "ga4.properties",
35676
36498
  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.",
@@ -35686,7 +36508,7 @@ function propertyHints(properties) {
35686
36508
  resources: properties.map((property) => ({ id: property.externalId, label: property.name }))
35687
36509
  });
35688
36510
  }
35689
- var propertiesCommand = defineCommand120({
36511
+ var propertiesCommand = defineCommand121({
35690
36512
  meta: {
35691
36513
  name: "properties",
35692
36514
  description: `List accessible GA4 properties.
@@ -35736,7 +36558,7 @@ Examples:
35736
36558
  // src/commands/ga4/query.ts
35737
36559
  import { appendFileSync as appendFileSync2, existsSync as existsSync7, readFileSync as readFileSync13, writeFileSync as writeFileSync4 } from "fs";
35738
36560
  import { resolve as resolve2 } from "path";
35739
- import { defineCommand as defineCommand121 } from "citty";
36561
+ import { defineCommand as defineCommand122 } from "citty";
35740
36562
 
35741
36563
  // src/commands/ga4/presets.ts
35742
36564
  var GA4_PRESETS = [
@@ -35871,7 +36693,7 @@ function handleError3(err) {
35871
36693
  });
35872
36694
  process.exit(1);
35873
36695
  }
35874
- var queryCommand2 = defineCommand121({
36696
+ var queryCommand2 = defineCommand122({
35875
36697
  meta: {
35876
36698
  name: "query",
35877
36699
  description: `Run GA4 Data API reports. Preset-first with free-form escape hatch.
@@ -35942,7 +36764,7 @@ Free-form (escape hatch):
35942
36764
  });
35943
36765
 
35944
36766
  // src/commands/ga4/write-commands.ts
35945
- import { defineCommand as defineCommand122 } from "citty";
36767
+ import { defineCommand as defineCommand123 } from "citty";
35946
36768
  var PROPERTY_ARG_DESCRIPTION = "GA4 property id (optional only when one property is connected \u2014 run `baker ga4 properties`)";
35947
36769
  var propertyArg = { type: "string", description: PROPERTY_ARG_DESCRIPTION, required: false };
35948
36770
  function createJsonDescription(noun) {
@@ -35960,7 +36782,7 @@ registerSchema({
35960
36782
  "property-id": { type: "string", description: PROPERTY_ARG_DESCRIPTION, required: false }
35961
36783
  }
35962
36784
  });
35963
- var keyEventCommand = defineCommand122({
36785
+ var keyEventCommand = defineCommand123({
35964
36786
  meta: {
35965
36787
  name: "key-event",
35966
36788
  description: `Stage key-event (conversion) changes
@@ -35973,7 +36795,7 @@ Examples:
35973
36795
  baker ga4 key-event delete 4185`
35974
36796
  },
35975
36797
  subCommands: {
35976
- create: defineCommand122({
36798
+ create: defineCommand123({
35977
36799
  meta: {
35978
36800
  name: "create",
35979
36801
  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."
@@ -35994,7 +36816,7 @@ Examples:
35994
36816
  );
35995
36817
  }
35996
36818
  }),
35997
- update: defineCommand122({
36819
+ update: defineCommand123({
35998
36820
  meta: {
35999
36821
  name: "update",
36000
36822
  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."
@@ -36014,7 +36836,7 @@ Examples:
36014
36836
  });
36015
36837
  }
36016
36838
  }),
36017
- delete: defineCommand122({
36839
+ delete: defineCommand123({
36018
36840
  meta: {
36019
36841
  name: "delete",
36020
36842
  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."
@@ -36062,7 +36884,7 @@ for (const { kind, noun, createHint } of DEFINITIONS) {
36062
36884
  }
36063
36885
  function definitionCommand(definition) {
36064
36886
  const { command, kind, noun, example } = definition;
36065
- return defineCommand122({
36887
+ return defineCommand123({
36066
36888
  meta: {
36067
36889
  name: command,
36068
36890
  description: `Stage ${noun} changes
@@ -36074,7 +36896,7 @@ Examples:
36074
36896
  baker ga4 ${command} archive 12`
36075
36897
  },
36076
36898
  subCommands: {
36077
- create: defineCommand122({
36899
+ create: defineCommand123({
36078
36900
  meta: { name: "create", description: `Stage a new ${noun} (or a JSON array of them, staged together)` },
36079
36901
  args: {
36080
36902
  json: { type: "string", description: createJsonDescription(noun), required: false },
@@ -36092,7 +36914,7 @@ Examples:
36092
36914
  );
36093
36915
  }
36094
36916
  }),
36095
- update: defineCommand122({
36917
+ update: defineCommand123({
36096
36918
  meta: {
36097
36919
  name: "update",
36098
36920
  description: `Stage a change to an existing ${noun} (pass its id). The parameter name and scope cannot change \u2014 archive and recreate for that.`
@@ -36112,7 +36934,7 @@ Examples:
36112
36934
  });
36113
36935
  }
36114
36936
  }),
36115
- archive: defineCommand122({
36937
+ archive: defineCommand123({
36116
36938
  meta: {
36117
36939
  name: "archive",
36118
36940
  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.`
@@ -36157,7 +36979,7 @@ var dataStreamArg = {
36157
36979
  function withStream(args) {
36158
36980
  return typeof args["data-stream"] === "string" ? { dataStream: args["data-stream"] } : {};
36159
36981
  }
36160
- var customEventCommand = defineCommand122({
36982
+ var customEventCommand = defineCommand123({
36161
36983
  meta: {
36162
36984
  name: "custom-event",
36163
36985
  description: `Stage custom events \u2014 new events built from events the site already sends
@@ -36168,7 +36990,7 @@ Examples:
36168
36990
  baker ga4 custom-event delete 7`
36169
36991
  },
36170
36992
  subCommands: {
36171
- create: defineCommand122({
36993
+ create: defineCommand123({
36172
36994
  meta: {
36173
36995
  name: "create",
36174
36996
  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."
@@ -36191,7 +37013,7 @@ Examples:
36191
37013
  );
36192
37014
  }
36193
37015
  }),
36194
- update: defineCommand122({
37016
+ update: defineCommand123({
36195
37017
  meta: { name: "update", description: "Stage a change to an existing custom event (pass its id)" },
36196
37018
  args: {
36197
37019
  id: { type: "positional", description: "Custom event rule id", required: false },
@@ -36210,7 +37032,7 @@ Examples:
36210
37032
  });
36211
37033
  }
36212
37034
  }),
36213
- delete: defineCommand122({
37035
+ delete: defineCommand123({
36214
37036
  meta: {
36215
37037
  name: "delete",
36216
37038
  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."
@@ -36265,7 +37087,7 @@ function booleanArg(input, flag) {
36265
37087
  if (input === "false") return false;
36266
37088
  return failValidation3(`--${flag} must be true or false`);
36267
37089
  }
36268
- var dataRetentionCommand = defineCommand122({
37090
+ var dataRetentionCommand = defineCommand123({
36269
37091
  meta: {
36270
37092
  name: "data-retention",
36271
37093
  description: `Stage a change to how long Google Analytics keeps data
@@ -36275,7 +37097,7 @@ Examples:
36275
37097
  baker ga4 data-retention set --event-data 14 --user-data 14 --reset-on-activity true`
36276
37098
  },
36277
37099
  subCommands: {
36278
- set: defineCommand122({
37100
+ set: defineCommand123({
36279
37101
  meta: { name: "set", description: "Stage the retention window (months)" },
36280
37102
  args: {
36281
37103
  "event-data": { type: "string", description: "2, 14, 26, 38 or 50", required: false },
@@ -36311,7 +37133,7 @@ registerSchema({
36311
37133
  "property-id": { type: "string", description: PROPERTY_ARG_DESCRIPTION, required: false }
36312
37134
  }
36313
37135
  });
36314
- var audienceCommand = defineCommand122({
37136
+ var audienceCommand = defineCommand123({
36315
37137
  meta: {
36316
37138
  name: "audience",
36317
37139
  description: `Stage audience changes (saved groups of users, for retargeting and analysis)
@@ -36343,7 +37165,7 @@ Examples:
36343
37165
  baker ga4 audience archive 8813`
36344
37166
  },
36345
37167
  subCommands: {
36346
- create: defineCommand122({
37168
+ create: defineCommand123({
36347
37169
  meta: { name: "create", description: createJsonDescription("audience") },
36348
37170
  args: {
36349
37171
  json: { type: "string", description: createJsonDescription("audience"), required: false },
@@ -36361,7 +37183,7 @@ Examples:
36361
37183
  );
36362
37184
  }
36363
37185
  }),
36364
- update: defineCommand122({
37186
+ update: defineCommand123({
36365
37187
  meta: {
36366
37188
  name: "update",
36367
37189
  description: "Stage a new name or description (pass the audience id). Who is in it cannot be changed."
@@ -36382,7 +37204,7 @@ Examples:
36382
37204
  });
36383
37205
  }
36384
37206
  }),
36385
- archive: defineCommand122({
37207
+ archive: defineCommand123({
36386
37208
  meta: {
36387
37209
  name: "archive",
36388
37210
  description: "Stage retiring an audience. Cannot be undone \u2014 the users it gathered do not come back."
@@ -36411,7 +37233,7 @@ registerSchema({
36411
37233
  "property-id": { type: "string", description: PROPERTY_ARG_DESCRIPTION, required: false }
36412
37234
  }
36413
37235
  });
36414
- var propertyCommand = defineCommand122({
37236
+ var propertyCommand = defineCommand123({
36415
37237
  meta: {
36416
37238
  name: "property",
36417
37239
  description: `Stage a change to the property's own settings
@@ -36421,7 +37243,7 @@ Examples:
36421
37243
  baker ga4 property set --name "Acme \u2014 Web" --industry REAL_ESTATE`
36422
37244
  },
36423
37245
  subCommands: {
36424
- set: defineCommand122({
37246
+ set: defineCommand123({
36425
37247
  meta: { name: "set", description: "Stage the property name and/or industry category" },
36426
37248
  args: {
36427
37249
  name: { type: "string", description: "New property display name", required: false },
@@ -36461,7 +37283,7 @@ registerSchema({
36461
37283
  "property-id": { type: "string", description: PROPERTY_ARG_DESCRIPTION, required: false }
36462
37284
  }
36463
37285
  });
36464
- var adsLinkCommand = defineCommand122({
37286
+ var adsLinkCommand = defineCommand123({
36465
37287
  meta: {
36466
37288
  name: "ads-link",
36467
37289
  description: `Stage linking this property to a Google Ads account
@@ -36476,7 +37298,7 @@ Examples:
36476
37298
  baker ga4 ads-link delete L1234`
36477
37299
  },
36478
37300
  subCommands: {
36479
- create: defineCommand122({
37301
+ create: defineCommand123({
36480
37302
  meta: { name: "create", description: "Stage linking the property to a Google Ads account" },
36481
37303
  args: {
36482
37304
  "customer-id": { type: "string", description: "Google Ads customer id (123-456-7890)", required: false },
@@ -36495,7 +37317,7 @@ Examples:
36495
37317
  await stageOp3({ kind: "ga4.googleAdsLink.create", payload, ...withProperty(args) });
36496
37318
  }
36497
37319
  }),
36498
- update: defineCommand122({
37320
+ update: defineCommand123({
36499
37321
  meta: {
36500
37322
  name: "update",
36501
37323
  description: "Stage the ads-personalisation setting on an existing link (pass its id)"
@@ -36517,7 +37339,7 @@ Examples:
36517
37339
  });
36518
37340
  }
36519
37341
  }),
36520
- delete: defineCommand122({
37342
+ delete: defineCommand123({
36521
37343
  meta: {
36522
37344
  name: "delete",
36523
37345
  description: "Stage unlinking. Stops conversion imports and strands every audience on this property."
@@ -36568,7 +37390,7 @@ var MEASUREMENT_FLAGS = {
36568
37390
  "page-changes": "pageChangesEnabled",
36569
37391
  "form-interactions": "formInteractionsEnabled"
36570
37392
  };
36571
- var enhancedMeasurementCommand = defineCommand122({
37393
+ var enhancedMeasurementCommand = defineCommand123({
36572
37394
  meta: {
36573
37395
  name: "enhanced-measurement",
36574
37396
  description: `Stage the automatic events GA4 collects on a website stream
@@ -36582,7 +37404,7 @@ Examples:
36582
37404
  baker ga4 enhanced-measurement set --video false`
36583
37405
  },
36584
37406
  subCommands: {
36585
- set: defineCommand122({
37407
+ set: defineCommand123({
36586
37408
  meta: { name: "set", description: "Stage which automatic events the website stream collects" },
36587
37409
  args: {
36588
37410
  scrolls: { type: "string", description: "true|false", required: false },
@@ -36625,7 +37447,7 @@ Examples:
36625
37447
  });
36626
37448
 
36627
37449
  // src/commands/ga4/index.ts
36628
- var ga4Command = defineCommand123({
37450
+ var ga4Command = defineCommand124({
36629
37451
  meta: {
36630
37452
  name: "ga4",
36631
37453
  description: `Google Analytics 4. Report on a property, audit its config, and change what it measures.
@@ -36674,12 +37496,12 @@ Full guide: __tooling__/docs/tools/baker/ga4.md`
36674
37496
  });
36675
37497
 
36676
37498
  // src/commands/gsc/index.ts
36677
- import { defineCommand as defineCommand127 } from "citty";
37499
+ import { defineCommand as defineCommand128 } from "citty";
36678
37500
 
36679
37501
  // src/commands/gsc/query.ts
36680
37502
  import { appendFileSync as appendFileSync3, existsSync as existsSync8, readFileSync as readFileSync14, writeFileSync as writeFileSync5 } from "fs";
36681
37503
  import { resolve as resolve3 } from "path";
36682
- import { defineCommand as defineCommand124 } from "citty";
37504
+ import { defineCommand as defineCommand125 } from "citty";
36683
37505
 
36684
37506
  // src/commands/gsc/presets.ts
36685
37507
  var GSC_PRESETS = [
@@ -36873,7 +37695,7 @@ function handleError4(err) {
36873
37695
  });
36874
37696
  process.exit(1);
36875
37697
  }
36876
- var queryCommand3 = defineCommand124({
37698
+ var queryCommand3 = defineCommand125({
36877
37699
  meta: {
36878
37700
  name: "query",
36879
37701
  description: `Run GSC Search Analytics queries. Preset-first with free-form escape hatch.
@@ -36951,7 +37773,7 @@ Free-form (escape hatch):
36951
37773
  });
36952
37774
 
36953
37775
  // src/commands/gsc/sitemaps.ts
36954
- import { defineCommand as defineCommand125 } from "citty";
37776
+ import { defineCommand as defineCommand126 } from "citty";
36955
37777
  registerSchema({
36956
37778
  command: "gsc.sitemaps",
36957
37779
  description: "List sitemaps for a Search Console site. Check sitemap health and errors.",
@@ -36960,7 +37782,7 @@ registerSchema({
36960
37782
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
36961
37783
  }
36962
37784
  });
36963
- var sitemapsCommand = defineCommand125({
37785
+ var sitemapsCommand = defineCommand126({
36964
37786
  meta: {
36965
37787
  name: "sitemaps",
36966
37788
  description: `List sitemaps for a site. Check health and errors.
@@ -37013,7 +37835,7 @@ Examples:
37013
37835
  });
37014
37836
 
37015
37837
  // src/commands/gsc/sites.ts
37016
- import { defineCommand as defineCommand126 } from "citty";
37838
+ import { defineCommand as defineCommand127 } from "citty";
37017
37839
  registerSchema({
37018
37840
  command: "gsc.sites",
37019
37841
  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.",
@@ -37029,7 +37851,7 @@ function siteHints(sites) {
37029
37851
  resources: sites.map((site) => ({ id: site.siteUrl, label: site.permissionLevel }))
37030
37852
  });
37031
37853
  }
37032
- var sitesCommand = defineCommand126({
37854
+ var sitesCommand = defineCommand127({
37033
37855
  meta: {
37034
37856
  name: "sites",
37035
37857
  description: `List verified Search Console sites.
@@ -37077,7 +37899,7 @@ Examples:
37077
37899
  });
37078
37900
 
37079
37901
  // src/commands/gsc/index.ts
37080
- var gscCommand = defineCommand127({
37902
+ var gscCommand = defineCommand128({
37081
37903
  meta: {
37082
37904
  name: "gsc",
37083
37905
  description: `Google Search Console commands. PPC-SEO arbitrage, brand halo analysis, negative keyword discovery.
@@ -37101,7 +37923,7 @@ Full guide: __tooling__/docs/tools/baker/gsc.md`
37101
37923
  });
37102
37924
 
37103
37925
  // src/commands/history/index.ts
37104
- import { defineCommand as defineCommand128 } from "citty";
37926
+ import { defineCommand as defineCommand129 } from "citty";
37105
37927
  registerSchema({
37106
37928
  command: "history.list",
37107
37929
  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.",
@@ -37156,7 +37978,7 @@ function parseBoundedInt2(raw, name, min, max) {
37156
37978
  }
37157
37979
  return value;
37158
37980
  }
37159
- var listCommand13 = defineCommand128({
37981
+ var listCommand13 = defineCommand129({
37160
37982
  meta: {
37161
37983
  name: "list",
37162
37984
  description: "List recent account changes (unified audit log), newest first."
@@ -37202,7 +38024,7 @@ var listCommand13 = defineCommand128({
37202
38024
  }
37203
38025
  }
37204
38026
  });
37205
- var historyCommand = defineCommand128({
38027
+ var historyCommand = defineCommand129({
37206
38028
  meta: {
37207
38029
  name: "history",
37208
38030
  description: `Unified account history (audit log): what changed, who did it, and when.
@@ -37212,7 +38034,7 @@ Full guide: __tooling__/docs/tools/baker/history.md`
37212
38034
  });
37213
38035
 
37214
38036
  // src/commands/hubspot/index.ts
37215
- import { defineCommand as defineCommand129 } from "citty";
38037
+ import { defineCommand as defineCommand130 } from "citty";
37216
38038
  var EMBED_TYPES = ["legacy", "v4", "unknown"];
37217
38039
  function failNotConnected(err) {
37218
38040
  if (err instanceof ApiError && err.code === "FORBIDDEN" && err.message.includes(HUBSPOT_MISSING_GRANT_MARKER)) {
@@ -37366,7 +38188,7 @@ registerSchema({
37366
38188
  }
37367
38189
  }
37368
38190
  });
37369
- var formsListCommand = defineCommand129({
38191
+ var formsListCommand = defineCommand130({
37370
38192
  meta: {
37371
38193
  name: "list",
37372
38194
  description: "List HubSpot forms with embed type and post-submit action. Example: baker hubspot forms list --redirecting-only"
@@ -37411,7 +38233,7 @@ var formsListCommand = defineCommand129({
37411
38233
  }
37412
38234
  }
37413
38235
  });
37414
- var formsViewCommand = defineCommand129({
38236
+ var formsViewCommand = defineCommand130({
37415
38237
  meta: {
37416
38238
  name: "view",
37417
38239
  description: "Show one HubSpot form's fields and configuration. Example: baker hubspot forms view 1a2b3c"
@@ -37463,7 +38285,7 @@ var formsViewCommand = defineCommand129({
37463
38285
  }
37464
38286
  }
37465
38287
  });
37466
- var meetingsListCommand = defineCommand129({
38288
+ var meetingsListCommand = defineCommand130({
37467
38289
  meta: {
37468
38290
  name: "list",
37469
38291
  description: "List HubSpot meeting links (calendars). Example: baker hubspot meetings list"
@@ -37505,7 +38327,7 @@ var meetingsListCommand = defineCommand129({
37505
38327
  }
37506
38328
  }
37507
38329
  });
37508
- var meetingsViewCommand = defineCommand129({
38330
+ var meetingsViewCommand = defineCommand130({
37509
38331
  meta: {
37510
38332
  name: "view",
37511
38333
  description: "Show one HubSpot meeting link's booking fields. Example: baker hubspot meetings view discovery-call"
@@ -37549,7 +38371,7 @@ var meetingsViewCommand = defineCommand129({
37549
38371
  }
37550
38372
  }
37551
38373
  });
37552
- var formsSubmissionsCommand = defineCommand129({
38374
+ var formsSubmissionsCommand = defineCommand130({
37553
38375
  meta: {
37554
38376
  name: "submissions",
37555
38377
  description: "How many leads a form received, and when. Example: baker hubspot forms submissions <formId> --days 30"
@@ -37598,7 +38420,7 @@ var formsSubmissionsCommand = defineCommand129({
37598
38420
  }
37599
38421
  }
37600
38422
  });
37601
- var workflowsListCommand = defineCommand129({
38423
+ var workflowsListCommand = defineCommand130({
37602
38424
  meta: {
37603
38425
  name: "list",
37604
38426
  description: "List HubSpot workflows. Example: baker hubspot workflows list --enabled-only"
@@ -37663,7 +38485,7 @@ function workflowViewHints(workflow) {
37663
38485
  }
37664
38486
  return hints;
37665
38487
  }
37666
- var workflowsViewCommand = defineCommand129({
38488
+ var workflowsViewCommand = defineCommand130({
37667
38489
  meta: {
37668
38490
  name: "view",
37669
38491
  description: "Read one workflow's real configuration \u2014 enrolment, branches in order, and what each step writes. Example: baker hubspot workflows view 121183594 --full"
@@ -37690,7 +38512,7 @@ var workflowsViewCommand = defineCommand129({
37690
38512
  }
37691
38513
  }
37692
38514
  });
37693
- var pipelinesListCommand = defineCommand129({
38515
+ var pipelinesListCommand = defineCommand130({
37694
38516
  meta: {
37695
38517
  name: "list",
37696
38518
  description: "List HubSpot deal pipelines and their stages. Example: baker hubspot pipelines list"
@@ -37707,7 +38529,7 @@ var pipelinesListCommand = defineCommand129({
37707
38529
  }
37708
38530
  }
37709
38531
  });
37710
- var contactsSummaryCommand = defineCommand129({
38532
+ var contactsSummaryCommand = defineCommand130({
37711
38533
  meta: {
37712
38534
  name: "summary",
37713
38535
  description: "Whether recent leads are being worked, as counts. Example: baker hubspot contacts summary --days 30"
@@ -37777,7 +38599,7 @@ function contactLookupHints(data) {
37777
38599
  }
37778
38600
  return hints;
37779
38601
  }
37780
- var contactsLookupCommand = defineCommand129({
38602
+ var contactsLookupCommand = defineCommand130({
37781
38603
  meta: {
37782
38604
  name: "lookup",
37783
38605
  description: "Find one contact by email and see whether it was worked. Example: baker hubspot contacts lookup a@b.com"
@@ -37801,27 +38623,27 @@ var contactsLookupCommand = defineCommand129({
37801
38623
  }
37802
38624
  }
37803
38625
  });
37804
- var contactsCommand = defineCommand129({
38626
+ var contactsCommand = defineCommand130({
37805
38627
  meta: { name: "contacts", description: "Contacts on the connected HubSpot account." },
37806
38628
  subCommands: { summary: contactsSummaryCommand, lookup: contactsLookupCommand }
37807
38629
  });
37808
- var formsCommand = defineCommand129({
38630
+ var formsCommand = defineCommand130({
37809
38631
  meta: { name: "forms", description: "HubSpot forms on the connected account." },
37810
38632
  subCommands: { list: formsListCommand, view: formsViewCommand, submissions: formsSubmissionsCommand }
37811
38633
  });
37812
- var workflowsCommand = defineCommand129({
38634
+ var workflowsCommand = defineCommand130({
37813
38635
  meta: { name: "workflows", description: "HubSpot workflows on the connected account." },
37814
38636
  subCommands: { list: workflowsListCommand, view: workflowsViewCommand }
37815
38637
  });
37816
- var pipelinesCommand = defineCommand129({
38638
+ var pipelinesCommand = defineCommand130({
37817
38639
  meta: { name: "pipelines", description: "HubSpot deal pipelines on the connected account." },
37818
38640
  subCommands: { list: pipelinesListCommand }
37819
38641
  });
37820
- var meetingsCommand = defineCommand129({
38642
+ var meetingsCommand = defineCommand130({
37821
38643
  meta: { name: "meetings", description: "HubSpot meeting links (calendars) on the connected account." },
37822
38644
  subCommands: { list: meetingsListCommand, view: meetingsViewCommand }
37823
38645
  });
37824
- var hubspotCommand = defineCommand129({
38646
+ var hubspotCommand = defineCommand130({
37825
38647
  meta: {
37826
38648
  name: "hubspot",
37827
38649
  description: `Read the connected HubSpot account \u2014 forms, the leads they received, workflows, deal pipelines and
@@ -37859,10 +38681,10 @@ Full guide: __tooling__/docs/tools/baker/hubspot.md`
37859
38681
  });
37860
38682
 
37861
38683
  // src/commands/images/index.ts
37862
- import { defineCommand as defineCommand155 } from "citty";
38684
+ import { defineCommand as defineCommand156 } from "citty";
37863
38685
 
37864
38686
  // src/commands/images/crop.ts
37865
- import { defineCommand as defineCommand130 } from "citty";
38687
+ import { defineCommand as defineCommand131 } from "citty";
37866
38688
 
37867
38689
  // src/lib/image/crop-sprite.ts
37868
38690
  import sharp from "sharp";
@@ -37877,7 +38699,7 @@ function cropSprite(input, region) {
37877
38699
 
37878
38700
  // src/lib/image/io.ts
37879
38701
  import { randomBytes } from "crypto";
37880
- import { glob as fsGlob, readFile as readFile20, rename, stat as stat4, writeFile as writeFile11 } from "fs/promises";
38702
+ import { glob as fsGlob, readFile as readFile21, rename, stat as stat5, writeFile as writeFile11 } from "fs/promises";
37881
38703
  import { dirname as dirname2, extname as extname2, join as join5, resolve as resolve4 } from "path";
37882
38704
  var REMOTE_RE = /^https?:\/\//i;
37883
38705
  var GLOB_RE = /[*?[\]{}]/;
@@ -37910,11 +38732,11 @@ async function readImageBuffer(pathOrUrl) {
37910
38732
  const { buffer } = await fetchExternalBytes(pathOrUrl, { maxBytes: MAX_REMOTE_IMAGE_BYTES });
37911
38733
  return buffer;
37912
38734
  }
37913
- return readFile20(pathOrUrl);
38735
+ return readFile21(pathOrUrl);
37914
38736
  }
37915
- async function isDirectory(path38) {
38737
+ async function isDirectory(path41) {
37916
38738
  try {
37917
- const s = await stat4(path38);
38739
+ const s = await stat5(path41);
37918
38740
  return s.isDirectory();
37919
38741
  } catch {
37920
38742
  return false;
@@ -37984,7 +38806,7 @@ function emitError2(err) {
37984
38806
  }
37985
38807
  process.exit(1);
37986
38808
  }
37987
- var cropCommand = defineCommand130({
38809
+ var cropCommand = defineCommand131({
37988
38810
  meta: {
37989
38811
  name: "crop",
37990
38812
  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"
@@ -38020,7 +38842,7 @@ var cropCommand = defineCommand130({
38020
38842
  });
38021
38843
 
38022
38844
  // src/commands/images/delete.ts
38023
- import { defineCommand as defineCommand131 } from "citty";
38845
+ import { defineCommand as defineCommand132 } from "citty";
38024
38846
  registerSchema({
38025
38847
  command: "images.delete",
38026
38848
  description: "Delete an image by ID",
@@ -38034,7 +38856,7 @@ registerSchema({
38034
38856
  }
38035
38857
  }
38036
38858
  });
38037
- var deleteCommand2 = defineCommand131({
38859
+ var deleteCommand2 = defineCommand132({
38038
38860
  meta: {
38039
38861
  name: "delete",
38040
38862
  description: "Delete an image by ID. Use --dry-run to preview. Example: baker images delete j571abc123 --dry-run"
@@ -38075,7 +38897,7 @@ var deleteCommand2 = defineCommand131({
38075
38897
  });
38076
38898
 
38077
38899
  // src/commands/images/dimensions.ts
38078
- import { defineCommand as defineCommand132 } from "citty";
38900
+ import { defineCommand as defineCommand133 } from "citty";
38079
38901
 
38080
38902
  // src/lib/image/dimensions.ts
38081
38903
  import { imageSize } from "image-size";
@@ -38104,7 +38926,7 @@ registerSchema({
38104
38926
  }
38105
38927
  }
38106
38928
  });
38107
- var dimensionsCommand = defineCommand132({
38929
+ var dimensionsCommand = defineCommand133({
38108
38930
  meta: {
38109
38931
  name: "dimensions",
38110
38932
  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"
@@ -38160,7 +38982,7 @@ var dimensionsCommand = defineCommand132({
38160
38982
  });
38161
38983
 
38162
38984
  // src/commands/images/download.ts
38163
- import { defineCommand as defineCommand133 } from "citty";
38985
+ import { defineCommand as defineCommand134 } from "citty";
38164
38986
 
38165
38987
  // src/commands/images/downloadPaths.ts
38166
38988
  import { basename as basename2, extname as extname3, join as join6 } from "path";
@@ -38216,13 +39038,13 @@ function resolveDownloadPath({ baseName, extension, out, outIsDirectory: outIsDi
38216
39038
  }
38217
39039
  function disambiguate(paths) {
38218
39040
  const taken = /* @__PURE__ */ new Set();
38219
- return paths.map((path38) => {
38220
- if (!taken.has(path38)) {
38221
- taken.add(path38);
38222
- return path38;
39041
+ return paths.map((path41) => {
39042
+ if (!taken.has(path41)) {
39043
+ taken.add(path41);
39044
+ return path41;
38223
39045
  }
38224
- const ext = extname3(path38);
38225
- const stem = path38.slice(0, path38.length - ext.length);
39046
+ const ext = extname3(path41);
39047
+ const stem = path41.slice(0, path41.length - ext.length);
38226
39048
  let n = 2;
38227
39049
  while (taken.has(`${stem}-${n}${ext}`)) n += 1;
38228
39050
  const unique = `${stem}-${n}${ext}`;
@@ -38349,10 +39171,10 @@ async function runDownloads(plan) {
38349
39171
  const paths = disambiguate(fetched.map((item) => item.path));
38350
39172
  const downloaded = [];
38351
39173
  for (const [index, item] of fetched.entries()) {
38352
- const path38 = paths[index] ?? item.path;
39174
+ const path41 = paths[index] ?? item.path;
38353
39175
  try {
38354
- await atomicWrite(path38, item.buffer);
38355
- downloaded.push({ input: item.input, output: path38, bytes: item.buffer.length, contentType: item.contentType });
39176
+ await atomicWrite(path41, item.buffer);
39177
+ downloaded.push({ input: item.input, output: path41, bytes: item.buffer.length, contentType: item.contentType });
38356
39178
  } catch (err) {
38357
39179
  failed.push({ input: item.input, error: failureMessage(err, "Write failed") });
38358
39180
  }
@@ -38385,7 +39207,7 @@ function emitError3(err) {
38385
39207
  writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
38386
39208
  process.exit(1);
38387
39209
  }
38388
- var downloadCommand = defineCommand133({
39210
+ var downloadCommand = defineCommand134({
38389
39211
  meta: {
38390
39212
  name: "download",
38391
39213
  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"
@@ -38418,7 +39240,7 @@ var downloadCommand = defineCommand133({
38418
39240
  });
38419
39241
 
38420
39242
  // src/commands/images/extract.ts
38421
- import { defineCommand as defineCommand134 } from "citty";
39243
+ import { defineCommand as defineCommand135 } from "citty";
38422
39244
 
38423
39245
  // src/commands/images/autoIngest.ts
38424
39246
  var AUTO_INGEST_MAX = {
@@ -38465,7 +39287,7 @@ registerSchema({
38465
39287
  }
38466
39288
  }
38467
39289
  });
38468
- var extractCommand = defineCommand134({
39290
+ var extractCommand = defineCommand135({
38469
39291
  meta: {
38470
39292
  name: "extract",
38471
39293
  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"
@@ -38520,7 +39342,7 @@ var extractCommand = defineCommand134({
38520
39342
  });
38521
39343
 
38522
39344
  // src/commands/images/find.ts
38523
- import { defineCommand as defineCommand135 } from "citty";
39345
+ import { defineCommand as defineCommand136 } from "citty";
38524
39346
 
38525
39347
  // src/commands/images/providerHits.ts
38526
39348
  function asRecord3(value) {
@@ -38658,7 +39480,7 @@ registerSchema({
38658
39480
  full: { type: "boolean", description: "Include full metadata", required: false, default: false }
38659
39481
  }
38660
39482
  });
38661
- var findCommand = defineCommand135({
39483
+ var findCommand = defineCommand136({
38662
39484
  meta: {
38663
39485
  name: "find",
38664
39486
  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"
@@ -38731,7 +39553,7 @@ var findCommand = defineCommand135({
38731
39553
  });
38732
39554
 
38733
39555
  // src/commands/images/get.ts
38734
- import { defineCommand as defineCommand136 } from "citty";
39556
+ import { defineCommand as defineCommand137 } from "citty";
38735
39557
  registerSchema({
38736
39558
  command: "images.get",
38737
39559
  description: "Get a single image by ID",
@@ -38739,7 +39561,7 @@ registerSchema({
38739
39561
  id: { type: "string", description: "Image ID", required: true }
38740
39562
  }
38741
39563
  });
38742
- var getCommand3 = defineCommand136({
39564
+ var getCommand3 = defineCommand137({
38743
39565
  meta: { name: "get", description: "Get a single image by ID. Example: baker images get j571abc123" },
38744
39566
  args: {
38745
39567
  id: { type: "positional", description: "Image ID", required: false },
@@ -38775,7 +39597,7 @@ var getCommand3 = defineCommand136({
38775
39597
  });
38776
39598
 
38777
39599
  // src/commands/images/gif.ts
38778
- import { defineCommand as defineCommand137 } from "citty";
39600
+ import { defineCommand as defineCommand138 } from "citty";
38779
39601
  registerSchema({
38780
39602
  command: "images.gif",
38781
39603
  description: "Search Giphy for GIFs / reaction memes (paid social creative).",
@@ -38807,7 +39629,7 @@ registerSchema({
38807
39629
  }
38808
39630
  }
38809
39631
  });
38810
- var gifCommand = defineCommand137({
39632
+ var gifCommand = defineCommand138({
38811
39633
  meta: {
38812
39634
  name: "gif",
38813
39635
  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"
@@ -38854,7 +39676,7 @@ var gifCommand = defineCommand137({
38854
39676
  });
38855
39677
 
38856
39678
  // src/commands/images/google.ts
38857
- import { defineCommand as defineCommand138 } from "citty";
39679
+ import { defineCommand as defineCommand139 } from "citty";
38858
39680
  var GOOGLE_ERROR_FIX = {
38859
39681
  action: "use_different_resource",
38860
39682
  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."
@@ -38894,7 +39716,7 @@ registerSchema({
38894
39716
  }
38895
39717
  }
38896
39718
  });
38897
- var googleCommand2 = defineCommand138({
39719
+ var googleCommand2 = defineCommand139({
38898
39720
  meta: {
38899
39721
  name: "google",
38900
39722
  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"
@@ -38967,7 +39789,7 @@ var googleCommand2 = defineCommand138({
38967
39789
  });
38968
39790
 
38969
39791
  // src/commands/images/group.ts
38970
- import { defineCommand as defineCommand139 } from "citty";
39792
+ import { defineCommand as defineCommand140 } from "citty";
38971
39793
 
38972
39794
  // src/commands/mediaGroup.ts
38973
39795
  async function runMediaGroupLookup(input) {
@@ -39020,7 +39842,7 @@ registerSchema({
39020
39842
  "group-key": { type: "string", description: "The set key directly, when you already have it", required: false }
39021
39843
  }
39022
39844
  });
39023
- var groupCommand = defineCommand139({
39845
+ var groupCommand = defineCommand140({
39024
39846
  meta: {
39025
39847
  name: "group",
39026
39848
  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>"
@@ -39040,7 +39862,7 @@ var groupCommand = defineCommand139({
39040
39862
  });
39041
39863
 
39042
39864
  // src/commands/images/icon.ts
39043
- import { defineCommand as defineCommand140 } from "citty";
39865
+ import { defineCommand as defineCommand141 } from "citty";
39044
39866
 
39045
39867
  // src/commands/images/brandVerification.ts
39046
39868
  function brandToken(domain) {
@@ -39137,7 +39959,7 @@ registerSchema({
39137
39959
  full: { type: "boolean", description: "Include full metadata", required: false, default: false }
39138
39960
  }
39139
39961
  });
39140
- var iconCommand = defineCommand140({
39962
+ var iconCommand = defineCommand141({
39141
39963
  meta: {
39142
39964
  name: "icon",
39143
39965
  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'"
@@ -39207,7 +40029,7 @@ var iconCommand = defineCommand140({
39207
40029
  });
39208
40030
 
39209
40031
  // src/commands/images/ingest.ts
39210
- import { defineCommand as defineCommand141 } from "citty";
40032
+ import { defineCommand as defineCommand142 } from "citty";
39211
40033
  var SOURCE_VALUES = imageSourceSchema.options.join(" | ");
39212
40034
  registerSchema({
39213
40035
  command: "images.ingest",
@@ -39222,7 +40044,7 @@ registerSchema({
39222
40044
  fields: { type: "string", description: "Comma-separated field names to include", required: false }
39223
40045
  }
39224
40046
  });
39225
- var ingestCommand = defineCommand141({
40047
+ var ingestCommand = defineCommand142({
39226
40048
  meta: {
39227
40049
  name: "ingest",
39228
40050
  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"
@@ -39291,7 +40113,7 @@ var ingestCommand = defineCommand141({
39291
40113
  });
39292
40114
 
39293
40115
  // src/commands/images/layerize.ts
39294
- import { defineCommand as defineCommand142 } from "citty";
40116
+ import { defineCommand as defineCommand143 } from "citty";
39295
40117
  registerSchema({
39296
40118
  command: "images.layerize",
39297
40119
  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.",
@@ -39355,7 +40177,7 @@ async function pollUntilSettled(imageId, maxWait) {
39355
40177
  }
39356
40178
  return null;
39357
40179
  }
39358
- var layerizeCommand = defineCommand142({
40180
+ var layerizeCommand = defineCommand143({
39359
40181
  meta: {
39360
40182
  name: "layerize",
39361
40183
  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'"
@@ -39424,7 +40246,7 @@ registerSchema({
39424
40246
  full: { type: "boolean", description: "Include geometry and typography for every layer", required: false }
39425
40247
  }
39426
40248
  });
39427
- var layersCommand = defineCommand142({
40249
+ var layersCommand = defineCommand143({
39428
40250
  meta: {
39429
40251
  name: "layers",
39430
40252
  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"
@@ -39464,7 +40286,7 @@ var layersCommand = defineCommand142({
39464
40286
  });
39465
40287
 
39466
40288
  // src/commands/images/library.ts
39467
- import { defineCommand as defineCommand143 } from "citty";
40289
+ import { defineCommand as defineCommand144 } from "citty";
39468
40290
  registerSchema({
39469
40291
  command: "images.library",
39470
40292
  description: "Search the company image library. Returns only ready images.",
@@ -39490,7 +40312,7 @@ registerSchema({
39490
40312
  }
39491
40313
  }
39492
40314
  });
39493
- var libraryCommand = defineCommand143({
40315
+ var libraryCommand = defineCommand144({
39494
40316
  meta: {
39495
40317
  name: "library",
39496
40318
  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"
@@ -39553,7 +40375,7 @@ var libraryCommand = defineCommand143({
39553
40375
  });
39554
40376
 
39555
40377
  // src/commands/images/logo.ts
39556
- import { defineCommand as defineCommand144 } from "citty";
40378
+ import { defineCommand as defineCommand145 } from "citty";
39557
40379
  registerSchema({
39558
40380
  command: "images.logo",
39559
40381
  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.",
@@ -39581,7 +40403,7 @@ registerSchema({
39581
40403
  full: { type: "boolean", description: "Include full metadata", required: false, default: false }
39582
40404
  }
39583
40405
  });
39584
- var logoCommand = defineCommand144({
40406
+ var logoCommand = defineCommand145({
39585
40407
  meta: {
39586
40408
  name: "logo",
39587
40409
  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"
@@ -39654,7 +40476,7 @@ var logoCommand = defineCommand144({
39654
40476
  });
39655
40477
 
39656
40478
  // src/commands/images/normalize.ts
39657
- import { defineCommand as defineCommand145 } from "citty";
40479
+ import { defineCommand as defineCommand146 } from "citty";
39658
40480
 
39659
40481
  // src/lib/image/color-changer.ts
39660
40482
  import quantize from "quantize";
@@ -40386,7 +41208,7 @@ function coerceRawArgs(args) {
40386
41208
  "dry-run": bool(args["dry-run"])
40387
41209
  };
40388
41210
  }
40389
- var normalizeCommand2 = defineCommand145({
41211
+ var normalizeCommand2 = defineCommand146({
40390
41212
  meta: {
40391
41213
  name: "normalize",
40392
41214
  description: `Normalize logos / images: declarative recolor + bg removal + trim + resize. Operates on local files; writes in-place by default.
@@ -40441,7 +41263,7 @@ Examples:
40441
41263
  });
40442
41264
 
40443
41265
  // src/commands/images/pinterest.ts
40444
- import { defineCommand as defineCommand146 } from "citty";
41266
+ import { defineCommand as defineCommand147 } from "citty";
40445
41267
  registerSchema({
40446
41268
  command: "images.pinterest",
40447
41269
  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.",
@@ -40461,7 +41283,7 @@ registerSchema({
40461
41283
  }
40462
41284
  }
40463
41285
  });
40464
- var pinterestCommand = defineCommand146({
41286
+ var pinterestCommand = defineCommand147({
40465
41287
  meta: {
40466
41288
  name: "pinterest",
40467
41289
  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'"
@@ -40518,7 +41340,7 @@ var pinterestCommand = defineCommand146({
40518
41340
  });
40519
41341
 
40520
41342
  // src/commands/images/screenshot.ts
40521
- import { defineCommand as defineCommand147 } from "citty";
41343
+ import { defineCommand as defineCommand148 } from "citty";
40522
41344
  registerSchema({
40523
41345
  command: "images.screenshot",
40524
41346
  description: "Capture a website screenshot via ScreenshotOne. Auto-ingests on success.",
@@ -40537,7 +41359,7 @@ registerSchema({
40537
41359
  full: { type: "boolean", description: "Include full metadata", required: false, default: false }
40538
41360
  }
40539
41361
  });
40540
- var screenshotCommand = defineCommand147({
41362
+ var screenshotCommand = defineCommand148({
40541
41363
  meta: {
40542
41364
  name: "screenshot",
40543
41365
  description: "Screenshot a URL via ScreenshotOne. $0.009/capture. Auto-ingests to library.\n\nExample: baker images screenshot https://stripe.com --full-page"
@@ -40601,7 +41423,7 @@ var screenshotCommand = defineCommand147({
40601
41423
  });
40602
41424
 
40603
41425
  // src/commands/images/search.ts
40604
- import { defineCommand as defineCommand148 } from "citty";
41426
+ import { defineCommand as defineCommand149 } from "citty";
40605
41427
  registerSchema({
40606
41428
  command: "images.search",
40607
41429
  description: "Search images by text query. Only returns ready images.",
@@ -40617,7 +41439,7 @@ registerSchema({
40617
41439
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
40618
41440
  }
40619
41441
  });
40620
- var searchCommand = defineCommand148({
41442
+ var searchCommand = defineCommand149({
40621
41443
  meta: {
40622
41444
  name: "search",
40623
41445
  description: "Semantic search images by text query. Uses hybrid BM25 + vector + reranking. Example: baker images search 'hero banner' --aspect-ratio 16:9 --tags logo"
@@ -40677,7 +41499,7 @@ var searchCommand = defineCommand148({
40677
41499
  });
40678
41500
 
40679
41501
  // src/commands/images/sticker.ts
40680
- import { defineCommand as defineCommand149 } from "citty";
41502
+ import { defineCommand as defineCommand150 } from "citty";
40681
41503
  registerSchema({
40682
41504
  command: "images.sticker",
40683
41505
  description: "Search Giphy stickers \u2014 transparent-background overlays for ad creative.",
@@ -40709,7 +41531,7 @@ registerSchema({
40709
41531
  }
40710
41532
  }
40711
41533
  });
40712
- var stickerCommand = defineCommand149({
41534
+ var stickerCommand = defineCommand150({
40713
41535
  meta: {
40714
41536
  name: "sticker",
40715
41537
  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"
@@ -40756,7 +41578,7 @@ var stickerCommand = defineCommand149({
40756
41578
  });
40757
41579
 
40758
41580
  // src/commands/images/stock.ts
40759
- import { defineCommand as defineCommand150 } from "citty";
41581
+ import { defineCommand as defineCommand151 } from "citty";
40760
41582
  var STOCK_ERROR_FIX = {
40761
41583
  action: "use_different_resource",
40762
41584
  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."
@@ -40833,7 +41655,7 @@ function buildStockRequest(query, args) {
40833
41655
  if (args.context) body.descriptionContext = args.context;
40834
41656
  return body;
40835
41657
  }
40836
- var stockCommand = defineCommand150({
41658
+ var stockCommand = defineCommand151({
40837
41659
  meta: {
40838
41660
  name: "stock",
40839
41661
  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"
@@ -40906,7 +41728,7 @@ var stockCommand = defineCommand150({
40906
41728
  });
40907
41729
 
40908
41730
  // src/lib/tags-command.ts
40909
- import { defineCommand as defineCommand151 } from "citty";
41731
+ import { defineCommand as defineCommand152 } from "citty";
40910
41732
  function makeTagsCommand(command, label, endpoint) {
40911
41733
  registerSchema({
40912
41734
  command: `${command}.tags`,
@@ -40915,7 +41737,7 @@ function makeTagsCommand(command, label, endpoint) {
40915
41737
  output: { type: "string", description: "Output format: md|json", required: false, default: "md" }
40916
41738
  }
40917
41739
  });
40918
- return defineCommand151({
41740
+ return defineCommand152({
40919
41741
  meta: {
40920
41742
  name: "tags",
40921
41743
  description: `List the available ${label} tag names (defaults + company custom tags). Use before filtering with --tags. Example: baker ${command} tags`
@@ -40951,7 +41773,7 @@ function makeTagsCommand(command, label, endpoint) {
40951
41773
  var tagsCommand3 = makeTagsCommand("images", "image", "/api/images/tags");
40952
41774
 
40953
41775
  // src/commands/images/upload.ts
40954
- import { defineCommand as defineCommand152 } from "citty";
41776
+ import { defineCommand as defineCommand153 } from "citty";
40955
41777
  registerSchema({
40956
41778
  command: "images.upload",
40957
41779
  description: "Upload an image to the library \u2014 local file path or remote http(s) URL.",
@@ -40989,7 +41811,7 @@ registerSchema({
40989
41811
  function isRemoteUrl2(value) {
40990
41812
  return /^https?:\/\//i.test(value);
40991
41813
  }
40992
- var uploadCommand = defineCommand152({
41814
+ var uploadCommand = defineCommand153({
40993
41815
  meta: {
40994
41816
  name: "upload",
40995
41817
  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'"
@@ -41082,7 +41904,7 @@ async function uploadLocal(target, args) {
41082
41904
  }
41083
41905
 
41084
41906
  // src/commands/images/upscale.ts
41085
- import { defineCommand as defineCommand153 } from "citty";
41907
+ import { defineCommand as defineCommand154 } from "citty";
41086
41908
  registerSchema({
41087
41909
  command: "images.upscale",
41088
41910
  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).",
@@ -41097,7 +41919,7 @@ registerSchema({
41097
41919
  }
41098
41920
  });
41099
41921
  var POLL_INTERVAL_MS4 = 1500;
41100
- var upscaleCommand = defineCommand153({
41922
+ var upscaleCommand = defineCommand154({
41101
41923
  meta: {
41102
41924
  name: "upscale",
41103
41925
  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"
@@ -41152,7 +41974,7 @@ var upscaleCommand = defineCommand153({
41152
41974
  });
41153
41975
 
41154
41976
  // src/commands/images/use.ts
41155
- import { defineCommand as defineCommand154 } from "citty";
41977
+ import { defineCommand as defineCommand155 } from "citty";
41156
41978
  registerSchema({
41157
41979
  command: "images.use",
41158
41980
  description: "Ingest a URL and wait for the library record to be ready.",
@@ -41181,7 +42003,7 @@ function emitReady(ingestResult, doc, args) {
41181
42003
  args.full === true
41182
42004
  );
41183
42005
  }
41184
- var useCommand = defineCommand154({
42006
+ var useCommand = defineCommand155({
41185
42007
  meta: {
41186
42008
  name: "use",
41187
42009
  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"
@@ -41230,7 +42052,7 @@ var useCommand = defineCommand154({
41230
42052
  });
41231
42053
 
41232
42054
  // src/commands/images/index.ts
41233
- var imagesCommand = defineCommand155({
42055
+ var imagesCommand = defineCommand156({
41234
42056
  meta: {
41235
42057
  name: "images",
41236
42058
  description: `Find, source, and normalize images. Subcommands route by provider so cost + license are explicit.
@@ -41308,12 +42130,12 @@ Full guide: __tooling__/docs/tools/baker/images.md`
41308
42130
  });
41309
42131
 
41310
42132
  // src/commands/landing/index.ts
41311
- import { defineCommand as defineCommand166 } from "citty";
42133
+ import { defineCommand as defineCommand168 } from "citty";
41312
42134
 
41313
42135
  // src/commands/landing/critique.ts
41314
42136
  import { readdir as readdir9, stat as stat6 } from "fs/promises";
41315
- import path28 from "path";
41316
- import { defineCommand as defineCommand156 } from "citty";
42137
+ import path29 from "path";
42138
+ import { defineCommand as defineCommand157 } from "citty";
41317
42139
 
41318
42140
  // src/engine/landing/lib/constants.ts
41319
42141
  var OVERUSED_FONTS = /* @__PURE__ */ new Set([
@@ -42280,13 +43102,13 @@ function describeCounts(findings) {
42280
43102
 
42281
43103
  // src/commands/landing/snapshot.ts
42282
43104
  import { mkdir as mkdir8, rename as rename2, writeFile as writeFile12 } from "fs/promises";
42283
- import path26 from "path";
43105
+ import path27 from "path";
42284
43106
  var CRITIC_VERSION = "2";
42285
43107
  function critiqueCacheDir(projectRoot) {
42286
- return path26.join(projectRoot, ".cache", "landing-critique");
43108
+ return path27.join(projectRoot, ".cache", "landing-critique");
42287
43109
  }
42288
43110
  function snapshotPath(projectRoot, slug) {
42289
- return path26.join(critiqueCacheDir(projectRoot), `${slug}.json`);
43111
+ return path27.join(critiqueCacheDir(projectRoot), `${slug}.json`);
42290
43112
  }
42291
43113
  async function writeCritiqueSnapshot(projectRoot, snapshot) {
42292
43114
  await mkdir8(critiqueCacheDir(projectRoot), { recursive: true });
@@ -42298,30 +43120,26 @@ async function writeCritiqueSnapshot(projectRoot, snapshot) {
42298
43120
  }
42299
43121
 
42300
43122
  // src/commands/landing/source-version.ts
42301
- import { readdir as readdir8, readFile as readFile21, stat as stat5 } from "fs/promises";
42302
- import path27 from "path";
42303
- async function landingSourceRelPaths(landingDir) {
42304
- const rel = [];
42305
- if (await isFile(path27.join(landingDir, "index.astro"))) rel.push("index.astro");
42306
- const componentsDir = path27.join(landingDir, "_components");
42307
- for (const abs of await walkAstro(componentsDir)) {
42308
- rel.push(path27.relative(landingDir, abs).split(path27.sep).join("/"));
42309
- }
42310
- return rel.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
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);
42311
43129
  }
42312
- async function readLandingSources(landingDir) {
42313
- const rel = await landingSourceRelPaths(landingDir);
43130
+ async function readLandingSources(root, slug) {
43131
+ const rel = await landingSourceRelPaths(root, slug);
42314
43132
  const out = [];
42315
- for (const r of rel) out.push({ path: r, text: await readFile21(path27.join(landingDir, r), "utf8") });
43133
+ for (const r of rel) out.push({ path: r, text: await readFile22(path28.join(root, r), "utf8") });
42316
43134
  return out;
42317
43135
  }
42318
- async function computeLandingSourceSha(landingDir) {
42319
- const rel = await landingSourceRelPaths(landingDir);
43136
+ async function computeLandingSourceSha(root, slug) {
43137
+ const rel = await landingSourceRelPaths(root, slug);
42320
43138
  const parts = [];
42321
43139
  for (const r of rel) {
42322
43140
  let bytes;
42323
43141
  try {
42324
- bytes = await readFile21(path27.join(landingDir, r));
43142
+ bytes = await readFile22(path28.join(root, r));
42325
43143
  } catch {
42326
43144
  bytes = Buffer.alloc(0);
42327
43145
  }
@@ -42329,28 +43147,6 @@ async function computeLandingSourceSha(landingDir) {
42329
43147
  }
42330
43148
  return sha256Hex(Buffer.concat(parts));
42331
43149
  }
42332
- async function isFile(p) {
42333
- try {
42334
- return (await stat5(p)).isFile();
42335
- } catch {
42336
- return false;
42337
- }
42338
- }
42339
- async function walkAstro(dir) {
42340
- let entries;
42341
- try {
42342
- entries = await readdir8(dir, { withFileTypes: true });
42343
- } catch {
42344
- return [];
42345
- }
42346
- const out = [];
42347
- for (const entry of entries) {
42348
- const abs = path27.join(dir, entry.name);
42349
- if (entry.isDirectory()) out.push(...await walkAstro(abs));
42350
- else if (entry.isFile() && entry.name.endsWith(".astro")) out.push(abs);
42351
- }
42352
- return out;
42353
- }
42354
43150
 
42355
43151
  // src/commands/landing/critique.ts
42356
43152
  registerSchema({
@@ -42375,14 +43171,14 @@ function parseCritiqueSlugs(args) {
42375
43171
  const all = [args.slug, ...rest].filter((s) => typeof s === "string" && s.length > 0);
42376
43172
  return [...new Set(all.map(String))];
42377
43173
  }
42378
- function fail5(code, message, fix) {
43174
+ function fail6(code, message, fix) {
42379
43175
  process.stderr.write(
42380
43176
  `${JSON.stringify({ ok: false, error: { code, message, ...fix ? { fix } : {} } }, null, 2)}
42381
43177
  `
42382
43178
  );
42383
43179
  process.exit(2);
42384
43180
  }
42385
- var critiqueCommand2 = defineCommand156({
43181
+ var critiqueCommand2 = defineCommand157({
42386
43182
  meta: {
42387
43183
  name: "critique",
42388
43184
  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."
@@ -42400,14 +43196,14 @@ var critiqueCommand2 = defineCommand156({
42400
43196
  const projectRoot = process.cwd();
42401
43197
  for (const slug of slugs) {
42402
43198
  if (!SLUG_RE.test(slug) || slug.includes("..")) {
42403
- fail5(
43199
+ fail6(
42404
43200
  "INVALID_SLUG",
42405
43201
  `"${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).`,
42406
43202
  { availableSlugs: await listLandingSlugs(projectRoot) }
42407
43203
  );
42408
43204
  }
42409
- if (!await isDir(path28.resolve(projectRoot, "src", "pages", slug))) {
42410
- fail5("NOT_FOUND", `No landing at src/pages/${slug}/`, {
43205
+ if (!await isDir(path29.resolve(projectRoot, "src", "pages", slug))) {
43206
+ fail6("NOT_FOUND", `No landing at src/pages/${slug}/`, {
42411
43207
  availableSlugs: await listLandingSlugs(projectRoot)
42412
43208
  });
42413
43209
  }
@@ -42445,8 +43241,10 @@ var critiqueCommand2 = defineCommand156({
42445
43241
  }
42446
43242
  });
42447
43243
  async function critiqueOne(projectRoot, slug, brand) {
42448
- const landingDir = path28.resolve(projectRoot, "src", "pages", slug);
42449
- const [sources, sourceSha] = await Promise.all([readLandingSources(landingDir), computeLandingSourceSha(landingDir)]);
43244
+ const [sources, sourceSha] = await Promise.all([
43245
+ readLandingSources(projectRoot, slug),
43246
+ computeLandingSourceSha(projectRoot, slug)
43247
+ ]);
42450
43248
  const report = critiqueLanding({ slug, sources, brand });
42451
43249
  let snapshotFailed = false;
42452
43250
  try {
@@ -42465,7 +43263,7 @@ async function critiqueOne(projectRoot, slug, brand) {
42465
43263
  }
42466
43264
  async function listLandingSlugs(projectRoot) {
42467
43265
  try {
42468
- const entries = await readdir9(path28.join(projectRoot, "src", "pages"), { withFileTypes: true });
43266
+ const entries = await readdir9(path29.join(projectRoot, "src", "pages"), { withFileTypes: true });
42469
43267
  return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).map((e) => e.name).sort();
42470
43268
  } catch {
42471
43269
  return [];
@@ -42491,10 +43289,10 @@ async function isDir(p) {
42491
43289
  }
42492
43290
 
42493
43291
  // src/commands/landing/inspiration/index.ts
42494
- import { defineCommand as defineCommand165 } from "citty";
43292
+ import { defineCommand as defineCommand166 } from "citty";
42495
43293
 
42496
43294
  // src/commands/landing/inspiration/add.ts
42497
- import { defineCommand as defineCommand157 } from "citty";
43295
+ import { defineCommand as defineCommand158 } from "citty";
42498
43296
 
42499
43297
  // src/commands/landing/inspiration/shared.ts
42500
43298
  var INSPIRATION_HINTS = {
@@ -42576,7 +43374,7 @@ registerSchema({
42576
43374
  note: { type: "string", description: "Why this page is worth keeping", required: false }
42577
43375
  }
42578
43376
  });
42579
- var addCommand = defineCommand157({
43377
+ var addCommand = defineCommand158({
42580
43378
  meta: {
42581
43379
  name: "add",
42582
43380
  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'"
@@ -42617,8 +43415,8 @@ var addCommand = defineCommand157({
42617
43415
 
42618
43416
  // src/commands/landing/inspiration/code.ts
42619
43417
  import { mkdir as mkdir9, writeFile as writeFile13 } from "fs/promises";
42620
- import path29 from "path";
42621
- import { defineCommand as defineCommand158 } from "citty";
43418
+ import path30 from "path";
43419
+ import { defineCommand as defineCommand159 } from "citty";
42622
43420
  registerSchema({
42623
43421
  command: "landing.inspiration.code",
42624
43422
  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.",
@@ -42627,7 +43425,7 @@ registerSchema({
42627
43425
  full: { type: "boolean", description: "Print the markup inline as well as writing it", required: false }
42628
43426
  }
42629
43427
  });
42630
- var codeCommand = defineCommand158({
43428
+ var codeCommand = defineCommand159({
42631
43429
  meta: {
42632
43430
  name: "code",
42633
43431
  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."
@@ -42640,9 +43438,9 @@ var codeCommand = defineCommand158({
42640
43438
  try {
42641
43439
  const id = args.id;
42642
43440
  const data = await apiGet("/api/landing-inspiration/section-code", { id });
42643
- const dir = path29.join(process.cwd(), ".baker", "inspiration", id);
43441
+ const dir = path30.join(process.cwd(), ".baker", "inspiration", id);
42644
43442
  await mkdir9(dir, { recursive: true });
42645
- const file = path29.join(dir, "section.html");
43443
+ const file = path30.join(dir, "section.html");
42646
43444
  await writeFile13(file, data.html);
42647
43445
  const hints = [INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt];
42648
43446
  const fidelity = fidelityHint(data.fidelity);
@@ -42652,7 +43450,7 @@ var codeCommand = defineCommand158({
42652
43450
  ok: true,
42653
43451
  data: {
42654
43452
  id,
42655
- file: path29.relative(process.cwd(), file),
43453
+ file: path30.relative(process.cwd(), file),
42656
43454
  bytes: data.html.length,
42657
43455
  fidelity: data.fidelity,
42658
43456
  reproduction_notes: data.reproductionNotes,
@@ -42673,7 +43471,7 @@ var codeCommand = defineCommand158({
42673
43471
  });
42674
43472
 
42675
43473
  // src/commands/landing/inspiration/favorites.ts
42676
- import { defineCommand as defineCommand159 } from "citty";
43474
+ import { defineCommand as defineCommand160 } from "citty";
42677
43475
  registerSchema({
42678
43476
  command: "landing.inspiration.favorites",
42679
43477
  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.",
@@ -42687,7 +43485,7 @@ registerSchema({
42687
43485
  }
42688
43486
  }
42689
43487
  });
42690
- var favoritesCommand = defineCommand159({
43488
+ var favoritesCommand = defineCommand160({
42691
43489
  meta: {
42692
43490
  name: "favorites",
42693
43491
  description: "List this company's saved reference sections. Example: baker landing inspiration favorites --type hero,pricing"
@@ -42767,7 +43565,7 @@ registerSchema({
42767
43565
  note: { type: "string", description: "Why this is worth keeping", required: false }
42768
43566
  }
42769
43567
  });
42770
- var favoriteCommand = defineCommand159({
43568
+ var favoriteCommand = defineCommand160({
42771
43569
  meta: {
42772
43570
  name: "favorite",
42773
43571
  description: "Save a reference section to this company. Example: baker landing inspiration favorite k57abc\u2026"
@@ -42805,7 +43603,7 @@ registerSchema({
42805
43603
  page: { type: "boolean", description: "Treat the id as a page rather than a section", required: false }
42806
43604
  }
42807
43605
  });
42808
- var unfavoriteCommand = defineCommand159({
43606
+ var unfavoriteCommand = defineCommand160({
42809
43607
  meta: {
42810
43608
  name: "unfavorite",
42811
43609
  description: "Remove a reference section from this company's saved set. Example: baker landing inspiration unfavorite k57abc\u2026"
@@ -42827,7 +43625,7 @@ var unfavoriteCommand = defineCommand159({
42827
43625
  });
42828
43626
 
42829
43627
  // src/commands/landing/inspiration/page.ts
42830
- import { defineCommand as defineCommand160 } from "citty";
43628
+ import { defineCommand as defineCommand161 } from "citty";
42831
43629
  registerSchema({
42832
43630
  command: "landing.inspiration.page",
42833
43631
  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.",
@@ -42844,7 +43642,7 @@ registerSchema({
42844
43642
  }
42845
43643
  }
42846
43644
  });
42847
- var pageCommand2 = defineCommand160({
43645
+ var pageCommand2 = defineCommand161({
42848
43646
  meta: {
42849
43647
  name: "page",
42850
43648
  description: "Show how a reference page sequences its sections. Example: baker landing inspiration page j91xyz\u2026 \u2014 the blueprint, not the pixels."
@@ -42907,7 +43705,7 @@ var pageCommand2 = defineCommand160({
42907
43705
  });
42908
43706
 
42909
43707
  // src/commands/landing/inspiration/scrape.ts
42910
- import { defineCommand as defineCommand161 } from "citty";
43708
+ import { defineCommand as defineCommand162 } from "citty";
42911
43709
 
42912
43710
  // src/engine/landing-library/proxyFailure.ts
42913
43711
  var PROXY_STATUS = 407;
@@ -43084,7 +43882,7 @@ function classifyCaptureFailure(error) {
43084
43882
 
43085
43883
  // src/engine/landing-library/run.ts
43086
43884
  import { mkdir as mkdir10, writeFile as writeFile15 } from "fs/promises";
43087
- import path31 from "path";
43885
+ import path32 from "path";
43088
43886
 
43089
43887
  // ../proxy/src/preflight.ts
43090
43888
  import http from "http";
@@ -44500,9 +45298,9 @@ async function renderBundleToPng(browser, html, viewportWidth, options = {}) {
44500
45298
 
44501
45299
  // src/engine/landing-library/report.ts
44502
45300
  import { writeFile as writeFile14 } from "fs/promises";
44503
- import path30 from "path";
45301
+ import path31 from "path";
44504
45302
  async function writeCaptureReport(manifest, outDir) {
44505
- const file = path30.join(outDir, "report.html");
45303
+ const file = path31.join(outDir, "report.html");
44506
45304
  await writeFile14(file, renderReport(manifest));
44507
45305
  return file;
44508
45306
  }
@@ -44681,32 +45479,32 @@ async function reproducePage(args) {
44681
45479
  const { browser, page, outDir, pageUrl, livePageShot } = args;
44682
45480
  const built = await buildSectionBundle(page, "body", pageUrl).catch(() => null);
44683
45481
  if (!built) return { bundle: null, fidelity: null };
44684
- await writeFile15(path31.join(outDir, "page.html"), built.html);
45482
+ await writeFile15(path32.join(outDir, "page.html"), built.html);
44685
45483
  const rendered = await renderBundleToPng(browser, built.html, DESKTOP_VIEWPORT.width, {
44686
45484
  wholePage: true,
44687
45485
  timeoutMs: 6e4
44688
45486
  });
44689
45487
  if (!rendered || !livePageShot) return { bundle: "page.html", fidelity: null };
44690
- await writeFile15(path31.join(outDir, "page-rendered.png"), rendered);
45488
+ await writeFile15(path32.join(outDir, "page-rendered.png"), rendered);
44691
45489
  const { score, note } = await scoreFidelity(livePageShot, rendered);
44692
45490
  return { bundle: "page.html", fidelity: score, ...note ? { fidelityNote: note } : {} };
44693
45491
  }
44694
45492
  async function captureOneSection(args) {
44695
45493
  const { browser, page, candidate, sectionsDir, outDir, pageUrl, withCode } = args;
44696
- const dir = path31.join(sectionsDir, String(candidate.index).padStart(2, "0"));
45494
+ const dir = path32.join(sectionsDir, String(candidate.index).padStart(2, "0"));
44697
45495
  await mkdir10(dir, { recursive: true });
44698
45496
  const desktop = await captureSection(page, candidate);
44699
- if (desktop) await writeFile15(path31.join(dir, "desktop.png"), desktop);
45497
+ if (desktop) await writeFile15(path32.join(dir, "desktop.png"), desktop);
44700
45498
  const visualHash = desktop ? await perceptualHash(desktop) : null;
44701
45499
  const motion = await collectMotion(page, candidate.selector);
44702
45500
  const built = withCode ? await buildSectionBundle(page, candidate.selector, pageUrl) : null;
44703
45501
  let fidelity = null;
44704
45502
  let fidelityNote;
44705
45503
  if (built) {
44706
- await writeFile15(path31.join(dir, "section.html"), built.html);
45504
+ await writeFile15(path32.join(dir, "section.html"), built.html);
44707
45505
  const rendered = await renderBundleToPng(browser, built.html, DESKTOP_VIEWPORT.width);
44708
45506
  if (rendered && desktop) {
44709
- await writeFile15(path31.join(dir, "section-rendered.png"), rendered);
45507
+ await writeFile15(path32.join(dir, "section-rendered.png"), rendered);
44710
45508
  const result = await scoreFidelity(desktop, rendered);
44711
45509
  fidelity = result.score;
44712
45510
  fidelityNote = result.note;
@@ -44714,9 +45512,9 @@ async function captureOneSection(args) {
44714
45512
  }
44715
45513
  return {
44716
45514
  ...candidate,
44717
- desktopShot: desktop ? path31.relative(outDir, path31.join(dir, "desktop.png")) : null,
45515
+ desktopShot: desktop ? path32.relative(outDir, path32.join(dir, "desktop.png")) : null,
44718
45516
  mobileShot: null,
44719
- bundle: built ? path31.relative(outDir, path31.join(dir, "section.html")) : null,
45517
+ bundle: built ? path32.relative(outDir, path32.join(dir, "section.html")) : null,
44720
45518
  fidelity,
44721
45519
  ...fidelityNote ? { fidelityNote } : {},
44722
45520
  ...built ? { cssStats: built.stats } : {},
@@ -44735,9 +45533,9 @@ async function captureMobileShots(args) {
44735
45533
  for (const section of sections) {
44736
45534
  const shot = await captureSectionOnMobile(mobile.page, section);
44737
45535
  if (!shot) continue;
44738
- const file = path31.join(sectionsDir, String(section.index).padStart(2, "0"), "mobile.png");
45536
+ const file = path32.join(sectionsDir, String(section.index).padStart(2, "0"), "mobile.png");
44739
45537
  await writeFile15(file, shot);
44740
- section.mobileShot = path31.relative(outDir, file);
45538
+ section.mobileShot = path32.relative(outDir, file);
44741
45539
  }
44742
45540
  } finally {
44743
45541
  await mobile.context.close();
@@ -44752,10 +45550,10 @@ async function captureMotionTakes(args) {
44752
45550
  const filmOne = async (section) => {
44753
45551
  const take = await captureMotionTake(browser, pageUrl, section.selector).catch(() => null);
44754
45552
  if (!take) return;
44755
- const dir = path31.join(sectionsDir, String(section.index).padStart(2, "0"));
44756
- const file = path31.join(dir, "motion-filmstrip.png");
45553
+ const dir = path32.join(sectionsDir, String(section.index).padStart(2, "0"));
45554
+ const file = path32.join(dir, "motion-filmstrip.png");
44757
45555
  await writeFile15(file, take.filmstrip);
44758
- section.motionFilmstrip = path31.relative(outDir, file);
45556
+ section.motionFilmstrip = path32.relative(outDir, file);
44759
45557
  log(` [${section.index}] ${section.motion.summary}`);
44760
45558
  };
44761
45559
  const queue = [...moving];
@@ -44812,7 +45610,7 @@ async function captureAlternateViews(args) {
44812
45610
  async function reproduceWholePage(args) {
44813
45611
  const { browser, page, outDir, pageUrl, withCode, log } = args;
44814
45612
  const fullPage = await page.screenshot({ type: "png", fullPage: true }).catch(() => null);
44815
- if (fullPage) await writeFile15(path31.join(outDir, "full-page.png"), fullPage);
45613
+ if (fullPage) await writeFile15(path32.join(outDir, "full-page.png"), fullPage);
44816
45614
  if (!withCode) return { bundle: null, fidelity: null };
44817
45615
  const reproduction = await reproducePage({ browser, page, outDir, pageUrl, livePageShot: fullPage });
44818
45616
  log(`page reproduction: ${reproduction.fidelity === null ? "unavailable" : reproduction.fidelity.toFixed(2)}`);
@@ -44883,7 +45681,7 @@ async function openViaLadder(args) {
44883
45681
  async function scrapeLanding(options) {
44884
45682
  const timeoutMs = options.timeoutMs ?? 45e3;
44885
45683
  const log = options.onProgress ?? (() => void 0);
44886
- const sectionsDir = path31.join(options.outDir, "sections");
45684
+ const sectionsDir = path32.join(options.outDir, "sections");
44887
45685
  const nonPublic = refuseNonPublicUrl(options.url);
44888
45686
  if (nonPublic) {
44889
45687
  throw new BlockedPageError({
@@ -44945,7 +45743,7 @@ async function scrapeLanding(options) {
44945
45743
  security: prepared.security,
44946
45744
  captureTier: tier
44947
45745
  };
44948
- await writeFile15(path31.join(options.outDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
45746
+ await writeFile15(path32.join(options.outDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
44949
45747
  `);
44950
45748
  if (options.report !== false) {
44951
45749
  const reportPath = await writeCaptureReport(manifest, options.outDir);
@@ -44960,28 +45758,28 @@ async function scrapeLanding(options) {
44960
45758
 
44961
45759
  // src/commands/landing/inspiration/captureOut.ts
44962
45760
  import { existsSync as existsSync9 } from "fs";
44963
- import path32 from "path";
45761
+ import path33 from "path";
44964
45762
  var SCRATCH_DIR = ".baker";
44965
45763
  function isWithin(parent, target) {
44966
- const relative = path32.relative(parent, target);
44967
- return relative === "" || !relative.startsWith("..") && !path32.isAbsolute(relative);
45764
+ const relative = path33.relative(parent, target);
45765
+ return relative === "" || !relative.startsWith("..") && !path33.isAbsolute(relative);
44968
45766
  }
44969
45767
  function findRepoRoot(from) {
44970
- let dir = path32.resolve(from);
45768
+ let dir = path33.resolve(from);
44971
45769
  for (; ; ) {
44972
- if (existsSync9(path32.join(dir, ".git"))) return dir;
44973
- const parent = path32.dirname(dir);
45770
+ if (existsSync9(path33.join(dir, ".git"))) return dir;
45771
+ const parent = path33.dirname(dir);
44974
45772
  if (parent === dir) return null;
44975
45773
  dir = parent;
44976
45774
  }
44977
45775
  }
44978
45776
  function checkCaptureOut(out, options) {
44979
45777
  const { cwd, repoRoot } = options;
44980
- const resolved = path32.resolve(cwd, out);
45778
+ const resolved = path33.resolve(cwd, out);
44981
45779
  if (repoRoot === null || !isWithin(repoRoot, resolved)) return { ok: true };
44982
- const scratch = path32.join(repoRoot, SCRATCH_DIR);
45780
+ const scratch = path33.join(repoRoot, SCRATCH_DIR);
44983
45781
  if (isWithin(scratch, resolved)) return { ok: true };
44984
- const suggestion = path32.posix.join(SCRATCH_DIR, "teardowns", path32.basename(resolved) || "capture");
45782
+ const suggestion = path33.posix.join(SCRATCH_DIR, "teardowns", path33.basename(resolved) || "capture");
44985
45783
  return {
44986
45784
  ok: false,
44987
45785
  error: {
@@ -45047,7 +45845,7 @@ registerSchema({
45047
45845
  report: { type: "boolean", description: "Write report.html. `--no-report` to skip", required: false }
45048
45846
  }
45049
45847
  });
45050
- var scrapeCommand = defineCommand161({
45848
+ var scrapeCommand = defineCommand162({
45051
45849
  meta: {
45052
45850
  name: "scrape",
45053
45851
  description: "Capture a landing page to a directory, now. Example: baker landing inspiration scrape https://linear.app --out .baker/inspiration/linear.app"
@@ -45155,12 +45953,12 @@ var scrapeCommand = defineCommand161({
45155
45953
  });
45156
45954
 
45157
45955
  // src/commands/landing/inspiration/search.ts
45158
- import path34 from "path";
45159
- import { defineCommand as defineCommand162 } from "citty";
45956
+ import path35 from "path";
45957
+ import { defineCommand as defineCommand163 } from "citty";
45160
45958
 
45161
45959
  // src/commands/landing/inspiration/shot.ts
45162
45960
  import { mkdir as mkdir11, writeFile as writeFile16 } from "fs/promises";
45163
- import path33 from "path";
45961
+ import path34 from "path";
45164
45962
  import sharp6 from "sharp";
45165
45963
  var READABLE_SHOT = {
45166
45964
  maxWidth: 1440,
@@ -45186,9 +45984,9 @@ async function downloadReadableShot(url, file) {
45186
45984
  const response = await fetch(url);
45187
45985
  if (!response.ok) return null;
45188
45986
  const shot = await toReadableShot(Buffer.from(await response.arrayBuffer()));
45189
- await mkdir11(path33.dirname(file), { recursive: true });
45987
+ await mkdir11(path34.dirname(file), { recursive: true });
45190
45988
  await writeFile16(file, shot);
45191
- return path33.relative(process.cwd(), file);
45989
+ return path34.relative(process.cwd(), file);
45192
45990
  } catch {
45193
45991
  return null;
45194
45992
  }
@@ -45280,20 +46078,20 @@ function buildSearchBody(args) {
45280
46078
  return body;
45281
46079
  }
45282
46080
  async function downloadShots(results) {
45283
- const dir = path34.join(process.cwd(), ".baker", "inspiration");
46081
+ const dir = path35.join(process.cwd(), ".baker", "inspiration");
45284
46082
  const saved = /* @__PURE__ */ new Map();
45285
46083
  await Promise.all(
45286
46084
  results.map(async (result) => {
45287
46085
  const file = await downloadReadableShot(
45288
46086
  result.desktopShotUrl,
45289
- path34.join(dir, `${result.id}.${READABLE_SHOT.extension}`)
46087
+ path35.join(dir, `${result.id}.${READABLE_SHOT.extension}`)
45290
46088
  );
45291
46089
  if (file) saved.set(result.id, file);
45292
46090
  })
45293
46091
  );
45294
46092
  return saved;
45295
46093
  }
45296
- var searchCommand2 = defineCommand162({
46094
+ var searchCommand2 = defineCommand163({
45297
46095
  meta: {
45298
46096
  name: "search",
45299
46097
  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"
@@ -45391,7 +46189,7 @@ var searchCommand2 = defineCommand162({
45391
46189
  });
45392
46190
 
45393
46191
  // src/commands/landing/inspiration/sequences.ts
45394
- import { defineCommand as defineCommand163 } from "citty";
46192
+ import { defineCommand as defineCommand164 } from "citty";
45395
46193
  var COMPACT_TRANSITIONS = 12;
45396
46194
  var COMPACT_ENDS = 5;
45397
46195
  var MAX_PAGES = 50;
@@ -45465,7 +46263,7 @@ function sequencesHints(data, { scope, full }) {
45465
46263
  if (scope === "favorites") hints.push(...favoritesScopeHints(data.favoritesHealth, data.pagesReturned));
45466
46264
  return hints;
45467
46265
  }
45468
- var sequencesCommand = defineCommand163({
46266
+ var sequencesCommand = defineCommand164({
45469
46267
  meta: {
45470
46268
  name: "sequences",
45471
46269
  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."
@@ -45514,8 +46312,8 @@ var sequencesCommand = defineCommand163({
45514
46312
  });
45515
46313
 
45516
46314
  // src/commands/landing/inspiration/view.ts
45517
- import path35 from "path";
45518
- import { defineCommand as defineCommand164 } from "citty";
46315
+ import path36 from "path";
46316
+ import { defineCommand as defineCommand165 } from "citty";
45519
46317
  registerSchema({
45520
46318
  command: "landing.inspiration.view",
45521
46319
  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.",
@@ -45528,7 +46326,7 @@ registerSchema({
45528
46326
  }
45529
46327
  }
45530
46328
  });
45531
- var viewCommand2 = defineCommand164({
46329
+ var viewCommand2 = defineCommand165({
45532
46330
  meta: {
45533
46331
  name: "view",
45534
46332
  description: "Full detail for one reference section. Example: baker landing inspiration view k57abc\u2026 \u2014 read the screenshots it saves before you build."
@@ -45547,12 +46345,12 @@ var viewCommand2 = defineCommand164({
45547
46345
  const id = args.id;
45548
46346
  const data = await apiGet("/api/landing-inspiration/section", { id });
45549
46347
  const section = data.section;
45550
- const dir = path35.join(process.cwd(), ".baker", "inspiration", id);
46348
+ const dir = path36.join(process.cwd(), ".baker", "inspiration", id);
45551
46349
  const ext = READABLE_SHOT.extension;
45552
46350
  const [desktop, mobile, filmstrip] = await Promise.all([
45553
- downloadReadableShot(section.desktopShotUrl, path35.join(dir, `desktop.${ext}`)),
45554
- downloadReadableShot(section.mobileShotUrl, path35.join(dir, `mobile.${ext}`)),
45555
- downloadReadableShot(section.motionFilmstripUrl, path35.join(dir, `motion-filmstrip.${ext}`))
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}`))
45556
46354
  ]);
45557
46355
  const full = args.full;
45558
46356
  const hints = [INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt];
@@ -45612,7 +46410,7 @@ var viewCommand2 = defineCommand164({
45612
46410
  });
45613
46411
 
45614
46412
  // src/commands/landing/inspiration/index.ts
45615
- var inspirationCommand = defineCommand165({
46413
+ var inspirationCommand = defineCommand166({
45616
46414
  meta: {
45617
46415
  name: "inspiration",
45618
46416
  description: `Reference library of real landing-page sections \u2014 look at how good pages actually solve a problem before you design one.
@@ -45656,8 +46454,310 @@ Full guide: __tooling__/docs/tools/baker/landing.md`
45656
46454
  }
45657
46455
  });
45658
46456
 
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
+
45659
46759
  // src/commands/landing/index.ts
45660
- var landingCommand = defineCommand166({
46760
+ var landingCommand = defineCommand168({
45661
46761
  meta: {
45662
46762
  name: "landing",
45663
46763
  description: `Design-quality tools for landing pages (src/pages/<slug>/).
@@ -45666,16 +46766,18 @@ Start here: \`baker landing critique <slug>\` after building or editing a landin
45666
46766
 
45667
46767
  Subcommands:
45668
46768
  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.
45669
46770
  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.`
45670
46771
  },
45671
46772
  subCommands: {
45672
46773
  inspiration: inspirationCommand,
45673
- critique: critiqueCommand2
46774
+ critique: critiqueCommand2,
46775
+ variant: variantCommand
45674
46776
  }
45675
46777
  });
45676
46778
 
45677
46779
  // src/commands/mcp/index.ts
45678
- import { defineCommand as defineCommand167 } from "citty";
46780
+ import { defineCommand as defineCommand169 } from "citty";
45679
46781
 
45680
46782
  // src/commands/mcp/platforms.ts
45681
46783
  function readsKey(label) {
@@ -45730,7 +46832,7 @@ function parseHeaders(raw) {
45730
46832
  }
45731
46833
  return Object.keys(headers).length > 0 ? headers : void 0;
45732
46834
  }
45733
- function fail6(err) {
46835
+ function fail8(err) {
45734
46836
  if (err instanceof ApiError) {
45735
46837
  writeJson({ ok: false, error: { code: err.code, message: err.message } });
45736
46838
  process.exit(1);
@@ -45744,7 +46846,7 @@ registerSchema({
45744
46846
  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.",
45745
46847
  args: {}
45746
46848
  });
45747
- var connectedCommand = defineCommand167({
46849
+ var connectedCommand = defineCommand169({
45748
46850
  meta: {
45749
46851
  name: "connected",
45750
46852
  description: `Everything this chat can reach \u2014 managed integrations, custom MCP servers, and connected platforms.
@@ -45794,7 +46896,7 @@ A tool or platform the user names that is NOT listed anywhere here is simply not
45794
46896
  hints
45795
46897
  });
45796
46898
  } catch (err) {
45797
- fail6(err);
46899
+ fail8(err);
45798
46900
  }
45799
46901
  }
45800
46902
  });
@@ -45803,7 +46905,7 @@ registerSchema({
45803
46905
  description: "List the custom MCP servers this company's chats see (org + company + your own user scope).",
45804
46906
  args: {}
45805
46907
  });
45806
- var listCommand14 = defineCommand167({
46908
+ var listCommand14 = defineCommand169({
45807
46909
  meta: { name: "list", description: "List custom MCP servers visible to this company's chats." },
45808
46910
  run: async () => {
45809
46911
  try {
@@ -45822,7 +46924,7 @@ var listCommand14 = defineCommand167({
45822
46924
  } : {}
45823
46925
  });
45824
46926
  } catch (err) {
45825
- fail6(err);
46927
+ fail8(err);
45826
46928
  }
45827
46929
  }
45828
46930
  });
@@ -45840,7 +46942,7 @@ registerSchema({
45840
46942
  header: { type: "string", description: 'Auth header "Key: Value" (repeatable)', required: false }
45841
46943
  }
45842
46944
  });
45843
- var addCommand2 = defineCommand167({
46945
+ var addCommand2 = defineCommand169({
45844
46946
  meta: {
45845
46947
  name: "add",
45846
46948
  description: `Register a custom MCP server. Tools appear as mcp__<name>__* on the NEXT message.
@@ -45883,7 +46985,7 @@ Examples:
45883
46985
  ]
45884
46986
  });
45885
46987
  } catch (err) {
45886
- fail6(err);
46988
+ fail8(err);
45887
46989
  }
45888
46990
  }
45889
46991
  });
@@ -45892,7 +46994,7 @@ registerSchema({
45892
46994
  description: "Remove a company custom MCP server by name.",
45893
46995
  args: { name: { type: "string", description: "Server name to remove", required: true } }
45894
46996
  });
45895
- var removeCommand4 = defineCommand167({
46997
+ var removeCommand4 = defineCommand169({
45896
46998
  meta: {
45897
46999
  name: "remove",
45898
47000
  description: `Remove a company custom MCP server by name.
@@ -45910,11 +47012,11 @@ Example:
45910
47012
  });
45911
47013
  writeJson({ ok: true, data });
45912
47014
  } catch (err) {
45913
- fail6(err);
47015
+ fail8(err);
45914
47016
  }
45915
47017
  }
45916
47018
  });
45917
- var mcpCommand = defineCommand167({
47019
+ var mcpCommand = defineCommand169({
45918
47020
  meta: {
45919
47021
  name: "mcp",
45920
47022
  description: `Third-party tools for this company \u2014 see what's connected, register custom HTTPS MCP endpoints.
@@ -45940,10 +47042,10 @@ Full guide: __tooling__/docs/tools/baker/mcp.md`
45940
47042
  });
45941
47043
 
45942
47044
  // src/commands/research/index.ts
45943
- import { defineCommand as defineCommand179 } from "citty";
47045
+ import { defineCommand as defineCommand181 } from "citty";
45944
47046
 
45945
47047
  // src/commands/research/advertisers.ts
45946
- import { defineCommand as defineCommand168 } from "citty";
47048
+ import { defineCommand as defineCommand170 } from "citty";
45947
47049
 
45948
47050
  // src/commands/research/hints.ts
45949
47051
  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.';
@@ -46126,7 +47228,7 @@ var FIELDS3 = {
46126
47228
  etv: "Estimated traffic value (USD)",
46127
47229
  visibility: "SERP visibility score (0-1)"
46128
47230
  };
46129
- var advertisersCommand = defineCommand168({
47231
+ var advertisersCommand = defineCommand170({
46130
47232
  meta: {
46131
47233
  name: "advertisers",
46132
47234
  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).
@@ -46182,7 +47284,7 @@ Examples:
46182
47284
  });
46183
47285
 
46184
47286
  // src/commands/research/autocomplete.ts
46185
- import { defineCommand as defineCommand169 } from "citty";
47287
+ import { defineCommand as defineCommand171 } from "citty";
46186
47288
  registerSchema({
46187
47289
  command: "research.autocomplete",
46188
47290
  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).",
@@ -46205,7 +47307,7 @@ registerSchema({
46205
47307
  var FIELDS4 = {
46206
47308
  suggestion: "Autocomplete suggestion from Google"
46207
47309
  };
46208
- var autocompleteCommand = defineCommand169({
47310
+ var autocompleteCommand = defineCommand171({
46209
47311
  meta: {
46210
47312
  name: "autocomplete",
46211
47313
  description: `Get Google Autocomplete suggestions for keyword expansion.
@@ -46260,7 +47362,7 @@ Examples:
46260
47362
  });
46261
47363
 
46262
47364
  // src/commands/research/countries.ts
46263
- import { defineCommand as defineCommand170 } from "citty";
47365
+ import { defineCommand as defineCommand172 } from "citty";
46264
47366
  registerSchema({
46265
47367
  command: "research.countries",
46266
47368
  description: "List all supported country codes for --location flag in research commands.",
@@ -46317,7 +47419,7 @@ var FIELDS5 = {
46317
47419
  code: "Country code to pass as --location",
46318
47420
  name: "Country name"
46319
47421
  };
46320
- var countriesCommand = defineCommand170({
47422
+ var countriesCommand = defineCommand172({
46321
47423
  meta: {
46322
47424
  name: "countries",
46323
47425
  description: "List all supported country codes for --location flag."
@@ -46328,7 +47430,7 @@ var countriesCommand = defineCommand170({
46328
47430
  });
46329
47431
 
46330
47432
  // src/commands/research/fetch.ts
46331
- import { defineCommand as defineCommand171 } from "citty";
47433
+ import { defineCommand as defineCommand173 } from "citty";
46332
47434
  var CONTENT_PREVIEW_CHARS = 2e4;
46333
47435
  var TIMEOUT_MS = 18e4;
46334
47436
  registerSchema({
@@ -46401,7 +47503,7 @@ function fetchFix(code) {
46401
47503
  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."
46402
47504
  };
46403
47505
  }
46404
- var fetchCommand = defineCommand171({
47506
+ var fetchCommand = defineCommand173({
46405
47507
  meta: {
46406
47508
  name: "fetch",
46407
47509
  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.
@@ -46478,7 +47580,7 @@ Examples:
46478
47580
  });
46479
47581
 
46480
47582
  // src/commands/research/intent.ts
46481
- import { defineCommand as defineCommand172 } from "citty";
47583
+ import { defineCommand as defineCommand174 } from "citty";
46482
47584
  registerSchema({
46483
47585
  command: "research.intent",
46484
47586
  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.",
@@ -46501,7 +47603,7 @@ var FIELDS7 = {
46501
47603
  intent: "Primary Google Search intent: informational, navigational, commercial, transactional",
46502
47604
  probability: "Confidence score 0.0-1.0"
46503
47605
  };
46504
- var intentCommand = defineCommand172({
47606
+ var intentCommand = defineCommand174({
46505
47607
  meta: {
46506
47608
  name: "intent",
46507
47609
  description: `Classify Google Search intent for keywords. Returns intent type and confidence.
@@ -46549,7 +47651,7 @@ Examples:
46549
47651
  });
46550
47652
 
46551
47653
  // src/commands/research/keyword-gap.ts
46552
- import { defineCommand as defineCommand173 } from "citty";
47654
+ import { defineCommand as defineCommand175 } from "citty";
46553
47655
  registerSchema({
46554
47656
  command: "research.keyword-gap",
46555
47657
  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.",
@@ -46578,7 +47680,7 @@ var FIELDS8 = {
46578
47680
  cpc: "Cost per click USD",
46579
47681
  their_position: "Competitor's ranking position"
46580
47682
  };
46581
- var keywordGapCommand = defineCommand173({
47683
+ var keywordGapCommand = defineCommand175({
46582
47684
  meta: {
46583
47685
  name: "keyword-gap",
46584
47686
  description: `Find keywords a competitor has that you don't. Supports pagination via --offset.
@@ -46653,7 +47755,7 @@ Examples:
46653
47755
  });
46654
47756
 
46655
47757
  // src/commands/research/keywords-for-site.ts
46656
- import { defineCommand as defineCommand174 } from "citty";
47758
+ import { defineCommand as defineCommand176 } from "citty";
46657
47759
  registerSchema({
46658
47760
  command: "research.keywords-for-site",
46659
47761
  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.",
@@ -46686,7 +47788,7 @@ var FIELDS9 = {
46686
47788
  competition: "LOW, MEDIUM, or HIGH",
46687
47789
  competition_index: "Competition score 0-100"
46688
47790
  };
46689
- var keywordsForSiteCommand = defineCommand174({
47791
+ var keywordsForSiteCommand = defineCommand176({
46690
47792
  meta: {
46691
47793
  name: "keywords-for-site",
46692
47794
  description: `Get keywords a competitor targets in Google. Use --type to filter paid/organic.
@@ -46748,7 +47850,7 @@ Examples:
46748
47850
  });
46749
47851
 
46750
47852
  // src/commands/research/languages.ts
46751
- import { defineCommand as defineCommand175 } from "citty";
47853
+ import { defineCommand as defineCommand177 } from "citty";
46752
47854
  registerSchema({
46753
47855
  command: "research.languages",
46754
47856
  description: "List all supported language codes for --language flag in research commands.",
@@ -46778,7 +47880,7 @@ var FIELDS10 = {
46778
47880
  code: "Language code to pass as --language",
46779
47881
  name: "Language name (also accepted by --language)"
46780
47882
  };
46781
- var languagesCommand2 = defineCommand175({
47883
+ var languagesCommand2 = defineCommand177({
46782
47884
  meta: {
46783
47885
  name: "languages",
46784
47886
  description: "List all supported language codes for --language flag."
@@ -46789,7 +47891,7 @@ var languagesCommand2 = defineCommand175({
46789
47891
  });
46790
47892
 
46791
47893
  // src/commands/research/lighthouse.ts
46792
- import { defineCommand as defineCommand176 } from "citty";
47894
+ import { defineCommand as defineCommand178 } from "citty";
46793
47895
  registerSchema({
46794
47896
  command: "research.lighthouse",
46795
47897
  description: "Landing page performance audit. Returns metrics that affect Google Ads Quality Score and CPC.",
@@ -46808,7 +47910,7 @@ var FIELDS11 = {
46808
47910
  speed_index_ms: "Speed Index in ms (good: < 3400)",
46809
47911
  interactive_ms: "Time to Interactive in ms (good: < 3800)"
46810
47912
  };
46811
- var lighthouseCommand = defineCommand176({
47913
+ var lighthouseCommand = defineCommand178({
46812
47914
  meta: {
46813
47915
  name: "lighthouse",
46814
47916
  description: `Landing page performance audit. Metrics affecting Google Ads Quality Score.
@@ -46846,7 +47948,7 @@ Examples:
46846
47948
  });
46847
47949
 
46848
47950
  // src/commands/research/relevant-pages.ts
46849
- import { defineCommand as defineCommand177 } from "citty";
47951
+ import { defineCommand as defineCommand179 } from "citty";
46850
47952
  registerSchema({
46851
47953
  command: "research.relevant-pages",
46852
47954
  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).",
@@ -46872,7 +47974,7 @@ var FIELDS12 = {
46872
47974
  keywords: "Total organic keywords the page ranks for",
46873
47975
  top_10: "Keywords in positions 1-10"
46874
47976
  };
46875
- var relevantPagesCommand = defineCommand177({
47977
+ var relevantPagesCommand = defineCommand179({
46876
47978
  meta: {
46877
47979
  name: "relevant-pages",
46878
47980
  description: `Get the top pages of a competitor domain with traffic data.
@@ -46919,7 +48021,7 @@ Examples:
46919
48021
  });
46920
48022
 
46921
48023
  // src/commands/research/web.ts
46922
- import { defineCommand as defineCommand178 } from "citty";
48024
+ import { defineCommand as defineCommand180 } from "citty";
46923
48025
  registerSchema({
46924
48026
  command: "research.web",
46925
48027
  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).",
@@ -46970,7 +48072,7 @@ async function runDeepResearch(question) {
46970
48072
  }
46971
48073
  throw new Error("Deep research timed out");
46972
48074
  }
46973
- var webCommand = defineCommand178({
48075
+ var webCommand = defineCommand180({
46974
48076
  meta: {
46975
48077
  name: "web",
46976
48078
  description: `Search the web with AI to answer any open-ended marketing question. Uses live internet data via Google Search.
@@ -47032,7 +48134,7 @@ Examples:
47032
48134
  });
47033
48135
 
47034
48136
  // src/commands/research/index.ts
47035
- var researchCommand = defineCommand179({
48137
+ var researchCommand = defineCommand181({
47036
48138
  meta: {
47037
48139
  name: "research",
47038
48140
  description: `Competitive intelligence and AI-powered research commands.
@@ -47076,10 +48178,10 @@ Full guide: __tooling__/docs/tools/baker/research.md`
47076
48178
  });
47077
48179
 
47078
48180
  // src/commands/scheduled-actions/index.ts
47079
- import { defineCommand as defineCommand187 } from "citty";
48181
+ import { defineCommand as defineCommand189 } from "citty";
47080
48182
 
47081
48183
  // src/commands/scheduled-actions/create.ts
47082
- import { defineCommand as defineCommand180 } from "citty";
48184
+ import { defineCommand as defineCommand182 } from "citty";
47083
48185
 
47084
48186
  // src/commands/scheduled-actions/shared.ts
47085
48187
  var TEMP_SCHEDULED_ACTION_PREFIX = "temp_sched_";
@@ -47226,7 +48328,7 @@ registerSchema({
47226
48328
  }
47227
48329
  }
47228
48330
  });
47229
- var createCommand3 = defineCommand180({
48331
+ var createCommand3 = defineCommand182({
47230
48332
  meta: {
47231
48333
  name: "create",
47232
48334
  description: 'Stage a scheduled action. Example: baker scheduled-actions create --name "Weekly report" --description "..." --cron "0 9 * * MON"'
@@ -47285,7 +48387,7 @@ var createCommand3 = defineCommand180({
47285
48387
  });
47286
48388
 
47287
48389
  // src/commands/scheduled-actions/delete.ts
47288
- import { defineCommand as defineCommand181 } from "citty";
48390
+ import { defineCommand as defineCommand183 } from "citty";
47289
48391
  registerSchema({
47290
48392
  command: "scheduled-actions.delete",
47291
48393
  description: "Stage deletion of a published scheduled action or cancellation of a temp_sched_* draft creation.",
@@ -47293,7 +48395,7 @@ registerSchema({
47293
48395
  id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
47294
48396
  }
47295
48397
  });
47296
- var deleteCommand3 = defineCommand181({
48398
+ var deleteCommand3 = defineCommand183({
47297
48399
  meta: {
47298
48400
  name: "delete",
47299
48401
  description: "Stage scheduled action deletion. Example: baker scheduled-actions delete <id-or-temp_sched_id>"
@@ -47322,7 +48424,7 @@ var deleteCommand3 = defineCommand181({
47322
48424
  });
47323
48425
 
47324
48426
  // src/commands/scheduled-actions/get.ts
47325
- import { defineCommand as defineCommand182 } from "citty";
48427
+ import { defineCommand as defineCommand184 } from "citty";
47326
48428
  registerSchema({
47327
48429
  command: "scheduled-actions.get",
47328
48430
  description: "Get a published scheduled action or a temp_sched_* draft-created scheduled action.",
@@ -47331,7 +48433,7 @@ registerSchema({
47331
48433
  chat: { type: "string", description: CHAT_READ_ARG.description, required: false }
47332
48434
  }
47333
48435
  });
47334
- var getCommand4 = defineCommand182({
48436
+ var getCommand4 = defineCommand184({
47335
48437
  meta: {
47336
48438
  name: "get",
47337
48439
  description: "Get a scheduled action. Example: baker scheduled-actions get <id-or-temp_sched_id>"
@@ -47370,7 +48472,7 @@ var getCommand4 = defineCommand182({
47370
48472
  });
47371
48473
 
47372
48474
  // src/commands/scheduled-actions/list.ts
47373
- import { defineCommand as defineCommand183 } from "citty";
48475
+ import { defineCommand as defineCommand185 } from "citty";
47374
48476
  registerSchema({
47375
48477
  command: "scheduled-actions.list",
47376
48478
  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.",
@@ -47378,7 +48480,7 @@ registerSchema({
47378
48480
  chat: { type: "string", description: CHAT_READ_ARG.description, required: false }
47379
48481
  }
47380
48482
  });
47381
- var listCommand15 = defineCommand183({
48483
+ var listCommand15 = defineCommand185({
47382
48484
  meta: {
47383
48485
  name: "list",
47384
48486
  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."
@@ -47401,9 +48503,9 @@ var listCommand15 = defineCommand183({
47401
48503
  });
47402
48504
 
47403
48505
  // src/commands/scheduled-actions/templates.ts
47404
- import { readFile as readFile22 } from "fs/promises";
47405
- import path36 from "path";
47406
- import { defineCommand as defineCommand184 } from "citty";
48506
+ import { readFile as readFile24 } from "fs/promises";
48507
+ import path39 from "path";
48508
+ import { defineCommand as defineCommand186 } from "citty";
47407
48509
  registerSchema({
47408
48510
  command: "scheduled-actions.templates",
47409
48511
  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.",
@@ -47458,7 +48560,7 @@ registerSchema({
47458
48560
  }
47459
48561
  }
47460
48562
  });
47461
- var templatesCommand = defineCommand184({
48563
+ var templatesCommand = defineCommand186({
47462
48564
  meta: {
47463
48565
  name: "templates",
47464
48566
  description: `The recipes this company can run \u2014 Baker's own plus theirs, with what each one produces.
@@ -47505,7 +48607,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-actions.md`
47505
48607
  }
47506
48608
  if (save.length > 0) {
47507
48609
  const briefFile = flag("brief-file");
47508
- const brief = briefFile.length > 0 ? await readFile22(path36.resolve(briefFile), "utf8") : flag("brief");
48610
+ const brief = briefFile.length > 0 ? await readFile24(path39.resolve(briefFile), "utf8") : flag("brief");
47509
48611
  if (brief.trim().length === 0) {
47510
48612
  failValidation4("--brief-file (preferred) or --brief is required: the brief is the recipe.");
47511
48613
  }
@@ -47550,7 +48652,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-actions.md`
47550
48652
  });
47551
48653
 
47552
48654
  // src/commands/scheduled-actions/trigger.ts
47553
- import { defineCommand as defineCommand185 } from "citty";
48655
+ import { defineCommand as defineCommand187 } from "citty";
47554
48656
  registerSchema({
47555
48657
  command: "scheduled-actions.trigger",
47556
48658
  description: "Immediately trigger a published scheduled action. Does not require BAKER_CHAT_ID and rejects temp_sched_* IDs.",
@@ -47558,7 +48660,7 @@ registerSchema({
47558
48660
  id: { type: "string", description: "Published scheduled action ID", required: true }
47559
48661
  }
47560
48662
  });
47561
- var triggerCommand = defineCommand185({
48663
+ var triggerCommand = defineCommand187({
47562
48664
  meta: {
47563
48665
  name: "trigger",
47564
48666
  description: "Immediately trigger a published scheduled action. Example: baker scheduled-actions trigger <id>"
@@ -47595,7 +48697,7 @@ var triggerCommand = defineCommand185({
47595
48697
  });
47596
48698
 
47597
48699
  // src/commands/scheduled-actions/update.ts
47598
- import { defineCommand as defineCommand186 } from "citty";
48700
+ import { defineCommand as defineCommand188 } from "citty";
47599
48701
  registerSchema({
47600
48702
  command: "scheduled-actions.update",
47601
48703
  description: "Stage an update to a published scheduled action or temp_sched_* draft-created scheduled action.",
@@ -47626,7 +48728,7 @@ registerSchema({
47626
48728
  prompt: { type: "string", description: "Replacement additional spawned-agent instructions", required: false }
47627
48729
  }
47628
48730
  });
47629
- var updateCommand3 = defineCommand186({
48731
+ var updateCommand3 = defineCommand188({
47630
48732
  meta: {
47631
48733
  name: "update",
47632
48734
  description: "Stage a scheduled action update. Examples: baker scheduled-actions update <id> --enabled false | baker scheduled-actions update <id> --mode publish"
@@ -47704,7 +48806,7 @@ var updateCommand3 = defineCommand186({
47704
48806
  });
47705
48807
 
47706
48808
  // src/commands/scheduled-actions/index.ts
47707
- var scheduledActionsCommand = defineCommand187({
48809
+ var scheduledActionsCommand = defineCommand189({
47708
48810
  meta: {
47709
48811
  name: "scheduled-actions",
47710
48812
  description: `Manage Scheduled Actions. Subcommands: list, get, create, update, delete, trigger, templates.
@@ -47733,14 +48835,14 @@ Full guide: __tooling__/docs/tools/baker/scheduled-actions.md`
47733
48835
  });
47734
48836
 
47735
48837
  // src/commands/schema.ts
47736
- import { defineCommand as defineCommand188 } from "citty";
48838
+ import { defineCommand as defineCommand190 } from "citty";
47737
48839
  function narrowToFamily(commandName, available) {
47738
48840
  const segments = commandName.split(".");
47739
48841
  const prefix = segments[0] === "ads" && segments[1] ? `ads.${segments[1]}.` : `${segments[0]}.`;
47740
48842
  const siblings = available.filter((name) => name.startsWith(prefix));
47741
48843
  return siblings.length > 0 ? siblings : available;
47742
48844
  }
47743
- var schemaCommand2 = defineCommand188({
48845
+ var schemaCommand2 = defineCommand190({
47744
48846
  meta: {
47745
48847
  name: "schema",
47746
48848
  description: "Inspect command argument schemas (for AI agent introspection). Lists all commands if no argument given. Example: baker schema images.search"
@@ -47784,10 +48886,10 @@ var schemaCommand2 = defineCommand188({
47784
48886
  });
47785
48887
 
47786
48888
  // src/commands/studio/index.ts
47787
- import { defineCommand as defineCommand197 } from "citty";
48889
+ import { defineCommand as defineCommand199 } from "citty";
47788
48890
 
47789
48891
  // src/commands/studio/animate.ts
47790
- import { defineCommand as defineCommand189 } from "citty";
48892
+ import { defineCommand as defineCommand191 } from "citty";
47791
48893
 
47792
48894
  // src/commands/studio/batch.ts
47793
48895
  function projectBatch(generation, full) {
@@ -47976,7 +49078,7 @@ function parseImageRefs(spec) {
47976
49078
  }
47977
49079
  var defaultDeps = {
47978
49080
  ingest: (url) => apiPost("/api/images/ingest", { url, source: "uploaded" }),
47979
- upload: (path38) => uploadLocalImage({ file: path38, contentType: detectImageContentType(path38), source: "uploaded" })
49081
+ upload: (path41) => uploadLocalImage({ file: path41, contentType: detectImageContentType(path41), source: "uploaded" })
47980
49082
  };
47981
49083
  async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
47982
49084
  const refs = parseImageRefs(spec);
@@ -47996,10 +49098,10 @@ async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
47996
49098
  }
47997
49099
  return { imageIds, added };
47998
49100
  }
47999
- function uploadFailure(path38) {
49101
+ function uploadFailure(path41) {
48000
49102
  return (error) => {
48001
49103
  if (error instanceof ApiError) throw error;
48002
- throw new ApiError("VALIDATION_ERROR", `Could not read "${path38}" as an image.`);
49104
+ throw new ApiError("VALIDATION_ERROR", `Could not read "${path41}" as an image.`);
48003
49105
  };
48004
49106
  }
48005
49107
 
@@ -48238,7 +49340,7 @@ function costHintsFor(body) {
48238
49340
  }
48239
49341
  return hints;
48240
49342
  }
48241
- var animateCommand = defineCommand189({
49343
+ var animateCommand = defineCommand191({
48242
49344
  meta: {
48243
49345
  name: "animate",
48244
49346
  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"
@@ -48357,7 +49459,7 @@ var animateCommand = defineCommand189({
48357
49459
  });
48358
49460
 
48359
49461
  // src/commands/studio/generate.ts
48360
- import { defineCommand as defineCommand190 } from "citty";
49462
+ import { defineCommand as defineCommand192 } from "citty";
48361
49463
  var MODEL_LIST2 = IMAGE_MODEL_IDS;
48362
49464
  var DEFAULT_MAX_WAIT_MS2 = 24e4;
48363
49465
  registerSchema({
@@ -48493,7 +49595,7 @@ function buildGenerateBody(args, prompt) {
48493
49595
  }
48494
49596
  return body;
48495
49597
  }
48496
- var generateCommand = defineCommand190({
49598
+ var generateCommand = defineCommand192({
48497
49599
  meta: {
48498
49600
  name: "generate",
48499
49601
  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]]'"
@@ -48571,7 +49673,7 @@ var generateCommand = defineCommand190({
48571
49673
  });
48572
49674
 
48573
49675
  // src/commands/studio/get.ts
48574
- import { defineCommand as defineCommand191 } from "citty";
49676
+ import { defineCommand as defineCommand193 } from "citty";
48575
49677
  registerSchema({
48576
49678
  command: "studio.get",
48577
49679
  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.",
@@ -48580,7 +49682,7 @@ registerSchema({
48580
49682
  full: { type: "boolean", description: "Include settings, references and attribution", required: false }
48581
49683
  }
48582
49684
  });
48583
- var getCommand5 = defineCommand191({
49685
+ var getCommand5 = defineCommand193({
48584
49686
  meta: {
48585
49687
  name: "get",
48586
49688
  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"
@@ -48609,7 +49711,7 @@ var getCommand5 = defineCommand191({
48609
49711
  });
48610
49712
 
48611
49713
  // src/commands/studio/improve.ts
48612
- import { defineCommand as defineCommand192 } from "citty";
49714
+ import { defineCommand as defineCommand194 } from "citty";
48613
49715
  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.";
48614
49716
  registerSchema({
48615
49717
  command: "studio.improve",
@@ -48634,7 +49736,7 @@ registerSchema({
48634
49736
  }
48635
49737
  }
48636
49738
  });
48637
- var improveCommand = defineCommand192({
49739
+ var improveCommand = defineCommand194({
48638
49740
  meta: {
48639
49741
  name: "improve",
48640
49742
  description: `${DESCRIPTION}
@@ -48678,7 +49780,7 @@ Examples:
48678
49780
  });
48679
49781
 
48680
49782
  // src/commands/studio/keep.ts
48681
- import { defineCommand as defineCommand193 } from "citty";
49783
+ import { defineCommand as defineCommand195 } from "citty";
48682
49784
  registerSchema({
48683
49785
  command: "studio.keep",
48684
49786
  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.",
@@ -48688,7 +49790,7 @@ registerSchema({
48688
49790
  undo: { type: "boolean", description: "Un-star an image, or take a kept clip back out", required: false }
48689
49791
  }
48690
49792
  });
48691
- var keepCommand = defineCommand193({
49793
+ var keepCommand = defineCommand195({
48692
49794
  meta: {
48693
49795
  name: "keep",
48694
49796
  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"
@@ -48739,7 +49841,7 @@ var keepCommand = defineCommand193({
48739
49841
  });
48740
49842
 
48741
49843
  // src/commands/studio/list.ts
48742
- import { defineCommand as defineCommand194 } from "citty";
49844
+ import { defineCommand as defineCommand196 } from "citty";
48743
49845
  registerSchema({
48744
49846
  command: "studio.list",
48745
49847
  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.",
@@ -48750,7 +49852,7 @@ registerSchema({
48750
49852
  full: { type: "boolean", description: "Include settings, references and attribution", required: false }
48751
49853
  }
48752
49854
  });
48753
- var listCommand16 = defineCommand194({
49855
+ var listCommand16 = defineCommand196({
48754
49856
  meta: {
48755
49857
  name: "list",
48756
49858
  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"
@@ -48784,7 +49886,7 @@ var listCommand16 = defineCommand194({
48784
49886
  });
48785
49887
 
48786
49888
  // src/commands/studio/models.ts
48787
- import { defineCommand as defineCommand195 } from "citty";
49889
+ import { defineCommand as defineCommand197 } from "citty";
48788
49890
  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.";
48789
49891
  registerSchema({
48790
49892
  command: "studio.models",
@@ -48871,7 +49973,7 @@ function buildModelCards(kind, model) {
48871
49973
  const selected = model ? ids.filter((id) => id === model) : ids;
48872
49974
  return selected.map((id) => build(id));
48873
49975
  }
48874
- var modelsCommand = defineCommand195({
49976
+ var modelsCommand = defineCommand197({
48875
49977
  meta: {
48876
49978
  name: "models",
48877
49979
  description: `${DESCRIPTION2}
@@ -48918,13 +50020,13 @@ Examples:
48918
50020
  });
48919
50021
 
48920
50022
  // src/commands/studio/skills.ts
48921
- import { defineCommand as defineCommand196 } from "citty";
50023
+ import { defineCommand as defineCommand198 } from "citty";
48922
50024
  registerSchema({
48923
50025
  command: "studio.skills",
48924
50026
  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.",
48925
50027
  args: {}
48926
50028
  });
48927
- var skillsCommand = defineCommand196({
50029
+ var skillsCommand = defineCommand198({
48928
50030
  meta: {
48929
50031
  name: "skills",
48930
50032
  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"
@@ -48948,7 +50050,7 @@ var skillsCommand = defineCommand196({
48948
50050
  });
48949
50051
 
48950
50052
  // src/commands/studio/index.ts
48951
- var studioCommand = defineCommand197({
50053
+ var studioCommand = defineCommand199({
48952
50054
  meta: {
48953
50055
  name: "studio",
48954
50056
  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.
@@ -48991,10 +50093,10 @@ Full guide: __tooling__/docs/tools/baker/studio.md`
48991
50093
  });
48992
50094
 
48993
50095
  // src/commands/tag-manager/index.ts
48994
- import { defineCommand as defineCommand201 } from "citty";
50096
+ import { defineCommand as defineCommand203 } from "citty";
48995
50097
 
48996
50098
  // src/commands/tag-manager/draft.ts
48997
- import { defineCommand as defineCommand198 } from "citty";
50099
+ import { defineCommand as defineCommand200 } from "citty";
48998
50100
 
48999
50101
  // src/commands/tag-manager/shared.ts
49000
50102
  import { readFileSync as readFileSync15 } from "fs";
@@ -49061,10 +50163,10 @@ async function stageOp4(op) {
49061
50163
  handleError5(err);
49062
50164
  }
49063
50165
  }
49064
- async function draftAction3(path38, body, chat) {
50166
+ async function draftAction3(path41, body, chat) {
49065
50167
  const chatId = resolveChatId(chat);
49066
50168
  try {
49067
- const data = await apiPost(path38, { chatId, ...body });
50169
+ const data = await apiPost(path41, { chatId, ...body });
49068
50170
  writeJsonEnvelope({ ok: true, data });
49069
50171
  return data;
49070
50172
  } catch (err) {
@@ -49117,13 +50219,13 @@ registerSchema({
49117
50219
  chat: { type: "string", description: CHAT_READ_ARG.description, required: false }
49118
50220
  }
49119
50221
  });
49120
- var draftCommand4 = defineCommand198({
50222
+ var draftCommand4 = defineCommand200({
49121
50223
  meta: {
49122
50224
  name: "draft",
49123
50225
  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."
49124
50226
  },
49125
50227
  subCommands: {
49126
- list: defineCommand198({
50228
+ list: defineCommand200({
49127
50229
  meta: {
49128
50230
  name: "list",
49129
50231
  description: "Review everything staged on this chat (--json for the raw envelope)"
@@ -49136,7 +50238,7 @@ var draftCommand4 = defineCommand198({
49136
50238
  await draftList2(args.json === true, args.chat);
49137
50239
  }
49138
50240
  }),
49139
- show: defineCommand198({
50241
+ show: defineCommand200({
49140
50242
  meta: {
49141
50243
  name: "show",
49142
50244
  description: "Print the full staged payload for one change \u2014 the receipt to verify it looks right before publish (never truncated)."
@@ -49153,7 +50255,7 @@ var draftCommand4 = defineCommand198({
49153
50255
  );
49154
50256
  }
49155
50257
  }),
49156
- amend: defineCommand198({
50258
+ amend: defineCommand200({
49157
50259
  meta: {
49158
50260
  name: "amend",
49159
50261
  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."
@@ -49170,7 +50272,7 @@ var draftCommand4 = defineCommand198({
49170
50272
  });
49171
50273
  }
49172
50274
  }),
49173
- remove: defineCommand198({
50275
+ remove: defineCommand200({
49174
50276
  meta: { name: "remove", description: "Remove one staged change (cascades to anything depending on it)" },
49175
50277
  args: { ref: { type: "positional", description: "Staged ref (gtm_temp_*) or target", required: false } },
49176
50278
  run: async ({ args }) => {
@@ -49179,7 +50281,7 @@ var draftCommand4 = defineCommand198({
49179
50281
  });
49180
50282
  }
49181
50283
  }),
49182
- clear: defineCommand198({
50284
+ clear: defineCommand200({
49183
50285
  meta: { name: "clear", description: "Discard all Tag Manager changes staged on this chat" },
49184
50286
  run: async () => {
49185
50287
  await draftAction3("/api/tag-manager/draft/clear", {});
@@ -49189,7 +50291,7 @@ var draftCommand4 = defineCommand198({
49189
50291
  });
49190
50292
 
49191
50293
  // src/commands/tag-manager/read.ts
49192
- import { defineCommand as defineCommand199 } from "citty";
50294
+ import { defineCommand as defineCommand201 } from "citty";
49193
50295
  registerSchema({
49194
50296
  command: "tagManager.containers",
49195
50297
  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.",
@@ -49230,7 +50332,7 @@ function containersHints(containers) {
49230
50332
  }))
49231
50333
  });
49232
50334
  }
49233
- var containersCommand = defineCommand199({
50335
+ var containersCommand = defineCommand201({
49234
50336
  meta: {
49235
50337
  name: "containers",
49236
50338
  description: `List Tag Manager containers reachable by this company's connection.
@@ -49247,7 +50349,7 @@ Start here:
49247
50349
  }
49248
50350
  }
49249
50351
  });
49250
- var readCommand = defineCommand199({
50352
+ var readCommand = defineCommand201({
49251
50353
  meta: {
49252
50354
  name: "read",
49253
50355
  description: `Read the current contents of the Tag Manager container \u2014 always do this before staging changes.
@@ -49289,7 +50391,7 @@ Examples:
49289
50391
  });
49290
50392
 
49291
50393
  // src/commands/tag-manager/write-commands.ts
49292
- import { defineCommand as defineCommand200 } from "citty";
50394
+ import { defineCommand as defineCommand202 } from "citty";
49293
50395
  var CONTAINER_ARG_DESCRIPTION = "Numeric container id (optional only when one container is connected \u2014 run `baker tag-manager containers`)";
49294
50396
  var ENTITIES = [
49295
50397
  {
@@ -49345,10 +50447,10 @@ for (const { entity, noun, createHint } of ENTITIES) {
49345
50447
  });
49346
50448
  }
49347
50449
  function entityCommand(entity, noun, example) {
49348
- return defineCommand200({
50450
+ return defineCommand202({
49349
50451
  meta: { name: entity, description: `Stage ${noun} changes on this chat's Tag Manager draft` },
49350
50452
  subCommands: {
49351
- create: defineCommand200({
50453
+ create: defineCommand202({
49352
50454
  meta: {
49353
50455
  name: "create",
49354
50456
  description: `Stage a new ${noun}
@@ -49370,7 +50472,7 @@ Examples:
49370
50472
  });
49371
50473
  }
49372
50474
  }),
49373
- update: defineCommand200({
50475
+ update: defineCommand202({
49374
50476
  meta: {
49375
50477
  name: "update",
49376
50478
  description: `Stage an update to an existing ${noun} (pass its id or path)`
@@ -49390,7 +50492,7 @@ Examples:
49390
50492
  });
49391
50493
  }
49392
50494
  }),
49393
- delete: defineCommand200({
50495
+ delete: defineCommand202({
49394
50496
  meta: { name: "delete", description: `Stage the deletion of a ${noun} (pass its id or path)` },
49395
50497
  args: {
49396
50498
  id: { type: "positional", description: `${noun} id or path`, required: false },
@@ -49431,7 +50533,7 @@ function builtinTypes(args) {
49431
50533
  }
49432
50534
  return raw.split(",").map((entry) => entry.trim());
49433
50535
  }
49434
- var builtinCommand = defineCommand200({
50536
+ var builtinCommand = defineCommand202({
49435
50537
  meta: {
49436
50538
  name: "builtin",
49437
50539
  description: `Enable or disable built-in variables
@@ -49441,7 +50543,7 @@ Examples:
49441
50543
  baker tag-manager builtin disable --types formId`
49442
50544
  },
49443
50545
  subCommands: {
49444
- enable: defineCommand200({
50546
+ enable: defineCommand202({
49445
50547
  meta: { name: "enable", description: "Stage enabling built-in variables" },
49446
50548
  args: {
49447
50549
  types: { type: "string", description: "Comma-separated types", required: false },
@@ -49455,7 +50557,7 @@ Examples:
49455
50557
  });
49456
50558
  }
49457
50559
  }),
49458
- disable: defineCommand200({
50560
+ disable: defineCommand202({
49459
50561
  meta: { name: "disable", description: "Stage disabling built-in variables" },
49460
50562
  args: {
49461
50563
  types: { type: "string", description: "Comma-separated types", required: false },
@@ -49473,7 +50575,7 @@ Examples:
49473
50575
  });
49474
50576
 
49475
50577
  // src/commands/tag-manager/index.ts
49476
- var tagManagerCommand = defineCommand201({
50578
+ var tagManagerCommand = defineCommand203({
49477
50579
  meta: {
49478
50580
  name: "tag-manager",
49479
50581
  description: `Read and change what lives inside the client's Google Tag Manager container \u2014 tags, triggers, variables, folders and built-in variables.
@@ -49510,7 +50612,7 @@ Full guide: __tooling__/docs/tools/baker/tag-manager.md`
49510
50612
  });
49511
50613
 
49512
50614
  // src/commands/tags/index.ts
49513
- import { defineCommand as defineCommand202 } from "citty";
50615
+ import { defineCommand as defineCommand204 } from "citty";
49514
50616
 
49515
50617
  // src/commands/tags/shared.ts
49516
50618
  function failApi3(err) {
@@ -49579,7 +50681,7 @@ async function listTags(json) {
49579
50681
  var listArgs9 = {
49580
50682
  json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable list" }
49581
50683
  };
49582
- var listCommand17 = defineCommand202({
50684
+ var listCommand17 = defineCommand204({
49583
50685
  meta: {
49584
50686
  name: "list",
49585
50687
  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"
@@ -49598,7 +50700,7 @@ async function listDraft3(chat) {
49598
50700
  failApi3(err);
49599
50701
  }
49600
50702
  }
49601
- var draftCommand5 = defineCommand202({
50703
+ var draftCommand5 = defineCommand204({
49602
50704
  meta: {
49603
50705
  name: "draft",
49604
50706
  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."
@@ -49608,7 +50710,7 @@ var draftCommand5 = defineCommand202({
49608
50710
  await listDraft3(args.chat);
49609
50711
  }
49610
50712
  });
49611
- var tagsCommand4 = defineCommand202({
50713
+ var tagsCommand4 = defineCommand204({
49612
50714
  meta: {
49613
50715
  name: "tags",
49614
50716
  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.
@@ -49637,10 +50739,10 @@ Full guide: __tooling__/docs/tools/baker/tags.md`
49637
50739
  });
49638
50740
 
49639
50741
  // src/commands/testimonials/index.ts
49640
- import { defineCommand as defineCommand206 } from "citty";
50742
+ import { defineCommand as defineCommand208 } from "citty";
49641
50743
 
49642
50744
  // src/commands/testimonials/get.ts
49643
- import { defineCommand as defineCommand203 } from "citty";
50745
+ import { defineCommand as defineCommand205 } from "citty";
49644
50746
  registerSchema({
49645
50747
  command: "testimonials.get",
49646
50748
  description: "Get a single testimonial by ID",
@@ -49648,7 +50750,7 @@ registerSchema({
49648
50750
  id: { type: "string", description: "Testimonial ID", required: true }
49649
50751
  }
49650
50752
  });
49651
- var getCommand6 = defineCommand203({
50753
+ var getCommand6 = defineCommand205({
49652
50754
  meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
49653
50755
  args: {
49654
50756
  id: { type: "positional", description: "Testimonial ID", required: false },
@@ -49685,7 +50787,7 @@ var getCommand6 = defineCommand203({
49685
50787
  });
49686
50788
 
49687
50789
  // src/commands/testimonials/list.ts
49688
- import { defineCommand as defineCommand204 } from "citty";
50790
+ import { defineCommand as defineCommand206 } from "citty";
49689
50791
 
49690
50792
  // src/commands/testimonials/emptyCorpusHints.ts
49691
50793
  function resolveEmptyReason({
@@ -49820,7 +50922,7 @@ function buildListParams(args) {
49820
50922
  }
49821
50923
  return params;
49822
50924
  }
49823
- var listCommand18 = defineCommand204({
50925
+ var listCommand18 = defineCommand206({
49824
50926
  meta: {
49825
50927
  name: "list",
49826
50928
  description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
@@ -49872,7 +50974,7 @@ var listCommand18 = defineCommand204({
49872
50974
  });
49873
50975
 
49874
50976
  // src/commands/testimonials/search.ts
49875
- import { defineCommand as defineCommand205 } from "citty";
50977
+ import { defineCommand as defineCommand207 } from "citty";
49876
50978
  var FILTER_FLAGS2 = ["source", "rating-min", "rating-max", "status", "sentiment", "language", "tags"];
49877
50979
  function languageBiasHint(results, requestedLanguage) {
49878
50980
  if (requestedLanguage) {
@@ -49951,7 +51053,7 @@ function buildSearchRequest(query, args) {
49951
51053
  }
49952
51054
  return body;
49953
51055
  }
49954
- var searchCommand3 = defineCommand205({
51056
+ var searchCommand3 = defineCommand207({
49955
51057
  meta: {
49956
51058
  name: "search",
49957
51059
  description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
@@ -50015,7 +51117,7 @@ var searchCommand3 = defineCommand205({
50015
51117
  var tagsCommand5 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
50016
51118
 
50017
51119
  // src/commands/testimonials/index.ts
50018
- var testimonialsCommand = defineCommand206({
51120
+ var testimonialsCommand = defineCommand208({
50019
51121
  meta: {
50020
51122
  name: "testimonials",
50021
51123
  description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
@@ -50037,10 +51139,10 @@ Full guide: __tooling__/docs/tools/baker/testimonials.md`
50037
51139
  });
50038
51140
 
50039
51141
  // src/commands/videos/index.ts
50040
- import { defineCommand as defineCommand213 } from "citty";
51142
+ import { defineCommand as defineCommand215 } from "citty";
50041
51143
 
50042
51144
  // src/commands/videos/delete.ts
50043
- import { defineCommand as defineCommand207 } from "citty";
51145
+ import { defineCommand as defineCommand209 } from "citty";
50044
51146
  registerSchema({
50045
51147
  command: "videos.delete",
50046
51148
  description: "Delete a video by ID",
@@ -50054,7 +51156,7 @@ registerSchema({
50054
51156
  }
50055
51157
  }
50056
51158
  });
50057
- var deleteCommand4 = defineCommand207({
51159
+ var deleteCommand4 = defineCommand209({
50058
51160
  meta: {
50059
51161
  name: "delete",
50060
51162
  description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
@@ -50095,7 +51197,7 @@ var deleteCommand4 = defineCommand207({
50095
51197
  });
50096
51198
 
50097
51199
  // src/commands/videos/get.ts
50098
- import { defineCommand as defineCommand208 } from "citty";
51200
+ import { defineCommand as defineCommand210 } from "citty";
50099
51201
  registerSchema({
50100
51202
  command: "videos.get",
50101
51203
  description: "Get a single video by ID",
@@ -50103,7 +51205,7 @@ registerSchema({
50103
51205
  id: { type: "string", description: "Video ID", required: true }
50104
51206
  }
50105
51207
  });
50106
- var getCommand7 = defineCommand208({
51208
+ var getCommand7 = defineCommand210({
50107
51209
  meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
50108
51210
  args: {
50109
51211
  id: { type: "positional", description: "Video ID", required: false },
@@ -50140,7 +51242,7 @@ var getCommand7 = defineCommand208({
50140
51242
  });
50141
51243
 
50142
51244
  // src/commands/videos/group.ts
50143
- import { defineCommand as defineCommand209 } from "citty";
51245
+ import { defineCommand as defineCommand211 } from "citty";
50144
51246
  registerSchema({
50145
51247
  command: "videos.group",
50146
51248
  description: "List every clip and image that arrived in the same set as this video (carousel slides, one page)",
@@ -50149,7 +51251,7 @@ registerSchema({
50149
51251
  "group-key": { type: "string", description: "The set key directly, when you already have it", required: false }
50150
51252
  }
50151
51253
  });
50152
- var groupCommand2 = defineCommand209({
51254
+ var groupCommand2 = defineCommand211({
50153
51255
  meta: {
50154
51256
  name: "group",
50155
51257
  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>"
@@ -50169,10 +51271,10 @@ var groupCommand2 = defineCommand209({
50169
51271
  });
50170
51272
 
50171
51273
  // src/commands/videos/ingest.ts
50172
- import { mkdtemp as mkdtemp2, rm as rm7, stat as stat7 } from "fs/promises";
51274
+ import { mkdtemp as mkdtemp2, rm as rm7, stat as stat8 } from "fs/promises";
50173
51275
  import { tmpdir as tmpdir3 } from "os";
50174
- import path37 from "path";
50175
- import { defineCommand as defineCommand210 } from "citty";
51276
+ import path40 from "path";
51277
+ import { defineCommand as defineCommand212 } from "citty";
50176
51278
 
50177
51279
  // src/lib/streamUpload.ts
50178
51280
  import { createHash as createHash2 } from "crypto";
@@ -50336,7 +51438,7 @@ registerSchema({
50336
51438
  "dry-run": { type: "boolean", description: "Preview the operation without executing", required: false }
50337
51439
  }
50338
51440
  });
50339
- var ingestCommand2 = defineCommand210({
51441
+ var ingestCommand2 = defineCommand212({
50340
51442
  meta: {
50341
51443
  name: "ingest",
50342
51444
  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"
@@ -50452,35 +51554,35 @@ async function ingestByRoute(args, direct, country) {
50452
51554
  function reportYtDlpFailure(err) {
50453
51555
  const detail = `${err.stderrTail} ${err.message}`;
50454
51556
  if (isProxyFailure(ytDlpBlockSignal(detail))) {
50455
- fail7(
51557
+ fail9(
50456
51558
  "Couldn't download that video: our connection to the internet was refused.",
50457
51559
  "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."
50458
51560
  );
50459
51561
  }
50460
51562
  if (isDrmProtected(detail)) {
50461
- fail7(
51563
+ fail9(
50462
51564
  "That video is copy-protected, so it can't be added to the library.",
50463
51565
  "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>`."
50464
51566
  );
50465
51567
  }
50466
51568
  if (isVimeoAuthFailure(detail)) {
50467
- fail7(
51569
+ fail9(
50468
51570
  "Vimeo wouldn't hand over that video \u2014 Baker isn't signed in to Vimeo.",
50469
51571
  "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>`."
50470
51572
  );
50471
51573
  }
50472
51574
  if (isRegionBlocked(detail)) {
50473
- fail7(
51575
+ fail9(
50474
51576
  `That video isn't available in the region we're fetching from. ${err.stderrTail || err.message}`,
50475
51577
  "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."
50476
51578
  );
50477
51579
  }
50478
- fail7(
51580
+ fail9(
50479
51581
  `Couldn't download that video. ${err.stderrTail || err.message}`,
50480
51582
  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>`."
50481
51583
  );
50482
51584
  }
50483
- function fail7(message, fix, code = "INGEST_FAILED") {
51585
+ function fail9(message, fix, code = "INGEST_FAILED") {
50484
51586
  writeJson({ ok: false, error: { code, message, fix } });
50485
51587
  process.exit(1);
50486
51588
  }
@@ -50492,13 +51594,13 @@ function reportIngestFailure(err) {
50492
51594
  if (err instanceof YtDlpError) reportYtDlpFailure(err);
50493
51595
  const detail = err instanceof Error ? err.message : String(err);
50494
51596
  if (detail.includes("timed out after")) {
50495
- fail7(
51597
+ fail9(
50496
51598
  "That video took too long to download and was stopped part-way.",
50497
51599
  "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>`.",
50498
51600
  "INTERNAL_ERROR"
50499
51601
  );
50500
51602
  }
50501
- fail7(
51603
+ fail9(
50502
51604
  `Couldn't add that video. ${detail}`,
50503
51605
  "This is a fault on Baker's side, not a problem with the link. Report it.",
50504
51606
  "INTERNAL_ERROR"
@@ -50522,7 +51624,7 @@ function ingestUrl(args) {
50522
51624
  }
50523
51625
  async function downloadThenIngest(args, country) {
50524
51626
  const vimeoCookie = captureVimeoCookie();
50525
- const workDir = await mkdtemp2(path37.join(tmpdir3(), "videos-ingest-"));
51627
+ const workDir = await mkdtemp2(path40.join(tmpdir3(), "videos-ingest-"));
50526
51628
  try {
50527
51629
  const probe = await probeYtDlp({ url: args.url, country, vimeoCookie, cookieDir: workDir });
50528
51630
  if (isAudioOnly(probe.info)) {
@@ -50553,7 +51655,7 @@ async function downloadThenIngest(args, country) {
50553
51655
  // we allow to fetch it cannot drift apart.
50554
51656
  timeoutMs: downloadTimeoutMs(durationSeconds(probe.info))
50555
51657
  });
50556
- const stats = await stat7(filePath);
51658
+ const stats = await stat8(filePath);
50557
51659
  if (stats.size > MAX_VIDEO_INGEST_BYTES) {
50558
51660
  throw new ApiError(
50559
51661
  "VALIDATION_ERROR",
@@ -50598,7 +51700,7 @@ async function uploadToAssetStore(filePath, sizeBytes) {
50598
51700
  }
50599
51701
 
50600
51702
  // src/commands/videos/search.ts
50601
- import { defineCommand as defineCommand211 } from "citty";
51703
+ import { defineCommand as defineCommand213 } from "citty";
50602
51704
  registerSchema({
50603
51705
  command: "videos.search",
50604
51706
  description: "Search videos by text query. Only returns ready videos.",
@@ -50608,7 +51710,7 @@ registerSchema({
50608
51710
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
50609
51711
  }
50610
51712
  });
50611
- var searchCommand4 = defineCommand211({
51713
+ var searchCommand4 = defineCommand213({
50612
51714
  meta: {
50613
51715
  name: "search",
50614
51716
  description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
@@ -50658,9 +51760,9 @@ var searchCommand4 = defineCommand211({
50658
51760
  var tagsCommand6 = makeTagsCommand("videos", "video", "/api/videos/tags");
50659
51761
 
50660
51762
  // src/commands/videos/upload.ts
50661
- import { readFile as readFile23, stat as stat8 } from "fs/promises";
51763
+ import { readFile as readFile25, stat as stat9 } from "fs/promises";
50662
51764
  import { basename as basename3, extname as extname4 } from "path";
50663
- import { defineCommand as defineCommand212 } from "citty";
51765
+ import { defineCommand as defineCommand214 } from "citty";
50664
51766
  var MIME_MAP = {
50665
51767
  ".mp4": "video/mp4",
50666
51768
  ".mov": "video/quicktime",
@@ -50702,7 +51804,7 @@ function detectContentType(filePath) {
50702
51804
  function isRemoteUrl3(value) {
50703
51805
  return /^https?:\/\//i.test(value);
50704
51806
  }
50705
- var uploadCommand2 = defineCommand212({
51807
+ var uploadCommand2 = defineCommand214({
50706
51808
  meta: {
50707
51809
  name: "upload",
50708
51810
  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"
@@ -50742,7 +51844,7 @@ var uploadCommand2 = defineCommand212({
50742
51844
  const originalFilename = basename3(filePath);
50743
51845
  const descriptionContext = args.context;
50744
51846
  if (args["dry-run"]) {
50745
- const fileStats = await stat8(filePath);
51847
+ const fileStats = await stat9(filePath);
50746
51848
  writeJson({
50747
51849
  ok: true,
50748
51850
  dryRun: true,
@@ -50755,7 +51857,7 @@ var uploadCommand2 = defineCommand212({
50755
51857
  originalFilename,
50756
51858
  descriptionContext
50757
51859
  });
50758
- const fileBuffer = await readFile23(filePath);
51860
+ const fileBuffer = await readFile25(filePath);
50759
51861
  const uploadResponse = await fetch(uploadUrl, {
50760
51862
  method: "PUT",
50761
51863
  headers: { "Content-Type": contentType },
@@ -50786,7 +51888,7 @@ var uploadCommand2 = defineCommand212({
50786
51888
  });
50787
51889
 
50788
51890
  // src/commands/videos/index.ts
50789
- var videosCommand = defineCommand213({
51891
+ var videosCommand = defineCommand215({
50790
51892
  meta: {
50791
51893
  name: "videos",
50792
51894
  description: `Find and manage videos in Baker. Subcommands: search, get, upload, ingest, delete, tags.
@@ -50813,10 +51915,10 @@ Full guide: __tooling__/docs/tools/baker/videos.md`
50813
51915
  });
50814
51916
 
50815
51917
  // src/commands/winning-ads/index.ts
50816
- import { defineCommand as defineCommand226 } from "citty";
51918
+ import { defineCommand as defineCommand228 } from "citty";
50817
51919
 
50818
51920
  // src/commands/winning-ads/advertisers.ts
50819
- import { defineCommand as defineCommand214 } from "citty";
51921
+ import { defineCommand as defineCommand216 } from "citty";
50820
51922
 
50821
51923
  // src/commands/winning-ads/shared.ts
50822
51924
  function splitList2(value) {
@@ -50869,7 +51971,7 @@ function advertiserNormalizer(record, full) {
50869
51971
  last_synced_at: record.last_synced_at ?? null
50870
51972
  };
50871
51973
  }
50872
- var advertisersCommand2 = defineCommand214({
51974
+ var advertisersCommand2 = defineCommand216({
50873
51975
  meta: {
50874
51976
  name: "advertisers",
50875
51977
  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'
@@ -50927,7 +52029,7 @@ var advertisersCommand2 = defineCommand214({
50927
52029
  });
50928
52030
 
50929
52031
  // src/commands/winning-ads/brief.ts
50930
- import { defineCommand as defineCommand215 } from "citty";
52032
+ import { defineCommand as defineCommand217 } from "citty";
50931
52033
  registerSchema({
50932
52034
  command: "winning-ads.brief",
50933
52035
  description: "Generate a creative brief grounded in strategically-similar winning ads. Optionally describe the target creative with --dna (JSON) and steer with --notes.",
@@ -50973,7 +52075,7 @@ function parseDna(raw) {
50973
52075
  }
50974
52076
  return parsed;
50975
52077
  }
50976
- var briefCommand = defineCommand215({
52078
+ var briefCommand = defineCommand217({
50977
52079
  meta: {
50978
52080
  name: "brief",
50979
52081
  description: `Generate a creative brief from winning references. Example: baker winning-ads brief --dna '{"angle":"cost savings"}' --notes "B2B, LinkedIn video" --k 8`
@@ -51009,7 +52111,7 @@ var briefCommand = defineCommand215({
51009
52111
  });
51010
52112
 
51011
52113
  // src/commands/winning-ads/content.ts
51012
- import { defineCommand as defineCommand216 } from "citty";
52114
+ import { defineCommand as defineCommand218 } from "citty";
51013
52115
  registerSchema({
51014
52116
  command: "winning-ads.content",
51015
52117
  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.",
@@ -51022,7 +52124,7 @@ registerSchema({
51022
52124
  }
51023
52125
  }
51024
52126
  });
51025
- var contentCommand = defineCommand216({
52127
+ var contentCommand = defineCommand218({
51026
52128
  meta: {
51027
52129
  name: "content",
51028
52130
  description: "Read the transcript + on-screen text + copy of one winning ad. Example: baker winning-ads content adg_123 --platform meta --full --output md"
@@ -51071,7 +52173,7 @@ var contentCommand = defineCommand216({
51071
52173
  });
51072
52174
 
51073
52175
  // src/commands/winning-ads/feed.ts
51074
- import { defineCommand as defineCommand217 } from "citty";
52176
+ import { defineCommand as defineCommand219 } from "citty";
51075
52177
  function buildFeedParams(input) {
51076
52178
  const params = {};
51077
52179
  const advertiser = splitList2(input.advertiser);
@@ -51123,7 +52225,7 @@ registerSchema({
51123
52225
  format: { type: "string", description: "Comma-separated formats to include (e.g. static,video)", required: false }
51124
52226
  }
51125
52227
  });
51126
- var feedCommand = defineCommand217({
52228
+ var feedCommand = defineCommand219({
51127
52229
  meta: {
51128
52230
  name: "feed",
51129
52231
  description: "Winners across every brand you follow (browse, then trim per advertiser). Example: baker winning-ads feed --per-advertiser 5 --output md"
@@ -51208,7 +52310,7 @@ var feedCommand = defineCommand217({
51208
52310
  });
51209
52311
 
51210
52312
  // src/commands/winning-ads/follow.ts
51211
- import { defineCommand as defineCommand218 } from "citty";
52313
+ import { defineCommand as defineCommand220 } from "citty";
51212
52314
  var PLATFORMS = ["meta", "linkedin"];
51213
52315
  registerSchema({
51214
52316
  command: "winning-ads.follow",
@@ -51223,7 +52325,7 @@ registerSchema({
51223
52325
  label: { type: "string", description: "Optional display label (defaults to the resolved name)", required: false }
51224
52326
  }
51225
52327
  });
51226
- var followCommand = defineCommand218({
52328
+ var followCommand = defineCommand220({
51227
52329
  meta: {
51228
52330
  name: "follow",
51229
52331
  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'
@@ -51270,7 +52372,7 @@ var followCommand = defineCommand218({
51270
52372
  });
51271
52373
 
51272
52374
  // src/commands/winning-ads/follow-competitors.ts
51273
- import { defineCommand as defineCommand219 } from "citty";
52375
+ import { defineCommand as defineCommand221 } from "citty";
51274
52376
  var PLATFORMS2 = ["meta", "linkedin"];
51275
52377
  var BATCH_TIMEOUT_MS = 3e5;
51276
52378
  function buildFollowBatchBody(input) {
@@ -51303,7 +52405,7 @@ registerSchema({
51303
52405
  }
51304
52406
  }
51305
52407
  });
51306
- var followCompetitorsCommand = defineCommand219({
52408
+ var followCompetitorsCommand = defineCommand221({
51307
52409
  meta: {
51308
52410
  name: "follow-competitors",
51309
52411
  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"'
@@ -51378,7 +52480,7 @@ var followCompetitorsCommand = defineCommand219({
51378
52480
  });
51379
52481
 
51380
52482
  // src/commands/winning-ads/following.ts
51381
- import { defineCommand as defineCommand220 } from "citty";
52483
+ import { defineCommand as defineCommand222 } from "citty";
51382
52484
  registerSchema({
51383
52485
  command: "winning-ads.following",
51384
52486
  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.",
@@ -51432,7 +52534,7 @@ function followingNormalizer(record, full) {
51432
52534
  platforms: Array.isArray(record.platforms) ? record.platforms : []
51433
52535
  };
51434
52536
  }
51435
- var followingCommand = defineCommand220({
52537
+ var followingCommand = defineCommand222({
51436
52538
  meta: {
51437
52539
  name: "following",
51438
52540
  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"
@@ -51468,7 +52570,7 @@ var followingCommand = defineCommand220({
51468
52570
  });
51469
52571
 
51470
52572
  // src/commands/winning-ads/patterns.ts
51471
- import { defineCommand as defineCommand221 } from "citty";
52573
+ import { defineCommand as defineCommand223 } from "citty";
51472
52574
  registerSchema({
51473
52575
  command: "winning-ads.patterns",
51474
52576
  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.",
@@ -51507,7 +52609,7 @@ function discriminatorRow(record) {
51507
52609
  top_values_duds: Array.isArray(record.top_values_b) ? record.top_values_b.join(", ") : ""
51508
52610
  };
51509
52611
  }
51510
- var patternsCommand = defineCommand221({
52612
+ var patternsCommand = defineCommand223({
51511
52613
  meta: {
51512
52614
  name: "patterns",
51513
52615
  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"
@@ -51563,7 +52665,7 @@ var patternsCommand = defineCommand221({
51563
52665
  });
51564
52666
 
51565
52667
  // src/commands/winning-ads/search.ts
51566
- import { defineCommand as defineCommand222 } from "citty";
52668
+ import { defineCommand as defineCommand224 } from "citty";
51567
52669
  registerSchema({
51568
52670
  command: "winning-ads.search",
51569
52671
  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.",
@@ -51671,7 +52773,7 @@ function buildSearchBody2(args) {
51671
52773
  }
51672
52774
  return body;
51673
52775
  }
51674
- var searchCommand5 = defineCommand222({
52776
+ var searchCommand5 = defineCommand224({
51675
52777
  meta: {
51676
52778
  name: "search",
51677
52779
  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"
@@ -51786,7 +52888,7 @@ var searchCommand5 = defineCommand222({
51786
52888
  });
51787
52889
 
51788
52890
  // src/commands/winning-ads/seeds.ts
51789
- import { defineCommand as defineCommand223 } from "citty";
52891
+ import { defineCommand as defineCommand225 } from "citty";
51790
52892
  function leanRow(r) {
51791
52893
  return {
51792
52894
  key: r.key,
@@ -51814,7 +52916,7 @@ function makeSeedCommand(opts) {
51814
52916
  limit: { type: "number", description: "Max keys 1-100 (default 20)", required: false, default: 20 }
51815
52917
  }
51816
52918
  });
51817
- return defineCommand223({
52919
+ return defineCommand225({
51818
52920
  meta: { name: opts.name, description: opts.description },
51819
52921
  args: {
51820
52922
  platform: { type: "string", description: "Single platform to segment on", required: false },
@@ -51863,7 +52965,7 @@ var formatsCommand = makeSeedCommand({
51863
52965
  });
51864
52966
 
51865
52967
  // src/commands/winning-ads/unfollow.ts
51866
- import { defineCommand as defineCommand224 } from "citty";
52968
+ import { defineCommand as defineCommand226 } from "citty";
51867
52969
  registerSchema({
51868
52970
  command: "winning-ads.unfollow",
51869
52971
  description: "Stop following a brand \u2014 removes it from your ad-dna library by advertiser id.",
@@ -51871,7 +52973,7 @@ registerSchema({
51871
52973
  advertiser: { type: "string", description: "Advertiser id to unfollow", required: true }
51872
52974
  }
51873
52975
  });
51874
- var unfollowCommand = defineCommand224({
52976
+ var unfollowCommand = defineCommand226({
51875
52977
  meta: {
51876
52978
  name: "unfollow",
51877
52979
  description: "Stop following a brand by advertiser id. Example: baker winning-ads unfollow adv_123"
@@ -51892,7 +52994,7 @@ var unfollowCommand = defineCommand224({
51892
52994
  });
51893
52995
 
51894
52996
  // src/commands/winning-ads/winners.ts
51895
- import { defineCommand as defineCommand225 } from "citty";
52997
+ import { defineCommand as defineCommand227 } from "citty";
51896
52998
  registerSchema({
51897
52999
  command: "winning-ads.winners",
51898
53000
  description: "Top winning ads for one advertiser id (from `advertisers` or `following`). Returns lean winner cards; add --full for DNA + longevity.",
@@ -51902,7 +53004,7 @@ registerSchema({
51902
53004
  platform: { type: "string", description: "Filter to a single platform: meta|linkedin", required: false }
51903
53005
  }
51904
53006
  });
51905
- var winnersCommand = defineCommand225({
53007
+ var winnersCommand = defineCommand227({
51906
53008
  meta: {
51907
53009
  name: "winners",
51908
53010
  description: "Top winning ads for a specific advertiser id. Example: baker winning-ads winners adv_123 --top 15 --output md"
@@ -51952,7 +53054,7 @@ var winnersCommand = defineCommand225({
51952
53054
  });
51953
53055
 
51954
53056
  // src/commands/winning-ads/index.ts
51955
- var winningAdsCommand = defineCommand226({
53057
+ var winningAdsCommand = defineCommand228({
51956
53058
  meta: {
51957
53059
  name: "winning-ads",
51958
53060
  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.
@@ -52142,7 +53244,7 @@ function unknownFlagEnvelope(unknown, commandPath, suggestion) {
52142
53244
  };
52143
53245
  }
52144
53246
  function commandPathOf(root, argv) {
52145
- const path38 = [];
53247
+ const path41 = [];
52146
53248
  let command = root;
52147
53249
  for (const token of argv) {
52148
53250
  if (token === "--" || token.startsWith("-")) {
@@ -52153,10 +53255,10 @@ function commandPathOf(root, argv) {
52153
53255
  if (next === void 0 || typeof next !== "object") {
52154
53256
  break;
52155
53257
  }
52156
- path38.push(token);
53258
+ path41.push(token);
52157
53259
  command = next;
52158
53260
  }
52159
- return path38.join(" ");
53261
+ return path41.join(" ");
52160
53262
  }
52161
53263
  function refuseUnknownFlags(root, argv) {
52162
53264
  const unknown = findUnknownFlags(root, argv);
@@ -52190,7 +53292,7 @@ function getCliVersion() {
52190
53292
  }
52191
53293
 
52192
53294
  // src/cli.ts
52193
- var main = defineCommand227({
53295
+ var main = defineCommand229({
52194
53296
  meta: {
52195
53297
  name: "baker",
52196
53298
  version: getCliVersion(),
@@ -52209,6 +53311,7 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
52209
53311
  ads: adsCommand2,
52210
53312
  brand: brandCommand,
52211
53313
  analytics: analyticsCommand2,
53314
+ experiment: experimentCommand,
52212
53315
  ga4: ga4Command,
52213
53316
  gsc: gscCommand,
52214
53317
  research: researchCommand,