@drip-apex/apex-cli 0.14.1 → 0.14.2

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.
Files changed (2) hide show
  1. package/dist/cli.js +170 -85
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -7325,7 +7325,7 @@ async function checkForUpdate(current) {
7325
7325
  // package.json
7326
7326
  var package_default = {
7327
7327
  name: "@drip-apex/apex-cli",
7328
- version: "0.14.1",
7328
+ version: "0.14.2",
7329
7329
  license: "MIT",
7330
7330
  description: "Apex CLI for managing experiments, approved roadmap ideas, and draft workspaces.",
7331
7331
  private: false,
@@ -9549,10 +9549,10 @@ var evidenceKinds = [
9549
9549
 
9550
9550
  // src/lib/experiment-handover.ts
9551
9551
  function summarizeHandoverQa(value) {
9552
- const record3 = (value2) => value2 !== null && typeof value2 === "object" && !Array.isArray(value2) ? value2 : {};
9553
- const qa3 = record3(value);
9554
- const run3 = record3(qa3.latestRun);
9555
- const summary = record3(run3.summary);
9552
+ const record4 = (value2) => value2 !== null && typeof value2 === "object" && !Array.isArray(value2) ? value2 : {};
9553
+ const qa3 = record4(value);
9554
+ const run3 = record4(qa3.latestRun);
9555
+ const summary = record4(run3.summary);
9556
9556
  const count2 = (value2) => typeof value2 === "number" && Number.isInteger(value2) && value2 >= 0 ? value2 : null;
9557
9557
  let requiredDone = count2(summary.completedRequired);
9558
9558
  let requiredTotal = count2(summary.required);
@@ -9627,12 +9627,6 @@ function deviceLabel(targeting) {
9627
9627
  return void 0;
9628
9628
  }
9629
9629
 
9630
- // src/lib/test-key.ts
9631
- var TEST_KEY_RE = /^([A-Z0-9]{2,8})-(\d+)$/;
9632
- function isTestKeyReference(value) {
9633
- return value === value.toUpperCase() && TEST_KEY_RE.test(value.toUpperCase());
9634
- }
9635
-
9636
9630
  // src/lib/effective-page-targeting.ts
9637
9631
  var ALL_PAGES_LABEL = "All pages";
9638
9632
  var CHECKOUT_LABEL = "Checkout";
@@ -9719,6 +9713,99 @@ function classifyIdeaReference(reference) {
9719
9713
  return { kind: "invalid", value: trimmed };
9720
9714
  }
9721
9715
 
9716
+ // ../api-client/src/experiments.ts
9717
+ var ID_REFERENCE = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[1-9][0-9]{9})$/i;
9718
+ function isExperimentTestKey(value) {
9719
+ return /^([A-Z0-9]{2,8})-(\d+)$/.test(value);
9720
+ }
9721
+ function record(value) {
9722
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
9723
+ }
9724
+ async function resolveExperimentReference(request2, idOrSlug, variationRef) {
9725
+ const explicitSlug = idOrSlug.startsWith("slug:");
9726
+ const reference = explicitSlug ? idOrSlug.slice(5) : idOrSlug;
9727
+ const idShaped = !explicitSlug && ID_REFERENCE.test(reference);
9728
+ const keyShaped = !explicitSlug && isExperimentTestKey(reference);
9729
+ const slugPath = `/api/v1/experiments/by-slug/${encodeURIComponent(reference)}`;
9730
+ let res = await request2("GET", idShaped || keyShaped ? `/api/v1/experiments/${encodeURIComponent(reference)}` : slugPath);
9731
+ if (!res.ok && res.status === 404 && idShaped) res = await request2("GET", slugPath);
9732
+ if (!res.ok) return { ok: false, error: res.error ?? "Experiment not found", status: res.status, response: res };
9733
+ const experiment = record(res.data);
9734
+ if (typeof experiment.id !== "string") return { ok: false, error: "Experiment has no id" };
9735
+ const variations = Array.isArray(experiment.variations) ? experiment.variations.map(record) : [];
9736
+ if (variationRef === void 0) return { ok: true, experimentId: experiment.id, variations, experiment };
9737
+ const available = variations.map((v) => String(v.slug ?? v.name)).join(", ") || "none";
9738
+ const byIdentity = variations.filter((v) => v.id === variationRef || v.public_id === variationRef || v.slug === variationRef);
9739
+ const byName = variations.filter((v) => v.name === variationRef);
9740
+ const matches = byIdentity.length > 0 ? byIdentity : byName;
9741
+ if (matches.length > 1) return {
9742
+ ok: false,
9743
+ error: `Variation "${variationRef}" is ambiguous; use one of these slugs: ${matches.map((v) => String(v.slug)).join(", ")}`
9744
+ };
9745
+ const match2 = matches[0];
9746
+ if (typeof match2?.id !== "string") return { ok: false, error: `Variation "${variationRef}" not found. Available: ${available}` };
9747
+ return { ok: true, experimentId: experiment.id, variationId: match2.id, variations, experiment };
9748
+ }
9749
+ function summarizeResults(payload) {
9750
+ const data = record(payload);
9751
+ const experiment = record(data.experiment);
9752
+ const decision = record(data.decision);
9753
+ const outcome = record(data.effective_outcome);
9754
+ const commerce = record(data.commerce);
9755
+ const rawArms = Array.isArray(data.arms) ? data.arms.map(record) : [];
9756
+ const degradedFlags = {
9757
+ explicit: data.degraded === true,
9758
+ commerceUnavailable: commerce.unavailable === true,
9759
+ armMetricsMissing: rawArms.some((arm) => arm.primaryConversions == null || arm.primaryRate == null)
9760
+ };
9761
+ const missing = /* @__PURE__ */ new Set();
9762
+ if (degradedFlags.commerceUnavailable) missing.add("commerce orders");
9763
+ const controlRate = rawArms.find((arm) => arm.isControl === true)?.primaryRate;
9764
+ const treatmentCount = rawArms.filter((arm) => arm.isControl !== true).length;
9765
+ const arms = rawArms.map((arm) => {
9766
+ const judged = arm.isControl !== true && (decision.treatmentVariationId != null ? arm.variationId === decision.treatmentVariationId : treatmentCount === 1);
9767
+ let lift = null;
9768
+ let confidence = null;
9769
+ if (arm.isControl !== true) {
9770
+ if (judged) {
9771
+ lift = decision.lift;
9772
+ confidence = decision.judgedConfidence;
9773
+ } else if (typeof arm.primaryRate === "number" && typeof controlRate === "number" && controlRate > 0)
9774
+ lift = Math.round((arm.primaryRate / controlRate - 1) * 1e4) / 100;
9775
+ if (lift == null) missing.add("lift");
9776
+ if (judged && confidence == null) missing.add("confidence");
9777
+ }
9778
+ if (arm.visitors == null) missing.add("visitors");
9779
+ if (arm.primaryConversions == null) missing.add("conversions");
9780
+ if (arm.primaryRate == null) missing.add("conversion rate");
9781
+ return { ...arm, lift, confidence, judged };
9782
+ });
9783
+ const verdictWithheld = decision.state === "untrustworthy";
9784
+ return {
9785
+ experiment,
9786
+ runWindow: { startedAt: experiment.resultsWindowStartedAt ?? experiment.startedAt, endedAt: experiment.endedAt },
9787
+ primaryGoal: decision.primaryGoalName,
9788
+ totals: record(data.totals),
9789
+ decision,
9790
+ outcome,
9791
+ arms,
9792
+ judgedArm: arms.find((arm) => arm.judged)?.variationId,
9793
+ verdict: outcome.outcome ?? decision.state,
9794
+ verdictWithheld,
9795
+ statisticsState: (verdictWithheld ? decision.state : outcome.statisticsOutcome ?? decision.state) ?? "unknown",
9796
+ presentedOutcome: (verdictWithheld && outcome.provenance !== "manager_decided" ? decision.state : outcome.outcome ?? decision.state) ?? "unknown",
9797
+ degraded: Object.values(degradedFlags).some(Boolean),
9798
+ degradedFlags,
9799
+ missingMetrics: [...missing],
9800
+ warnings: Array.isArray(data.warnings) ? data.warnings.map((value) => ({
9801
+ message: record(value).message,
9802
+ value
9803
+ })) : [],
9804
+ metrics: Array.isArray(data.metrics) ? data.metrics.map(record) : [],
9805
+ resultsWeekdays: data.results_weekdays
9806
+ };
9807
+ }
9808
+
9722
9809
  // ../api-client/src/experiment-create.ts
9723
9810
  function deriveStoreUrl(patterns) {
9724
9811
  for (const pattern of patterns) {
@@ -9984,14 +10071,9 @@ function formatRevenue(value, currency) {
9984
10071
  }
9985
10072
  }
9986
10073
  function printExperimentResults(results2, currency) {
9987
- const experiment = results2.experiment ?? {};
9988
- const totals = results2.totals ?? {};
9989
- const decision = results2.decision ?? {};
9990
- const effectiveOutcome = results2.effective_outcome ?? {};
9991
- const outcomeProvenance = effectiveOutcome.provenance === "manager_decided" ? " (manager decided)" : "";
9992
- const verdictWithheld = decision.state === "untrustworthy";
9993
- const statisticsState = verdictWithheld ? decision.state : effectiveOutcome.statisticsOutcome ?? decision.state ?? "unknown";
9994
- const presentedOutcome = verdictWithheld && effectiveOutcome.provenance !== "manager_decided" ? decision.state : effectiveOutcome.outcome ?? decision.state ?? "unknown";
10074
+ const summary = summarizeResults(results2);
10075
+ const { experiment, totals, decision, verdictWithheld, statisticsState, presentedOutcome } = summary;
10076
+ const outcomeProvenance = summary.outcome.provenance === "manager_decided" ? " (manager decided)" : "";
9995
10077
  console.log();
9996
10078
  console.log(source_default.bold(String(experiment.name ?? experiment.id ?? "Experiment results")));
9997
10079
  console.log(` Status: ${statusBadge(String(experiment.status ?? "unknown"))}`);
@@ -9999,7 +10081,7 @@ function printExperimentResults(results2, currency) {
9999
10081
  console.log(` Conversions: ${String(totals.primaryConversions ?? 0)}`);
10000
10082
  console.log(` Revenue: ${formatRevenue(totals.revenue, currency)}`);
10001
10083
  console.log(` Outcome: ${statisticsStateLabel(presentedOutcome)}${outcomeProvenance}`);
10002
- const resultsWeekdays = results2.results_weekdays;
10084
+ const resultsWeekdays = summary.resultsWeekdays;
10003
10085
  if (resultsWeekdays && Array.isArray(resultsWeekdays.days)) {
10004
10086
  const labels = {
10005
10087
  monday: "Mon",
@@ -10022,7 +10104,7 @@ function printExperimentResults(results2, currency) {
10022
10104
  console.log(
10023
10105
  ` Confidence (${confidenceBasisLabel(decision.basis)}): ${verdictWithheld ? "withheld \u2014 not decision-grade" : formatPct(decision.judgedConfidence)}`
10024
10106
  );
10025
- const arms = Array.isArray(results2.arms) ? results2.arms : [];
10107
+ const arms = summary.arms;
10026
10108
  if (arms.length > 0) {
10027
10109
  console.log();
10028
10110
  printTable(
@@ -10040,7 +10122,7 @@ function printExperimentResults(results2, currency) {
10040
10122
  [32, 8, 6, 8, 10]
10041
10123
  );
10042
10124
  }
10043
- const metrics = Array.isArray(results2.metrics) ? results2.metrics : [];
10125
+ const metrics = summary.metrics;
10044
10126
  if (metrics.length > 0) {
10045
10127
  console.log();
10046
10128
  console.log(source_default.bold("Goal counting"));
@@ -10050,7 +10132,7 @@ function printExperimentResults(results2, currency) {
10050
10132
  });
10051
10133
  }
10052
10134
  console.log(" Definitions: https://docs.drip-apex.com/docs/experiments/metric-definitions");
10053
- const warnings = Array.isArray(results2.warnings) ? results2.warnings : [];
10135
+ const warnings = summary.warnings;
10054
10136
  if (warnings.length > 0) {
10055
10137
  console.log();
10056
10138
  console.log(source_default.yellow("Warnings"));
@@ -10353,10 +10435,10 @@ function printQaRun(run3) {
10353
10435
  }
10354
10436
  if ((run3.evidenceRecords ?? []).length > 0) {
10355
10437
  console.log(source_default.bold("\nEvidence records"));
10356
- for (const record3 of run3.evidenceRecords ?? []) {
10357
- const device = record3.device ? ` \xB7 ${record3.device}` : "";
10438
+ for (const record4 of run3.evidenceRecords ?? []) {
10439
+ const device = record4.device ? ` \xB7 ${record4.device}` : "";
10358
10440
  console.log(
10359
- ` - ${record3.kind} \xB7 ${record3.label} \xB7 ${record3.status}${device} \xB7 ${record3.capturedAt}${qaVersionMarker(record3)}`
10441
+ ` - ${record4.kind} \xB7 ${record4.label} \xB7 ${record4.status}${device} \xB7 ${record4.capturedAt}${qaVersionMarker(record4)}`
10360
10442
  );
10361
10443
  }
10362
10444
  }
@@ -10475,26 +10557,29 @@ async function refreshServerOwnedFilesIfNeeded(creds, folder, experimentId, upda
10475
10557
  }
10476
10558
  }
10477
10559
  var EXPERIMENT_REFERENCE_DESCRIPTION = "Experiment ID, slug, or test key (for example BIO-085)";
10560
+ function resolveCliExperimentReference(creds, reference, variationRef) {
10561
+ return resolveExperimentReference(
10562
+ (_method, requestPath) => {
10563
+ const prefix = "/api/v1/experiments/by-slug/";
10564
+ const bySlug = requestPath.startsWith(prefix);
10565
+ const idOrSlug = decodeURIComponent(
10566
+ requestPath.slice(bySlug ? prefix.length : "/api/v1/experiments/".length)
10567
+ );
10568
+ return bySlug ? getExperimentBySlug(creds, idOrSlug) : getExperiment(creds, idOrSlug);
10569
+ },
10570
+ reference,
10571
+ variationRef
10572
+ );
10573
+ }
10478
10574
  async function resolveExperiment(idOrSlug) {
10479
10575
  const creds = requireCredentials();
10480
- if (/^[0-9a-f-]{36}$/i.test(idOrSlug) || /^[1-9][0-9]{9}$/.test(idOrSlug) || isTestKeyReference(idOrSlug)) {
10481
- const res2 = await getExperiment(creds, idOrSlug);
10482
- if (res2.ok) return res2.data;
10483
- throw new CliError(
10484
- res2.status === 404 && isTestKeyReference(idOrSlug) ? `Experiment "${idOrSlug}" not found in selected shop ${creds.resolvedContext?.shopId ?? "(API key shop)"}. Test keys resolve within the selected shop; use --shop <shop-id> to change it.` : res2.error ?? `Experiment "${idOrSlug}" not found`,
10485
- classifyStatus(res2.status),
10486
- res2.errorDetails,
10487
- apiFailureOf(res2)
10488
- );
10489
- }
10490
- const slug = idOrSlug.startsWith("slug:") ? idOrSlug.slice(5) : idOrSlug;
10491
- const res = await getExperimentBySlug(creds, slug);
10492
- if (res.ok) return res.data;
10576
+ const res = await resolveCliExperimentReference(creds, idOrSlug);
10577
+ if (res.ok) return res.experiment;
10493
10578
  throw new CliError(
10494
- res.error ?? `Experiment "${idOrSlug}" not found`,
10495
- classifyStatus(res.status),
10496
- res.errorDetails,
10497
- apiFailureOf(res)
10579
+ res.status === 404 && isExperimentTestKey(idOrSlug) ? `Experiment "${idOrSlug}" not found in selected shop ${creds.resolvedContext?.shopId ?? "(API key shop)"}. Test keys resolve within the selected shop; use --shop <shop-id> to change it.` : res.response ? res.response.error ?? `Experiment "${idOrSlug}" not found` : res.error,
10580
+ classifyStatus(res.status ?? 500),
10581
+ res.response?.errorDetails,
10582
+ res.response ? apiFailureOf(res.response) : void 0
10498
10583
  );
10499
10584
  }
10500
10585
  var list = new Command("list").alias("ls").description(
@@ -12114,7 +12199,7 @@ var qaEvidence = new Command("evidence").description("Attach screenshot jobs or
12114
12199
  classifyStatus(current.status),
12115
12200
  current.errorDetails
12116
12201
  );
12117
- for (const record3 of current.data.run.evidenceRecords) previousIds.add(record3.id);
12202
+ for (const record4 of current.data.run.evidenceRecords) previousIds.add(record4.id);
12118
12203
  }
12119
12204
  let response;
12120
12205
  if (opts.job) {
@@ -12159,7 +12244,7 @@ var qaEvidence = new Command("evidence").description("Attach screenshot jobs or
12159
12244
  const run3 = response.data.run;
12160
12245
  const data = opts.summary ? qaSummary(
12161
12246
  run3,
12162
- run3.evidenceRecords.filter((record3) => !previousIds.has(record3.id))
12247
+ run3.evidenceRecords.filter((record4) => !previousIds.has(record4.id))
12163
12248
  ) : response.data;
12164
12249
  output(this, data, () => {
12165
12250
  if (opts.summary) process.stdout.write(`${JSON.stringify(data, null, 2)}
@@ -15362,18 +15447,18 @@ function fieldsFrom(value, prefix = "", descriptorList = false) {
15362
15447
  )
15363
15448
  );
15364
15449
  }
15365
- const record3 = value;
15366
- const explicitPath = typeof record3.path === "string" ? record3.path : void 0;
15450
+ const record4 = value;
15451
+ const explicitPath = typeof record4.path === "string" ? record4.path : void 0;
15367
15452
  if (descriptorList && explicitPath) {
15368
- const rawValues = record3.values ?? record3.samples ?? record3.examples ?? record3.example;
15453
+ const rawValues = record4.values ?? record4.samples ?? record4.examples ?? record4.example;
15369
15454
  const values = Array.isArray(rawValues) ? rawValues : rawValues === void 0 ? [] : [rawValues];
15370
- const magnitude = [record3.mean, record3.average, record3.max, record3.magnitude].find(
15455
+ const magnitude = [record4.mean, record4.average, record4.max, record4.magnitude].find(
15371
15456
  (candidate) => typeof candidate === "number"
15372
15457
  );
15373
- const numericType = Array.isArray(record3.types) && record3.types.length > 0 && record3.types.every((type) => type === "num" || type === "numstr" || type === "numstr_comma");
15458
+ const numericType = Array.isArray(record4.types) && record4.types.length > 0 && record4.types.every((type) => type === "num" || type === "numstr" || type === "numstr_comma");
15374
15459
  return [{ path: runtimePath(explicitPath), values, magnitude, numericType }];
15375
15460
  }
15376
- return Object.entries(record3).flatMap(([key, child]) => {
15461
+ return Object.entries(record4).flatMap(([key, child]) => {
15377
15462
  if (["eventName", "event_name", "name", "count", "frequency", "evidence"].includes(key))
15378
15463
  return [];
15379
15464
  const next = prefix ? `${prefix}.${key}` : key;
@@ -15406,8 +15491,8 @@ function isDescriptorArray(value) {
15406
15491
  ]);
15407
15492
  return Array.isArray(value) && value.length > 0 && value.every((item) => {
15408
15493
  if (!item || typeof item !== "object" || Array.isArray(item)) return false;
15409
- const record3 = item;
15410
- return typeof record3.path === "string" && record3.path.length > 0 && Object.keys(record3).every((key) => descriptorKeys.has(key));
15494
+ const record4 = item;
15495
+ return typeof record4.path === "string" && record4.path.length > 0 && Object.keys(record4).every((key) => descriptorKeys.has(key));
15411
15496
  });
15412
15497
  }
15413
15498
  function candidatesFrom(report) {
@@ -15563,10 +15648,10 @@ var whenOps = new Set(runtime_settings_trigger_constants_default.whenOps);
15563
15648
  function strictObject(value, location, keys) {
15564
15649
  if (!value || typeof value !== "object" || Array.isArray(value))
15565
15650
  throw new Error(`${location} must be an object`);
15566
- const record3 = value;
15567
- for (const key of Object.keys(record3))
15651
+ const record4 = value;
15652
+ for (const key of Object.keys(record4))
15568
15653
  if (!keys.has(key)) throw new Error(`${location}.${key} is not allowed`);
15569
- return record3;
15654
+ return record4;
15570
15655
  }
15571
15656
  function optionalType(value, type, location) {
15572
15657
  if (value !== void 0 && typeof value !== type)
@@ -15702,19 +15787,19 @@ function strictTriggers(value) {
15702
15787
  return value.map((item, index) => {
15703
15788
  if (!item || typeof item !== "object" || Array.isArray(item))
15704
15789
  throw new Error(`trigger[${index}] must be an object`);
15705
- const record3 = item;
15706
- for (const key of Object.keys(record3))
15790
+ const record4 = item;
15791
+ for (const key of Object.keys(record4))
15707
15792
  if (!allowed.has(key)) throw new Error(`trigger[${index}].${key} is not allowed`);
15708
- if (typeof record3.eventName !== "string" || !record3.eventName.trim())
15793
+ if (typeof record4.eventName !== "string" || !record4.eventName.trim())
15709
15794
  throw new Error(`trigger[${index}].eventName must be a non-empty string`);
15710
15795
  for (const key of ["enabled", "reEvaluate", "trackPageview"])
15711
- optionalType(record3[key], "boolean", `trigger[${index}].${key}`);
15796
+ optionalType(record4[key], "boolean", `trigger[${index}].${key}`);
15712
15797
  for (const key of ["dataLayerName", "trackEventName"])
15713
- optionalType(record3[key], "string", `trigger[${index}].${key}`);
15714
- strictWhen(record3.when, `trigger[${index}].when`);
15715
- if (record3.trackRevenue !== void 0) {
15798
+ optionalType(record4[key], "string", `trigger[${index}].${key}`);
15799
+ strictWhen(record4.when, `trigger[${index}].when`);
15800
+ if (record4.trackRevenue !== void 0) {
15716
15801
  const revenue = strictObject(
15717
- record3.trackRevenue,
15802
+ record4.trackRevenue,
15718
15803
  `trigger[${index}].trackRevenue`,
15719
15804
  /* @__PURE__ */ new Set([
15720
15805
  "enabled",
@@ -15737,21 +15822,21 @@ function strictTriggers(value) {
15737
15822
  );
15738
15823
  }
15739
15824
  }
15740
- if (record3.mappings !== void 0) {
15741
- if (!Array.isArray(record3.mappings))
15825
+ if (record4.mappings !== void 0) {
15826
+ if (!Array.isArray(record4.mappings))
15742
15827
  throw new Error(`trigger[${index}].mappings must be an array`);
15743
- record3.mappings.forEach(
15828
+ record4.mappings.forEach(
15744
15829
  (mapping, mappingIndex) => strictMapping(mapping, `trigger[${index}].mappings[${mappingIndex}]`, false)
15745
15830
  );
15746
15831
  }
15747
- if (record3.properties !== void 0) {
15748
- if (!Array.isArray(record3.properties))
15832
+ if (record4.properties !== void 0) {
15833
+ if (!Array.isArray(record4.properties))
15749
15834
  throw new Error(`trigger[${index}].properties must be an array`);
15750
- record3.properties.forEach(
15835
+ record4.properties.forEach(
15751
15836
  (mapping, mappingIndex) => strictMapping(mapping, `trigger[${index}].properties[${mappingIndex}]`, true)
15752
15837
  );
15753
15838
  }
15754
- return record3;
15839
+ return record4;
15755
15840
  });
15756
15841
  }
15757
15842
  function writeWarnings(result) {
@@ -16280,7 +16365,7 @@ function compare(a, b) {
16280
16365
  const left = a.fraction.padEnd(precision, "0"), right = b.fraction.padEnd(precision, "0");
16281
16366
  return left === right ? 0 : left < right ? -1 : 1;
16282
16367
  }
16283
- var record = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
16368
+ var record2 = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
16284
16369
  var text = (v) => typeof v === "string" && v.length > 0;
16285
16370
  var reason = (v) => typeof v === "string" && (/^[a-z][a-z0-9_]{0,79}$/.test(v) || /^(publishedConfig|consentPolicy|goalMapping|sdkArtifact|sdkPolicy|identityPolicy|goalDefinition|resultWindow|inputSnapshot)_(expected_unknown|observed_unknown|mismatch|binding_mismatch)$/.test(
16286
16371
  v
@@ -16289,8 +16374,8 @@ var member = (v, values) => typeof v === "string" && values.includes(v);
16289
16374
  var status = (v) => member(v, ["pass", "fail", "inconclusive"]);
16290
16375
  var count = (v) => typeof v === "number" && Number.isSafeInteger(v) && v >= 0;
16291
16376
  function validReport(v) {
16292
- if (!record(v) || v.schemaVersion !== 1 || v.finalStatisticalContribution !== "not_evaluated" || !record(v.evaluation) || !status(v.evaluation.status) || !member(v.evaluation.freshness, ["current", "stale", "unknown"]) || !Array.isArray(v.evaluation.stages) || !v.evaluation.stages.every(
16293
- (s) => record(s) && (s.freshness === void 0 || member(s.freshness, ["current", "stale", "unknown"])) && member(s.stage, [
16377
+ if (!record2(v) || v.schemaVersion !== 1 || v.finalStatisticalContribution !== "not_evaluated" || !record2(v.evaluation) || !status(v.evaluation.status) || !member(v.evaluation.freshness, ["current", "stale", "unknown"]) || !Array.isArray(v.evaluation.stages) || !v.evaluation.stages.every(
16378
+ (s) => record2(s) && (s.freshness === void 0 || member(s.freshness, ["current", "stale", "unknown"])) && member(s.stage, [
16294
16379
  "consent",
16295
16380
  "assignment",
16296
16381
  "event",
@@ -16302,17 +16387,17 @@ function validReport(v) {
16302
16387
  ))
16303
16388
  return false;
16304
16389
  if (v.receiptOutcomes !== void 0 && (!Array.isArray(v.receiptOutcomes) || v.receiptOutcomes.length > 6856 || !v.receiptOutcomes.every(
16305
- (r) => record(r) && text(r.receiptId) && text(r.stage) && text(r.producerContract) && record(r.scope) && [r.scope.experimentId, r.scope.variationId, r.scope.goalId].every(
16390
+ (r) => record2(r) && text(r.receiptId) && text(r.stage) && text(r.producerContract) && record2(r.scope) && [r.scope.experimentId, r.scope.variationId, r.scope.goalId].every(
16306
16391
  (x) => x === null || text(x)
16307
16392
  ) && member(r.freshness, ["current", "stale", "unknown"]) && Array.isArray(r.reasonCodes) && r.reasonCodes.every(reason)
16308
16393
  )))
16309
16394
  return false;
16310
16395
  const coverage = v.assignmentCoverage;
16311
- if (!record(coverage) || typeof coverage.complete !== "boolean" || typeof coverage.overflowCountIsLowerBound !== "boolean" || !(coverage.overflowCount === null || count(coverage.overflowCount)))
16396
+ if (!record2(coverage) || typeof coverage.complete !== "boolean" || typeof coverage.overflowCountIsLowerBound !== "boolean" || !(coverage.overflowCount === null || count(coverage.overflowCount)))
16312
16397
  return false;
16313
16398
  return Array.isArray(v.assignments) && v.assignments.length <= 50 && v.assignments.every(
16314
- (a) => record(a) && text(a.experimentId) && text(a.variationId) && (a.storedAttribution === null || typeof a.storedAttribution === "boolean") && reason(a.reasonCode) && Array.isArray(a.goals) && a.goals.length <= 50 && a.goals.every(
16315
- (g) => record(g) && text(g.goalId) && member(g.status, [
16399
+ (a) => record2(a) && text(a.experimentId) && text(a.variationId) && (a.storedAttribution === null || typeof a.storedAttribution === "boolean") && reason(a.reasonCode) && Array.isArray(a.goals) && a.goals.length <= 50 && a.goals.every(
16400
+ (g) => record2(g) && text(g.goalId) && member(g.status, [
16316
16401
  "eligible_for_attributed_goal_read",
16317
16402
  "excluded_from_attributed_goal_read",
16318
16403
  "unknown"
@@ -16683,7 +16768,7 @@ var PURCHASE_CADENCE_WINDOW_MINUTES = PURCHASE_WINDOW_MINUTES * 4;
16683
16768
  var MIN_CAPTURE_WINDOW_MINUTES = 60;
16684
16769
  var DUPLICATE_RATE_THRESHOLD = 0.02;
16685
16770
  var MAGNITUDE_TOLERANCE_RATE = 0.1;
16686
- function record2(value) {
16771
+ function record3(value) {
16687
16772
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
16688
16773
  }
16689
16774
  function purchasePlane(config) {
@@ -16691,8 +16776,8 @@ function purchasePlane(config) {
16691
16776
  const names = [];
16692
16777
  const triggers = config.runtime?.dataLayerTriggers ?? config.dataLayerTriggers;
16693
16778
  if (Array.isArray(triggers) && triggers.some((trigger) => {
16694
- const row = record2(trigger);
16695
- const trackRevenue = record2(row?.trackRevenue);
16779
+ const row = record3(trigger);
16780
+ const trackRevenue = record3(row?.trackRevenue);
16696
16781
  return row?.enabled !== false && trackRevenue !== null && trackRevenue.enabled !== false;
16697
16782
  }))
16698
16783
  names.push("dataLayer trigger");
@@ -16734,7 +16819,7 @@ function lineItemSum(value) {
16734
16819
  if (!Array.isArray(value)) return null;
16735
16820
  let sum = 0;
16736
16821
  for (const item of value) {
16737
- const row = record2(item);
16822
+ const row = record3(item);
16738
16823
  const price = numeric(row?.price);
16739
16824
  if (price === null) return null;
16740
16825
  sum += price * (numeric(row?.quantity) ?? 1);
@@ -18274,10 +18359,10 @@ function getEdgeDeliveryStatus(deliveryType, expectedWorstCaseSeconds = 360) {
18274
18359
  return deliveryType === "api" ? { edge_delivery: "not_applicable", message: `API-delivered flag \u2014 edge delivery is not applicable. A previously cached visual payload may remain at some PoPs for up to ~${expectedWorstCaseSeconds}s; a single-vantage status cannot prove global propagation.` } : { edge_delivery: "applicable", message: null };
18275
18360
  }
18276
18361
  function parsePublicationMetadata(value) {
18277
- const record3 = value && typeof value === "object" ? value : {};
18362
+ const record4 = value && typeof value === "object" ? value : {};
18278
18363
  return {
18279
- publication_revision: Number.isSafeInteger(record3.publication_revision) && record3.publication_revision >= 0 ? record3.publication_revision : null,
18280
- generated_at: typeof record3.generated_at === "string" && !Number.isNaN(Date.parse(record3.generated_at)) ? record3.generated_at : null
18364
+ publication_revision: Number.isSafeInteger(record4.publication_revision) && record4.publication_revision >= 0 ? record4.publication_revision : null,
18365
+ generated_at: typeof record4.generated_at === "string" && !Number.isNaN(Date.parse(record4.generated_at)) ? record4.generated_at : null
18281
18366
  };
18282
18367
  }
18283
18368
  function compareEdgePublication(currentValue, edgeValue, expectedWorstCaseSeconds, flagUpdatedAtValue, confirmedAt = (/* @__PURE__ */ new Date()).toISOString()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drip-apex/apex-cli",
3
- "version": "0.14.1",
3
+ "version": "0.14.2",
4
4
  "license": "MIT",
5
5
  "description": "Apex CLI for managing experiments, approved roadmap ideas, and draft workspaces.",
6
6
  "private": false,