@koda-sl/baker-cli 0.356.0 → 0.357.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1426,8 +1426,8 @@ baker experiment plan --landing oferta --variant oferta--1 --goal submit:book-a-
1426
1426
  baker experiment start --landing oferta --variant oferta--1 --because "60% of visitors never scroll past the hero" --change "put the price in the headline"
1427
1427
  baker experiment update --id temp_exp_1 --goal submit:book-a-call # a staged test can still change what it measures
1428
1428
  baker experiment update --id a3f91c2b --because "…" # a live one can only change its wording
1429
- baker experiment status # the verdict on every test
1430
- baker experiment status --id a3f91c2b --full # one test, with the confidence and posteriors behind it
1429
+ baker experiment status # the verdict on every test, first; dates as calendar dates
1430
+ baker experiment status --id a3f91c2b --full # one test, with everything the dashboard reads and the posteriors
1431
1431
  baker experiment history --landing oferta # every finished test on a page: claim, numbers, decision, learning
1432
1432
  baker experiment pause --id a3f91c2b # everyone sees the original for now
1433
1433
  baker experiment resume --id a3f91c2b # the split picks up with the same sides
package/dist/cli.js CHANGED
@@ -47300,6 +47300,80 @@ async function declarationsOf(root, files) {
47300
47300
  return sources.flatMap(eventDeclarationsIn);
47301
47301
  }
47302
47302
 
47303
+ // src/commands/experiment/readout.ts
47304
+ function isoMoment(ms) {
47305
+ return ms === null ? null : new Date(ms).toISOString();
47306
+ }
47307
+ function isoDay2(ms) {
47308
+ return ms === null ? null : new Date(ms).toISOString().slice(0, 10);
47309
+ }
47310
+ function compactArm(arm) {
47311
+ return { visitors: arm.visitors, conversions: arm.conversions, rate: Math.round(arm.rate * 1e4) / 1e4 };
47312
+ }
47313
+ function compactMetric(metric) {
47314
+ return {
47315
+ name: metric.name,
47316
+ reading: metric.reading,
47317
+ control: metric.control.conversions,
47318
+ variant: metric.variant.conversions
47319
+ };
47320
+ }
47321
+ function fullArm(arm) {
47322
+ return {
47323
+ ...arm,
47324
+ ...arm.snapshotCapturedAt === void 0 ? {} : { snapshotCapturedAt: isoMoment(arm.snapshotCapturedAt) }
47325
+ };
47326
+ }
47327
+ function statusReadout(row, { full, now }) {
47328
+ const decisionWhen = {
47329
+ earliestDecisionAt: isoDay2(row.earliestDecisionAt),
47330
+ ...row.earliestDecisionAt === null ? {} : { earliestDecisionIn: describeWait(row.earliestDecisionAt, now) }
47331
+ };
47332
+ const moments = {
47333
+ startedAt: isoMoment(row.startedAt),
47334
+ pausedAt: isoMoment(row.pausedAt),
47335
+ finishedAt: isoMoment(row.finishedAt)
47336
+ };
47337
+ if (full) {
47338
+ return {
47339
+ ...row,
47340
+ ...moments,
47341
+ ...decisionWhen,
47342
+ control: fullArm(row.control),
47343
+ variant: fullArm(row.variant)
47344
+ };
47345
+ }
47346
+ return {
47347
+ experimentId: row.experimentId,
47348
+ landingSlug: row.landingSlug,
47349
+ variantSlug: row.variantSlug,
47350
+ status: row.status,
47351
+ verdict: row.verdict,
47352
+ summary: row.summary,
47353
+ ...row.winner === null ? {} : { winner: row.winner },
47354
+ ...row.invalidReason === null ? {} : { invalidReason: row.invalidReason },
47355
+ stillNeeded: row.stillNeeded,
47356
+ ...decisionWhen,
47357
+ willNotConclude: row.willNotConclude,
47358
+ control: compactArm(row.control),
47359
+ variant: compactArm(row.variant),
47360
+ secondary: row.secondary.map(compactMetric),
47361
+ hypothesisStatement: row.hypothesisStatement,
47362
+ minDetectableRelativeLift: row.minDetectableRelativeLift,
47363
+ goal: row.goal,
47364
+ ...row.variantGoal === null ? {} : { variantGoal: row.variantGoal },
47365
+ goalLabel: row.goalLabel,
47366
+ ...moments,
47367
+ ...row.status === "finished" ? {
47368
+ survivor: row.survivor,
47369
+ hypothesisOutcome: row.hypothesisOutcome,
47370
+ fold: row.fold,
47371
+ learning: row.learning,
47372
+ endReason: row.endReason
47373
+ } : {}
47374
+ };
47375
+ }
47376
+
47303
47377
  // src/commands/experiment/update.ts
47304
47378
  function buildUpdateRequest(args5, rawArgs) {
47305
47379
  const expect = args5.expect === void 0 ? void 0 : String(args5.expect);
@@ -47541,18 +47615,26 @@ registerSchema({
47541
47615
  args: {
47542
47616
  id: { type: "string", description: "One test, by its id", required: false },
47543
47617
  landing: LANDING_FILTER_ARG,
47544
- full: { type: "boolean", description: "Include the posteriors behind the verdict", required: false }
47618
+ full: {
47619
+ type: "boolean",
47620
+ description: "Every field the dashboard reads too \u2014 the hypothesis in parts, what each version owns, the preview pictures and the posteriors behind the verdict",
47621
+ required: false
47622
+ }
47545
47623
  }
47546
47624
  });
47547
47625
  var statusCommand6 = defineCommand124({
47548
47626
  meta: {
47549
47627
  name: "status",
47550
- description: "The verdict on each test. Read `verdict` and nothing else to decide: keep_running | winner | no_difference | cannot_win | invalid. `cannot_win` means even the best case is under the lift the test was looking for \u2014 end it and keep the original. `stillNeeded` is the data (visitors, conversions) the test still needs; a test is gated on data, never on days. `summary` is one sentence you can show the client, and `secondary` lists every other conversion the company counts on the same two arms \u2014 context, never a second decision. 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."
47628
+ description: "The verdict on each test. Read `verdict` and nothing else to decide: keep_running | winner | no_difference | cannot_win | invalid. `cannot_win` means even the best case is under the lift the test was looking for \u2014 end it and keep the original. `stillNeeded` is the data (visitors, conversions) the test still needs; a test is gated on data, never on days. `earliestDecisionAt` is the day this page's traffic would get it there (YYYY-MM-DD) and `earliestDecisionIn` how far off that is \u2014 say those, never work a date out yourself. `summary` is one sentence you can show the client, and `secondary` lists every other conversion the company counts on the same two arms \u2014 context, never a second decision. 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."
47551
47629
  },
47552
47630
  args: {
47553
47631
  id: { type: "string", description: "One test, by its id", required: false },
47554
47632
  landing: LANDING_FILTER_ARG,
47555
- full: { type: "boolean", description: "Include the posteriors behind the verdict", required: false }
47633
+ full: {
47634
+ type: "boolean",
47635
+ description: "Every field the dashboard reads too \u2014 the hypothesis in parts, what each version owns, the preview pictures and the posteriors behind the verdict",
47636
+ required: false
47637
+ }
47556
47638
  },
47557
47639
  run: async ({ args: args5 }) => {
47558
47640
  try {
@@ -47561,10 +47643,13 @@ var statusCommand6 = defineCommand124({
47561
47643
  ...args5.landing ? { landingSlug: String(args5.landing) } : {},
47562
47644
  ...args5.full === true ? { full: true } : {}
47563
47645
  });
47646
+ const now = Date.now();
47564
47647
  writeJsonEnvelope({
47565
47648
  ok: true,
47566
- data: response.data,
47567
- hints: buildStatusHints(response.data.experiments)
47649
+ data: {
47650
+ experiments: response.data.experiments.map((row) => statusReadout(row, { full: args5.full === true, now }))
47651
+ },
47652
+ hints: buildStatusHints(response.data.experiments, now)
47568
47653
  });
47569
47654
  } catch (error) {
47570
47655
  reportApiError(error);