@wix/himalaya-cli 0.1110.0 → 0.1111.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/dist/cli.mjs CHANGED
@@ -994,8 +994,8 @@ function mobileUxDocumentBody(mobile) {
994
994
  }
995
995
  return out2 + mobile.slice(last);
996
996
  }
997
- function mobileUxSection(text6, heading) {
998
- const match = new RegExp(`(?:^|\\n)##[ \\t]+${heading}\\b[^\\n]*([\\s\\S]*?)(?=\\n##[ \\t]|$)`, "i").exec(text6);
997
+ function mobileUxSection(text8, heading) {
998
+ const match = new RegExp(`(?:^|\\n)##[ \\t]+${heading}\\b[^\\n]*([\\s\\S]*?)(?=\\n##[ \\t]|$)`, "i").exec(text8);
999
999
  return match ? match[1] : null;
1000
1000
  }
1001
1001
  function sectionTables(markdown) {
@@ -1024,8 +1024,8 @@ function namesOneCta(cell) {
1024
1024
  if (!cell) return false;
1025
1025
  return !/[,;]|\s\/\s/.test(cell);
1026
1026
  }
1027
- function declaredStates(text6) {
1028
- const contract = section(text6, "Screen contract");
1027
+ function declaredStates(text8) {
1028
+ const contract = section(text8, "Screen contract");
1029
1029
  if (!contract) return [];
1030
1030
  const states = [];
1031
1031
  for (const bullet of contract.matchAll(/^[ \t]*[-*][ \t]*[^:\n]*\bstates?[ \t]*:[ \t]*(\S.*)$/gim)) {
@@ -1035,8 +1035,8 @@ function declaredStates(text6) {
1035
1035
  }
1036
1036
  return [...new Set(states.map((state) => state.toLowerCase()))];
1037
1037
  }
1038
- function primaryCtaStructureGap(text6) {
1039
- const acceptance = section(text6, "Implementation acceptance");
1038
+ function primaryCtaStructureGap(text8) {
1039
+ const acceptance = section(text8, "Implementation acceptance");
1040
1040
  if (acceptance === null) return "There is no `## Implementation acceptance` section to read it from.";
1041
1041
  const tables = sectionTables(acceptance).filter((table) => table.data.length > 0);
1042
1042
  if (!tables.length) return "Its acceptance table has no rows.";
@@ -1049,7 +1049,7 @@ function primaryCtaStructureGap(text6) {
1049
1049
  const data = ctaTables.flatMap(({ table }) => table.data);
1050
1050
  const flat = (value) => value.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
1051
1051
  const rowText = data.map((row) => flat(row.join(" ")));
1052
- const missing = declaredStates(text6).filter((state) => !rowText.some((row) => row.includes(flat(state))));
1052
+ const missing = declaredStates(text8).filter((state) => !rowText.some((row) => row.includes(flat(state))));
1053
1053
  if (missing.length) return `The acceptance table has no row for the declared state(s): ${missing.join(", ")}.`;
1054
1054
  return null;
1055
1055
  }
@@ -1064,16 +1064,16 @@ function hasUnterminatedComment(mobile) {
1064
1064
  }
1065
1065
  }
1066
1066
  function mobileUxMarkerFindings(mobile, renderedWidths = []) {
1067
- const text6 = mobileUxDocumentBody(mobile);
1067
+ const text8 = mobileUxDocumentBody(mobile);
1068
1068
  const findings = [];
1069
- if (!/^## Implementation acceptance\b/im.test(text6)) {
1069
+ if (!/^## Implementation acceptance\b/im.test(text8)) {
1070
1070
  findings.push({ code: "missing-acceptance-matrix", message: "MOBILE-UX.md must contain the heading `## Implementation acceptance` at the start of a line. Case is not checked, but use this spelling: other tooling addresses the document by it." });
1071
1071
  }
1072
- if (!/^## Evidence\b/im.test(text6)) {
1072
+ if (!/^## Evidence\b/im.test(text8)) {
1073
1073
  findings.push({ code: "missing-evidence-section", message: "MOBILE-UX.md must contain the heading `## Evidence` at the start of a line. Case is not checked, but use this spelling: other tooling addresses the document by it." });
1074
1074
  }
1075
- if (!/one primary CTA per state/i.test(text6)) {
1076
- const gap = primaryCtaStructureGap(text6);
1075
+ if (!/one primary CTA per state/i.test(text8)) {
1076
+ const gap = primaryCtaStructureGap(text8);
1077
1077
  if (gap) {
1078
1078
  findings.push({
1079
1079
  code: "missing-primary-cta-rule",
@@ -1081,8 +1081,8 @@ function mobileUxMarkerFindings(mobile, renderedWidths = []) {
1081
1081
  });
1082
1082
  }
1083
1083
  }
1084
- if (!hasWidthEvidence(text6, renderedWidths)) {
1085
- findings.push({ code: "missing-width-evidence", message: widthEvidenceMessage(text6, renderedWidths) });
1084
+ if (!hasWidthEvidence(text8, renderedWidths)) {
1085
+ findings.push({ code: "missing-width-evidence", message: widthEvidenceMessage(text8, renderedWidths) });
1086
1086
  }
1087
1087
  if (findings.length && hasUnterminatedComment(mobile)) {
1088
1088
  return [{
@@ -1092,15 +1092,15 @@ function mobileUxMarkerFindings(mobile, renderedWidths = []) {
1092
1092
  }
1093
1093
  return findings;
1094
1094
  }
1095
- function widthMentions(text6) {
1095
+ function widthMentions(text8) {
1096
1096
  const mentions = [];
1097
- for (const match of text6.matchAll(/\d+/g)) {
1097
+ for (const match of text8.matchAll(/\d+/g)) {
1098
1098
  const value = Number(match[0]);
1099
1099
  const start = match.index ?? 0;
1100
1100
  if (!inRange(value)) continue;
1101
1101
  const end = start + match[0].length;
1102
- const after = text6.slice(end, end + EDGE_WINDOW);
1103
- const before = text6.slice(Math.max(0, start - EDGE_WINDOW), start);
1102
+ const after = text8.slice(end, end + EDGE_WINDOW);
1103
+ const before = text8.slice(Math.max(0, start - EDGE_WINDOW), start);
1104
1104
  if (looksLikeYear(value) && !(UNIT_ATTACHED.test(after) || UNIT_WORD_ATTACHED.test(after))) continue;
1105
1105
  const spelledAsWidth = UNIT_ATTACHED.test(after) || UNIT_WORD_ATTACHED.test(after) || FILENAME_AFTER.test(after);
1106
1106
  const vetoed = spelledAsWidth && (ANTI_CUE_BEFORE.test(before) || PAIR_HEIGHT_BEFORE.test(before) || ANTI_CUE_AFTER.test(after));
@@ -2093,7 +2093,7 @@ function foldLegacyReport(legacy, seed2) {
2093
2093
  ...arrayField(legacy.failures),
2094
2094
  ...arrayField(legacy.warnings)
2095
2095
  ];
2096
- const report2 = emptyReport({
2096
+ const report3 = emptyReport({
2097
2097
  ...seed2,
2098
2098
  ok: typeof legacy.ok === "boolean" ? legacy.ok : seed2.ok,
2099
2099
  app: seed2.app ?? stringField(legacy.app),
@@ -2104,12 +2104,12 @@ function foldLegacyReport(legacy, seed2) {
2104
2104
  const oldCounts = recordField(legacy.counts);
2105
2105
  return {
2106
2106
  ...legacy,
2107
- ...report2,
2107
+ ...report3,
2108
2108
  counts: {
2109
2109
  ...oldCounts,
2110
- errors: numberField(oldCounts.errors) ?? report2.counts.errors,
2111
- warnings: numberField(oldCounts.warnings) ?? report2.counts.warnings,
2112
- gaps: report2.counts.gaps
2110
+ errors: numberField(oldCounts.errors) ?? report3.counts.errors,
2111
+ warnings: numberField(oldCounts.warnings) ?? report3.counts.warnings,
2112
+ gaps: report3.counts.gaps
2113
2113
  }
2114
2114
  };
2115
2115
  }
@@ -2773,8 +2773,8 @@ function isAttestationV2(value) {
2773
2773
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
2774
2774
  const a = value;
2775
2775
  const coverage = a.coverage;
2776
- const report2 = a.report;
2777
- return a.attestation === 2 && typeof a.runId === "string" && ["himi-test", "himi-render", "himi-shots"].includes(a.tool) && [a.app, a.contentDir, a.gitDiffHash, a.gitUntrackedHash, a.releaseId, a.releaseHash, a.selfHash].every((item) => typeof item === "string" && item.length > 0) && stringRecord(a.descriptorHashes) && stringRecord(a.screenshots) && !!coverage && [coverage.screens, coverage.actionsDispatched, coverage.uncoveredFns, coverage.gaps].every((count2) => typeof count2 === "number" && Number.isFinite(count2) && count2 >= 0) && typeof report2?.ok === "boolean" && !!report2.counts && [report2.counts.errors, report2.counts.warnings, report2.counts.gaps].every((count2) => typeof count2 === "number" && Number.isFinite(count2) && count2 >= 0) && (a.prev === null || typeof a.prev === "string");
2776
+ const report3 = a.report;
2777
+ return a.attestation === 2 && typeof a.runId === "string" && ["himi-test", "himi-render", "himi-shots"].includes(a.tool) && [a.app, a.contentDir, a.gitDiffHash, a.gitUntrackedHash, a.releaseId, a.releaseHash, a.selfHash].every((item) => typeof item === "string" && item.length > 0) && stringRecord(a.descriptorHashes) && stringRecord(a.screenshots) && !!coverage && [coverage.screens, coverage.actionsDispatched, coverage.uncoveredFns, coverage.gaps].every((count2) => typeof count2 === "number" && Number.isFinite(count2) && count2 >= 0) && typeof report3?.ok === "boolean" && !!report3.counts && [report3.counts.errors, report3.counts.warnings, report3.counts.gaps].every((count2) => typeof count2 === "number" && Number.isFinite(count2) && count2 >= 0) && (a.prev === null || typeof a.prev === "string");
2778
2778
  }
2779
2779
  function readLatestAttestation(contentDir2) {
2780
2780
  try {
@@ -3170,8 +3170,8 @@ function penalty(m, size) {
3170
3170
  score += Math.floor(Math.abs(dark * 20 - total * 10) / total) * 10;
3171
3171
  return score;
3172
3172
  }
3173
- function encodeQr(text6) {
3174
- const bytes2 = [...new TextEncoder().encode(text6)];
3173
+ function encodeQr(text8) {
3174
+ const bytes2 = [...new TextEncoder().encode(text8)];
3175
3175
  const version2 = fitVersion(bytes2.length);
3176
3176
  if (!version2) {
3177
3177
  throw new RangeError(`QR payload too long: ${bytes2.length} bytes exceeds version ${QR_MAX_VERSION} at EC level L`);
@@ -3742,7 +3742,7 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
3742
3742
  tokenCache.set(cacheKey, fromEnv);
3743
3743
  return fromEnv;
3744
3744
  }
3745
- const token = await new Promise((resolve52, reject) => {
3745
+ const token = await new Promise((resolve53, reject) => {
3746
3746
  let child;
3747
3747
  try {
3748
3748
  child = spawnImpl("wix", [...args]);
@@ -3771,12 +3771,12 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
3771
3771
  child.stdout?.on("data", (d) => {
3772
3772
  out2 += String(d);
3773
3773
  const m = out2.match(TOKEN_RE);
3774
- if (m) done(() => resolve52(m[0]));
3774
+ if (m) done(() => resolve53(m[0]));
3775
3775
  });
3776
3776
  child.stderr?.on("data", (d) => {
3777
3777
  out2 += String(d);
3778
3778
  const m = out2.match(TOKEN_RE);
3779
- if (m) done(() => resolve52(m[0]));
3779
+ if (m) done(() => resolve53(m[0]));
3780
3780
  });
3781
3781
  child.on("error", (e) => done(() => reject(new Error(mintHelp(label2, e.message)))));
3782
3782
  child.on("exit", (code) => done(() => reject(new Error(
@@ -3821,10 +3821,10 @@ function ownerTransport(msid, fetchImpl = fetch, timeoutMs = DEFAULT_TIMEOUT_MS2
3821
3821
  }
3822
3822
  throw new Error(`${method} ${path2} failed: ${err?.message ?? String(e)}`);
3823
3823
  }
3824
- const text6 = await res.text();
3825
- let parsed = text6;
3824
+ const text8 = await res.text();
3825
+ let parsed = text8;
3826
3826
  try {
3827
- parsed = text6 ? JSON.parse(text6) : null;
3827
+ parsed = text8 ? JSON.parse(text8) : null;
3828
3828
  } catch {
3829
3829
  }
3830
3830
  if (!res.ok) throw new WixApiError(res.status, method, path2, parsed);
@@ -4486,18 +4486,18 @@ function confinementPlugin(contentRoot) {
4486
4486
  }
4487
4487
  function assertConfinedTsconfig(entry, contentRoot, allows) {
4488
4488
  const seen = /* @__PURE__ */ new Set();
4489
- const refuse4 = (p, why) => {
4489
+ const refuse5 = (p, why) => {
4490
4490
  throw new Error(
4491
4491
  `refused to read ${p}: ${why}. A tsconfig may extend a file from its own package or an installed dependency \u2014 nothing else.`
4492
4492
  );
4493
4493
  };
4494
- const stripJsonc = (text6) => {
4495
- if (text6.charCodeAt(0) === 65279) text6 = text6.slice(1);
4494
+ const stripJsonc = (text8) => {
4495
+ if (text8.charCodeAt(0) === 65279) text8 = text8.slice(1);
4496
4496
  let out2 = "";
4497
4497
  let inStr = false;
4498
4498
  let esc = false;
4499
- for (let i = 0; i < text6.length; i++) {
4500
- const c = text6[i];
4499
+ for (let i = 0; i < text8.length; i++) {
4500
+ const c = text8[i];
4501
4501
  if (inStr) {
4502
4502
  out2 += c;
4503
4503
  if (esc) esc = false;
@@ -4510,13 +4510,13 @@ function assertConfinedTsconfig(entry, contentRoot, allows) {
4510
4510
  out2 += c;
4511
4511
  continue;
4512
4512
  }
4513
- if (c === "/" && text6[i + 1] === "/") {
4514
- while (i < text6.length && text6[i] !== "\n") i++;
4513
+ if (c === "/" && text8[i + 1] === "/") {
4514
+ while (i < text8.length && text8[i] !== "\n") i++;
4515
4515
  continue;
4516
4516
  }
4517
- if (c === "/" && text6[i + 1] === "*") {
4517
+ if (c === "/" && text8[i + 1] === "*") {
4518
4518
  i += 2;
4519
- while (i < text6.length && !(text6[i] === "*" && text6[i + 1] === "/")) i++;
4519
+ while (i < text8.length && !(text8[i] === "*" && text8[i + 1] === "/")) i++;
4520
4520
  i++;
4521
4521
  continue;
4522
4522
  }
@@ -4552,7 +4552,7 @@ function assertConfinedTsconfig(entry, contentRoot, allows) {
4552
4552
  try {
4553
4553
  manifest = JSON.parse(stripJsonc(readFileSync10(pj, "utf8")));
4554
4554
  } catch {
4555
- refuse4(pj, "its package.json could not be parsed, so its `tsconfig` field cannot be checked");
4555
+ refuse5(pj, "its package.json could not be parsed, so its `tsconfig` field cannot be checked");
4556
4556
  }
4557
4557
  const field = manifest?.tsconfig;
4558
4558
  if (typeof field === "string" && field) {
@@ -4568,7 +4568,7 @@ function assertConfinedTsconfig(entry, contentRoot, allows) {
4568
4568
  const real = realpathOrSelf(file);
4569
4569
  if (seen.has(real)) return;
4570
4570
  seen.add(real);
4571
- if (!allows(real)) refuse4(file, "it is outside this content package");
4571
+ if (!allows(real)) refuse5(file, "it is outside this content package");
4572
4572
  let raw;
4573
4573
  try {
4574
4574
  raw = readFileSync10(real, "utf8");
@@ -4579,7 +4579,7 @@ function assertConfinedTsconfig(entry, contentRoot, allows) {
4579
4579
  try {
4580
4580
  parsed = JSON.parse(stripJsonc(raw));
4581
4581
  } catch {
4582
- refuse4(file, "its tsconfig could not be parsed, so its `extends` cannot be checked");
4582
+ refuse5(file, "its tsconfig could not be parsed, so its `extends` cannot be checked");
4583
4583
  }
4584
4584
  const ext = parsed?.extends;
4585
4585
  for (const one of Array.isArray(ext) ? ext : ext ? [ext] : []) {
@@ -8420,8 +8420,8 @@ function pushSpan(out2, s) {
8420
8420
  else out2.push(s);
8421
8421
  }
8422
8422
  function spanOf(textNode) {
8423
- const text6 = str(at(textNode, "textData", "text"));
8424
- if (text6 === "") return null;
8423
+ const text8 = str(at(textNode, "textData", "text"));
8424
+ if (text8 === "") return null;
8425
8425
  let bold = false, italic = false, underline = false;
8426
8426
  let link;
8427
8427
  const decorations = at(textNode, "textData", "decorations");
@@ -8448,7 +8448,7 @@ function spanOf(textNode) {
8448
8448
  }
8449
8449
  }
8450
8450
  }
8451
- const span = { text: text6 };
8451
+ const span = { text: text8 };
8452
8452
  if (bold) span.bold = true;
8453
8453
  if (italic) span.italic = true;
8454
8454
  if (underline) span.underline = true;
@@ -8670,8 +8670,8 @@ function blockOf(ids, n, path2) {
8670
8670
  const { title, url } = cardFields(n, type);
8671
8671
  return [card(ids.claim(n, path2), type, title, url)];
8672
8672
  }
8673
- const text6 = plainText(n);
8674
- return text6.trim() !== "" ? [{ kind: "paragraph", id: ids.claim(n, path2), spans: [{ text: text6 }] }] : [];
8673
+ const text8 = plainText(n);
8674
+ return text8.trim() !== "" ? [{ kind: "paragraph", id: ids.claim(n, path2), spans: [{ text: text8 }] }] : [];
8675
8675
  }
8676
8676
  }
8677
8677
  }
@@ -9942,26 +9942,26 @@ function serviceOnlyBindingValues(props, key2) {
9942
9942
  });
9943
9943
  return out2;
9944
9944
  }
9945
- function matchBraceSafe(text6, open) {
9945
+ function matchBraceSafe(text8, open) {
9946
9946
  let depth = 0;
9947
- for (let i = open; i < text6.length; i++) {
9948
- const c = text6[i];
9947
+ for (let i = open; i < text8.length; i++) {
9948
+ const c = text8[i];
9949
9949
  if (c === '"' || c === "'" || c === "`") {
9950
9950
  const q = c;
9951
9951
  i++;
9952
- while (i < text6.length && text6[i] !== q) {
9953
- if (text6[i] === "\\") i++;
9952
+ while (i < text8.length && text8[i] !== q) {
9953
+ if (text8[i] === "\\") i++;
9954
9954
  i++;
9955
9955
  }
9956
9956
  continue;
9957
9957
  }
9958
- if (c === "/" && text6[i + 1] === "/") {
9959
- while (i < text6.length && text6[i] !== "\n") i++;
9958
+ if (c === "/" && text8[i + 1] === "/") {
9959
+ while (i < text8.length && text8[i] !== "\n") i++;
9960
9960
  continue;
9961
9961
  }
9962
- if (c === "/" && text6[i + 1] === "*") {
9962
+ if (c === "/" && text8[i + 1] === "*") {
9963
9963
  i += 2;
9964
- while (i < text6.length && !(text6[i] === "*" && text6[i + 1] === "/")) i++;
9964
+ while (i < text8.length && !(text8[i] === "*" && text8[i + 1] === "/")) i++;
9965
9965
  i++;
9966
9966
  continue;
9967
9967
  }
@@ -12909,8 +12909,8 @@ var init_owner_claim = __esm({
12909
12909
 
12910
12910
  // ../native-config/car.ts
12911
12911
  function parseCarConfig(configTs) {
12912
- const { text: text6, inString } = scanConfig(configTs);
12913
- for (const m of text6.matchAll(/\bcar\s*[:=]\s*\{([^}]*)\}/g)) {
12912
+ const { text: text8, inString } = scanConfig(configTs);
12913
+ for (const m of text8.matchAll(/\bcar\s*[:=]\s*\{([^}]*)\}/g)) {
12914
12914
  if (inString[m.index]) continue;
12915
12915
  return { category: /category\s*:\s*["']([^"']+)["']/.exec(m[1])?.[1] };
12916
12916
  }
@@ -17996,12 +17996,12 @@ function hostAppliesDeferredWidgetActions(app) {
17996
17996
  }
17997
17997
  return false;
17998
17998
  }
17999
- function hasMarkers(text6, kind, label2) {
18000
- const lines = text6.split("\n");
17999
+ function hasMarkers(text8, kind, label2) {
18000
+ const lines = text8.split("\n");
18001
18001
  return lines.some((l) => isBegin(l, kind, label2)) && lines.some((l) => isEnd(l, kind, label2));
18002
18002
  }
18003
- function injectBlock(text6, kind, label2, render) {
18004
- const lines = text6.split("\n");
18003
+ function injectBlock(text8, kind, label2, render) {
18004
+ const lines = text8.split("\n");
18005
18005
  const beginIdx = lines.findIndex((l) => isBegin(l, kind, label2));
18006
18006
  const endIdx = lines.findIndex((l) => isEnd(l, kind, label2));
18007
18007
  if (beginIdx === -1 || endIdx === -1 || endIdx < beginIdx) {
@@ -18116,8 +18116,8 @@ function genNativeConfig(app, opts = {}) {
18116
18116
  ];
18117
18117
  const rce = declaresRichContentEditor(configTs);
18118
18118
  for (const yml of [iosYml, macosProjectYml(app)]) {
18119
- const text6 = existsSync26(yml) ? readFileSync26(yml, "utf8") : "";
18120
- const r = applyToFile(yml, "yaml", LABEL_LOCALWEB, renderLocalWebYaml(resourcesDirOf(text6), rce), check);
18119
+ const text8 = existsSync26(yml) ? readFileSync26(yml, "utf8") : "";
18120
+ const r = applyToFile(yml, "yaml", LABEL_LOCALWEB, renderLocalWebYaml(resourcesDirOf(text8), rce), check);
18121
18121
  if (existsSync26(yml)) assertLocalWebBlockLanded(app, rce, yml, r.outcome);
18122
18122
  files.push(r);
18123
18123
  }
@@ -18527,21 +18527,21 @@ function carryPlanningJournal(parentDir, appDir3) {
18527
18527
  return carried;
18528
18528
  }
18529
18529
  function formatBrief(input) {
18530
- const { summary, open } = input;
18530
+ const { summary: summary2, open } = input;
18531
18531
  const who = `himi \u2014 ${input.appName ?? "this folder"}`;
18532
18532
  const lines = [];
18533
- if (!summary.count) {
18533
+ if (!summary2.count) {
18534
18534
  lines.push(`${who}: no journey journal yet (${PROGRESS_FILE.split(sep6).join("/")}).`);
18535
18535
  lines.push(
18536
18536
  'A new app starts with discovery (step 1). An app built before journaling existed continues from its current state instead: confirm with the customer that its SPEC.md was approved rather than re-running discovery. Either way, journal each milestone with `himi progress "<what changed>" --step <n>` so the next session can pick up from it.'
18537
18537
  );
18538
18538
  } else {
18539
- const at2 = summary.current ? `journey step ${summary.current.stepNumber}/${summary.current.of} (${summary.current.step})` : "no journey step recorded yet";
18540
- lines.push(`${who}: ${at2} \xB7 ${summary.count} postcard${summary.count === 1 ? "" : "s"} since ${minute(summary.startedAt)}.`);
18541
- if (summary.last) lines.push(`Last postcard (${minute(summary.last.ts)}): ${summary.last.message}`);
18542
- const pastPlan = (summary.current?.stepNumber ?? 0) > JOURNEY_STEPS.indexOf("plan") + 1;
18539
+ const at2 = summary2.current ? `journey step ${summary2.current.stepNumber}/${summary2.current.of} (${summary2.current.step})` : "no journey step recorded yet";
18540
+ lines.push(`${who}: ${at2} \xB7 ${summary2.count} postcard${summary2.count === 1 ? "" : "s"} since ${minute(summary2.startedAt)}.`);
18541
+ if (summary2.last) lines.push(`Last postcard (${minute(summary2.last.ts)}): ${summary2.last.message}`);
18542
+ const pastPlan = (summary2.current?.stepNumber ?? 0) > JOURNEY_STEPS.indexOf("plan") + 1;
18543
18543
  lines.push(
18544
- !summary.current ? "No journey step recorded yet: a new app starts with discovery (step 1); one whose SPEC.md the customer approved continues from its current state. `himi progress` prints every postcard." : pastPlan ? `Resume at step ${summary.current.stepNumber}. Do not restart discovery: the approved plan is SPEC.md + MOBILE-UX.md.` : `Resume at step ${summary.current.stepNumber}. Implementation has not started: treat SPEC.md + MOBILE-UX.md as a draft unless the journal records the customer approving them.`
18544
+ !summary2.current ? "No journey step recorded yet: a new app starts with discovery (step 1); one whose SPEC.md the customer approved continues from its current state. `himi progress` prints every postcard." : pastPlan ? `Resume at step ${summary2.current.stepNumber}. Do not restart discovery: the approved plan is SPEC.md + MOBILE-UX.md.` : `Resume at step ${summary2.current.stepNumber}. Implementation has not started: treat SPEC.md + MOBILE-UX.md as a draft unless the journal records the customer approving them.`
18545
18545
  );
18546
18546
  }
18547
18547
  if (open.length) {
@@ -19465,10 +19465,10 @@ var init_preview = __esm({
19465
19465
  }
19466
19466
  },
19467
19467
  kill: (pid, signal) => process.kill(pid, signal),
19468
- portFree: (port) => new Promise((resolve52) => {
19468
+ portFree: (port) => new Promise((resolve53) => {
19469
19469
  const s = createServer2();
19470
- s.once("error", () => resolve52(false));
19471
- s.listen(port, "127.0.0.1", () => s.close(() => resolve52(true)));
19470
+ s.once("error", () => resolve53(false));
19471
+ s.listen(port, "127.0.0.1", () => s.close(() => resolve53(true)));
19472
19472
  }),
19473
19473
  sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
19474
19474
  servingIdentity: async (origin) => {
@@ -19652,17 +19652,17 @@ ${BLOCK_END}`;
19652
19652
  ${block}
19653
19653
  `;
19654
19654
  }
19655
- function markersIntact(text6) {
19656
- const begins = text6.split(BLOCK_BEGIN).length - 1;
19657
- const ends = text6.split(BLOCK_END).length - 1;
19655
+ function markersIntact(text8) {
19656
+ const begins = text8.split(BLOCK_BEGIN).length - 1;
19657
+ const ends = text8.split(BLOCK_END).length - 1;
19658
19658
  if (begins === 0 && ends === 0) return true;
19659
- return begins === 1 && ends === 1 && text6.indexOf(BLOCK_BEGIN) < text6.indexOf(BLOCK_END) && BLOCK_RE.test(text6);
19659
+ return begins === 1 && ends === 1 && text8.indexOf(BLOCK_BEGIN) < text8.indexOf(BLOCK_END) && BLOCK_RE.test(text8);
19660
19660
  }
19661
- function withoutBlock(text6) {
19662
- const m = BLOCK_RE.exec(text6);
19663
- if (!m) return text6;
19664
- const before = text6.slice(0, m.index).replace(/\n+$/, "");
19665
- const after = text6.slice(m.index + m[0].length).replace(/^\n+/, "");
19661
+ function withoutBlock(text8) {
19662
+ const m = BLOCK_RE.exec(text8);
19663
+ if (!m) return text8;
19664
+ const before = text8.slice(0, m.index).replace(/\n+$/, "");
19665
+ const after = text8.slice(m.index + m[0].length).replace(/^\n+/, "");
19666
19666
  if (!before) return after;
19667
19667
  if (!after) return `${before}
19668
19668
  `;
@@ -19670,8 +19670,8 @@ function withoutBlock(text6) {
19670
19670
 
19671
19671
  ${after}`;
19672
19672
  }
19673
- function blockVersion(text6) {
19674
- return STAMP_RE.exec(text6)?.[1] ?? null;
19673
+ function blockVersion(text8) {
19674
+ return STAMP_RE.exec(text8)?.[1] ?? null;
19675
19675
  }
19676
19676
  function agentsMdBody(appName2) {
19677
19677
  const gates = APPROVAL_GATES.map((g) => `- \`${g.id}\` \u2014 ${g.label}`).join("\n");
@@ -20612,7 +20612,7 @@ async function injectRequest(listener, request) {
20612
20612
  req.headers.host ??= url.host;
20613
20613
  if (body && body.length > 0) req.push(body);
20614
20614
  req.push(null);
20615
- return await new Promise((resolve52, reject) => {
20615
+ return await new Promise((resolve53, reject) => {
20616
20616
  const streamed = () => {
20617
20617
  queueMicrotask(() => {
20618
20618
  req.emit("close");
@@ -20628,7 +20628,7 @@ async function injectRequest(listener, request) {
20628
20628
  else headers2.set(name, value);
20629
20629
  }
20630
20630
  const bodyless = out2.status === 204 || out2.status === 304 || request.method === "HEAD";
20631
- resolve52(new Response(bodyless ? null : out2.body, { status: out2.status, headers: headers2 }));
20631
+ resolve53(new Response(bodyless ? null : out2.body, { status: out2.status, headers: headers2 }));
20632
20632
  }, streamed);
20633
20633
  res.on("inject-error", reject);
20634
20634
  try {
@@ -21166,8 +21166,8 @@ async function postJson(path2, body, auth) {
21166
21166
  headers: { "Content-Type": "application/json", ...auth ? { Authorization: auth } : {} },
21167
21167
  body: JSON.stringify(body)
21168
21168
  });
21169
- const text6 = await res.text();
21170
- return { status: res.status, json: text6 ? JSON.parse(text6) : {} };
21169
+ const text8 = await res.text();
21170
+ return { status: res.status, json: text8 ? JSON.parse(text8) : {} };
21171
21171
  }
21172
21172
  async function mintVisitor(clientId) {
21173
21173
  const r = await postJson("/oauth2/token", { clientId, grantType: "anonymous" });
@@ -21413,13 +21413,13 @@ function recordWixTraffic(gw, app, adminUrl, ev) {
21413
21413
  full.respBody = truncate(redactBodyString(full.respBody));
21414
21414
  gw.traffic.push(full);
21415
21415
  if (gw.traffic.length > TRAFFIC_CAP) gw.traffic.splice(0, gw.traffic.length - TRAFFIC_CAP);
21416
- const text6 = `event: wix.traffic
21416
+ const text8 = `event: wix.traffic
21417
21417
  data: ${JSON.stringify(full)}
21418
21418
 
21419
21419
  `;
21420
21420
  for (const res of [...gw.clients]) {
21421
21421
  try {
21422
- res.write(text6);
21422
+ res.write(text8);
21423
21423
  } catch {
21424
21424
  gw.clients.delete(res);
21425
21425
  }
@@ -21781,10 +21781,10 @@ async function mintAnonymousVisitor(clientId, fetchImpl = fetch) {
21781
21781
  headers: { "Content-Type": "application/json" },
21782
21782
  body: JSON.stringify({ clientId, grantType: "anonymous" })
21783
21783
  });
21784
- const text6 = await res.text();
21784
+ const text8 = await res.text();
21785
21785
  let j = {};
21786
21786
  try {
21787
- j = text6 ? JSON.parse(text6) : {};
21787
+ j = text8 ? JSON.parse(text8) : {};
21788
21788
  } catch {
21789
21789
  }
21790
21790
  if (res.status !== 200 || !j.access_token) throw new Error(`visitor mint failed (${res.status})`);
@@ -21948,10 +21948,10 @@ ${session}`);
21948
21948
  }),
21949
21949
  timedOut
21950
21950
  ]);
21951
- const text6 = await Promise.race([res.text(), timedOut]);
21951
+ const text8 = await Promise.race([res.text(), timedOut]);
21952
21952
  let j = {};
21953
21953
  try {
21954
- j = text6 ? JSON.parse(text6) : {};
21954
+ j = text8 ? JSON.parse(text8) : {};
21955
21955
  } catch {
21956
21956
  }
21957
21957
  if (res.status < 200 || res.status >= 300 || !j.signedInstance)
@@ -22302,9 +22302,9 @@ var init_images = __esm({
22302
22302
  });
22303
22303
 
22304
22304
  // ../../core/dev-server/src/l10n-catalog.ts
22305
- function parseCatalog(text6) {
22305
+ function parseCatalog(text8) {
22306
22306
  try {
22307
- const c = JSON.parse(text6);
22307
+ const c = JSON.parse(text8);
22308
22308
  return c && typeof c === "object" && c.messages && typeof c.messages === "object" ? c : void 0;
22309
22309
  } catch {
22310
22310
  return void 0;
@@ -22785,9 +22785,9 @@ async function getAndroidPixelDims(serial) {
22785
22785
  try {
22786
22786
  const args = serial ? ["-s", serial, "shell", "wm", "size"] : ["shell", "wm", "size"];
22787
22787
  const out2 = await runner.capture(ADB_BIN, args);
22788
- const text6 = out2.toString("utf8");
22789
- const override = /Override size:\s*(\d+)x(\d+)/.exec(text6);
22790
- const physical = /Physical size:\s*(\d+)x(\d+)/.exec(text6);
22788
+ const text8 = out2.toString("utf8");
22789
+ const override = /Override size:\s*(\d+)x(\d+)/.exec(text8);
22790
+ const physical = /Physical size:\s*(\d+)x(\d+)/.exec(text8);
22791
22791
  const m = override ?? physical;
22792
22792
  if (!m) throw new Error("could not parse wm size");
22793
22793
  const dims = { width: parseInt(m[1], 10), height: parseInt(m[2], 10) };
@@ -23162,12 +23162,12 @@ function finalizeRecording(key2, rec) {
23162
23162
  if (rec.finalize) return rec.finalize;
23163
23163
  rec.finalize = (async () => {
23164
23164
  clearTimeout(rec.autoStop);
23165
- await new Promise((resolve52) => {
23165
+ await new Promise((resolve53) => {
23166
23166
  let done = false;
23167
23167
  const finish2 = () => {
23168
23168
  if (!done) {
23169
23169
  done = true;
23170
- resolve52();
23170
+ resolve53();
23171
23171
  }
23172
23172
  };
23173
23173
  rec.child.once("close", finish2);
@@ -23278,7 +23278,7 @@ var init_preview2 = __esm({
23278
23278
  DEVICE_LIST_TIMEOUT_MS = 5e3;
23279
23279
  defaultRunner2 = {
23280
23280
  capture(cmd, args, timeoutMs = DEFAULT_CAPTURE_TIMEOUT_MS) {
23281
- return new Promise((resolve52, reject) => {
23281
+ return new Promise((resolve53, reject) => {
23282
23282
  const child = spawn4(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
23283
23283
  const out2 = [];
23284
23284
  const err = [];
@@ -23300,7 +23300,7 @@ var init_preview2 = __esm({
23300
23300
  child.stderr.on("data", (b) => err.push(b));
23301
23301
  child.on("error", (e) => settle(reject, e));
23302
23302
  child.on("close", (code) => {
23303
- if (code === 0) settle(resolve52, Buffer.concat(out2));
23303
+ if (code === 0) settle(resolve53, Buffer.concat(out2));
23304
23304
  else settle(reject, new Error(`${cmd} exited ${code}: ${Buffer.concat(err).toString("utf8")}`));
23305
23305
  });
23306
23306
  });
@@ -23720,7 +23720,7 @@ function buildOpenApi(descriptors) {
23720
23720
  // Widgets
23721
23721
  "/__dev/widget/preview": ["get", "Render a frozen widget snapshot."]
23722
23722
  };
23723
- for (const [p, [method, summary]] of Object.entries(control)) {
23723
+ for (const [p, [method, summary2]] of Object.entries(control)) {
23724
23724
  const responses = p === "/__dev/render" ? {
23725
23725
  "200": { description: "completed render (legacy mode, or clean envelope verdict)" },
23726
23726
  "400": { description: "invalid_json" },
@@ -23728,7 +23728,7 @@ function buildOpenApi(descriptors) {
23728
23728
  "422": { description: "completed render with a failing envelope:1 verdict" },
23729
23729
  "503": { description: "dev plane unavailable" }
23730
23730
  } : { "200": { description: "ok" } };
23731
- paths[p] = { [method]: { summary, responses } };
23731
+ paths[p] = { [method]: { summary: summary2, responses } };
23732
23732
  }
23733
23733
  for (const scope of ["net", "wix"]) {
23734
23734
  paths[`/__dev/${scope}/rules`] = {
@@ -24156,9 +24156,9 @@ function mdScan(src, linkStyle = "") {
24156
24156
  }
24157
24157
  return out2 + mdEsc(src.slice(last));
24158
24158
  }
24159
- function mdInline(text6, linkColor) {
24159
+ function mdInline(text8, linkColor) {
24160
24160
  const safe = typeof linkColor === "string" && /^[#a-zA-Z0-9(),.%\s-]+$/.test(linkColor) ? linkColor : "";
24161
- return { __html: mdScan(text6, safe ? ` style="color:${safe}"` : "") };
24161
+ return { __html: mdScan(text8, safe ? ` style="color:${safe}"` : "") };
24162
24162
  }
24163
24163
  function sevColor(ctx, sev) {
24164
24164
  switch (sev) {
@@ -27527,9 +27527,9 @@ function createRicosHostSession(o) {
27527
27527
  if (!state.ready || state.unavailable) return;
27528
27528
  o.send({ v: 1, type: "command", name, ...arg?.level ? { level: arg.level } : {}, ...arg?.value ? { value: arg.value } : {} });
27529
27529
  },
27530
- insertLink(url, text6) {
27530
+ insertLink(url, text8) {
27531
27531
  if (!state.ready || state.unavailable || !isSafeEditorLink(url)) return false;
27532
- o.send({ v: 1, type: "insertLink", url: url.trim(), ...text6 ? { text: text6 } : {} });
27532
+ o.send({ v: 1, type: "insertLink", url: url.trim(), ...text8 ? { text: text8 } : {} });
27533
27533
  return true;
27534
27534
  },
27535
27535
  removeLink() {
@@ -27552,12 +27552,12 @@ function createRicosHostSession(o) {
27552
27552
  flush() {
27553
27553
  if (!state.ready || state.unavailable || disposed) return Promise.resolve(null);
27554
27554
  const requestId2 = newId();
27555
- return new Promise((resolve52) => {
27555
+ return new Promise((resolve53) => {
27556
27556
  const timer = t.setTimeout(() => {
27557
27557
  flushes.delete(requestId2);
27558
- resolve52(null);
27558
+ resolve53(null);
27559
27559
  }, flushMs);
27560
- flushes.set(requestId2, { resolve: resolve52, timer });
27560
+ flushes.set(requestId2, { resolve: resolve53, timer });
27561
27561
  o.send({ v: 1, type: "requestContent", requestId: requestId2 });
27562
27562
  });
27563
27563
  },
@@ -27610,7 +27610,7 @@ async function runRicosImageUpload(o) {
27610
27610
  };
27611
27611
  session.insertMediaPlaceholder(requestId2);
27612
27612
  try {
27613
- const entry = await new Promise((resolve52) => {
27613
+ const entry = await new Promise((resolve53) => {
27614
27614
  let done = false;
27615
27615
  let unsub = () => {
27616
27616
  };
@@ -27619,7 +27619,7 @@ async function runRicosImageUpload(o) {
27619
27619
  done = true;
27620
27620
  t.clearTimeout(timer);
27621
27621
  queueMicrotask(() => unsub());
27622
- resolve52(v);
27622
+ resolve53(v);
27623
27623
  };
27624
27624
  const timer = t.setTimeout(() => finish2(null), o.timeoutMs ?? RICOS_UPLOAD_TIMEOUT_MS);
27625
27625
  unsub = deps.subscribe(`${svc}.uploads.${requestId2}`, (v) => {
@@ -29226,13 +29226,13 @@ function NamedImage({ node, alt, env }) {
29226
29226
  }
29227
29227
  function Block({ b, env, depth }) {
29228
29228
  const { ctx } = env;
29229
- const text6 = ctx.color("textPrimary", "#13171e");
29229
+ const text8 = ctx.color("textPrimary", "#13171e");
29230
29230
  const secondary = ctx.color("textSecondary", "#5c6370");
29231
29231
  const border = ctx.color("border", "#e5e5e5");
29232
29232
  switch (b.kind) {
29233
29233
  case "paragraph":
29234
29234
  return /* @__PURE__ */ jsx7("p", { ...tid(env, b.id, b.kind), style: {
29235
- ...textStyle(ctx, "body", text6),
29235
+ ...textStyle(ctx, "body", text8),
29236
29236
  textAlign: b.align,
29237
29237
  paddingInlineStart: b.indent ? Math.min(b.indent, 8) * 16 : void 0,
29238
29238
  minHeight: b.spans.length ? void 0 : "1.5em"
@@ -29240,7 +29240,7 @@ function Block({ b, env, depth }) {
29240
29240
  case "heading":
29241
29241
  return React6.createElement(
29242
29242
  `h${b.level}`,
29243
- { ...tid(env, b.id, b.kind), style: textStyle(ctx, RICH_CONTENT_HEADING_TOKENS[b.level - 1], text6) },
29243
+ { ...tid(env, b.id, b.kind), style: textStyle(ctx, RICH_CONTENT_HEADING_TOKENS[b.level - 1], text8) },
29244
29244
  /* @__PURE__ */ jsx7(Spans, { spans: b.spans, env })
29245
29245
  );
29246
29246
  case "list": {
@@ -29250,7 +29250,7 @@ function Block({ b, env, depth }) {
29250
29250
  {
29251
29251
  ...tid(env, b.id, b.kind),
29252
29252
  start: b.ordered ? b.start : void 0,
29253
- style: { ...textStyle(ctx, "body", text6), paddingInlineStart: 24, listStyleType: b.ordered ? "decimal" : depth % 2 ? "circle" : "disc" },
29253
+ style: { ...textStyle(ctx, "body", text8), paddingInlineStart: 24, listStyleType: b.ordered ? "decimal" : depth % 2 ? "circle" : "disc" },
29254
29254
  children: b.items.map((item, i) => /* @__PURE__ */ jsx7("li", { "data-component-id": `${env.componentId}/${item.id}`, id: `${env.componentId}/${item.id}`, style: { marginBottom: 6 }, children: /* @__PURE__ */ jsx7("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: item.blocks.map((child, j) => /* @__PURE__ */ jsx7(Block, { b: child, env, depth: depth + 1 }, `${j}:${child.id}`)) }) }, `${i}:${item.id}`))
29255
29255
  }
29256
29256
  );
@@ -29264,7 +29264,7 @@ function Block({ b, env, depth }) {
29264
29264
  overflowWrap: "anywhere",
29265
29265
  fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
29266
29266
  fontSize: "0.9em",
29267
- color: text6,
29267
+ color: text8,
29268
29268
  background: ctx.color("surfaceSecondary", "#f5f5f7"),
29269
29269
  padding: 10,
29270
29270
  borderRadius: 6
@@ -29283,11 +29283,11 @@ function Block({ b, env, depth }) {
29283
29283
  case "button":
29284
29284
  return /* @__PURE__ */ jsx7(LinkButton, { label: b.label, url: b.url, env, testId: `${env.componentId}/${b.id}` });
29285
29285
  case "table":
29286
- return /* @__PURE__ */ jsx7("table", { ...tid(env, b.id, b.kind), style: { width: "100%", borderCollapse: "collapse", ...textStyle(ctx, "body", text6) }, children: /* @__PURE__ */ jsx7("tbody", { children: b.rows.map((row, r) => /* @__PURE__ */ jsx7("tr", { children: row.map((cell, c) => /* @__PURE__ */ jsx7("td", { style: { border: `1px solid ${border}`, padding: 6, whiteSpace: "pre-wrap", verticalAlign: "top" }, children: cell }, c)) }, r)) }) });
29286
+ return /* @__PURE__ */ jsx7("table", { ...tid(env, b.id, b.kind), style: { width: "100%", borderCollapse: "collapse", ...textStyle(ctx, "body", text8) }, children: /* @__PURE__ */ jsx7("tbody", { children: b.rows.map((row, r) => /* @__PURE__ */ jsx7("tr", { children: row.map((cell, c) => /* @__PURE__ */ jsx7("td", { style: { border: `1px solid ${border}`, padding: 6, whiteSpace: "pre-wrap", verticalAlign: "top" }, children: cell }, c)) }, r)) }) });
29287
29287
  case "card": {
29288
29288
  const title = richContentCardTitle(b);
29289
29289
  return /* @__PURE__ */ jsxs4("div", { ...tid(env, b.id, b.kind), role: "group", "aria-label": title, style: { border: `1px solid ${border}`, borderRadius: 8, padding: 12, display: "flex", flexDirection: "column", gap: 6 }, children: [
29290
- /* @__PURE__ */ jsx7("div", { style: textStyle(ctx, "bodyEmphasis", text6), children: title }),
29290
+ /* @__PURE__ */ jsx7("div", { style: textStyle(ctx, "bodyEmphasis", text8), children: title }),
29291
29291
  b.url ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
29292
29292
  /* @__PURE__ */ jsx7("div", { style: textStyle(ctx, "caption", secondary), children: richContentHost(b.url) }),
29293
29293
  /* @__PURE__ */ jsx7(LinkButton, { label: RICH_CONTENT_OPEN_LABEL, url: b.url, env, testId: `${env.componentId}/${b.id}/open` })
@@ -30883,8 +30883,8 @@ function applyA11ySemantics(node, ctx, extra) {
30883
30883
  extra["aria-live"] = str9(announce.politeness) === "assertive" ? "assertive" : "polite";
30884
30884
  extra["aria-atomic"] = "true";
30885
30885
  extra["aria-relevant"] = trigger === "on_appear" ? "additions" : trigger === "both" ? "additions text" : "text";
30886
- const text6 = str9(announce.text);
30887
- if (text6 && extra["aria-label"] == null) extra["aria-label"] = text6;
30886
+ const text8 = str9(announce.text);
30887
+ if (text8 && extra["aria-label"] == null) extra["aria-label"] = text8;
30888
30888
  }
30889
30889
  }
30890
30890
  return hint;
@@ -32474,13 +32474,13 @@ var init_renderNode = __esm({
32474
32474
  const C = ctx.color;
32475
32475
  const isBoundText = typeof props.textPath === "string" && isBinding(props.textPath);
32476
32476
  const bound = useResolvedScalar(isBoundText ? props.textPath : void 0, ctx);
32477
- const text6 = isBoundText ? typeof bound === "string" || typeof bound === "number" ? String(bound) : "" : literalErrorText;
32477
+ const text8 = isBoundText ? typeof bound === "string" || typeof bound === "number" ? String(bound) : "" : literalErrorText;
32478
32478
  if (props.visible === false) return null;
32479
- if (isBoundText && !text6) return null;
32479
+ if (isBoundText && !text8) return null;
32480
32480
  const c = (props.severity ?? "error") === "warning" ? C("warning", "#E89F00") : C("danger", "#E62214");
32481
32481
  return /* @__PURE__ */ jsxs5("div", { role: "alert", style: { display: "flex", gap: 6, alignItems: "center", color: c, fontSize: 13, fontFamily: bodyFont(ctx), ...wrap }, children: [
32482
32482
  /* @__PURE__ */ jsx8("span", { "aria-hidden": "true", children: "\u26A0" }),
32483
- text6
32483
+ text8
32484
32484
  ] });
32485
32485
  });
32486
32486
  FormView = withExtras("FormView", ({ props, ctx, wrap }) => {
@@ -33967,8 +33967,8 @@ var init_renderNode = __esm({
33967
33967
  const base = invalidIcon ? ICON_FALLBACK : (typeof props.icon === "string" && props.icon ? props.icon : "star").replace(/_fill$/, "");
33968
33968
  const filledCount = Math.round(val);
33969
33969
  const onClickStar = (i) => ctx.onAction && props.interactive && props.onChange ? () => ctx.onAction({ ...props.onChange, params: { ...props.onChange?.params ?? {}, value: String(i + 1) } }) : void 0;
33970
- const cv = Number.isFinite(val) ? Math.max(0, Math.min(max, val)) : 0, summary = `${Number.isInteger(cv) ? cv : cv.toFixed(1)} of ${max}`;
33971
- return /* @__PURE__ */ jsx8("span", { style: { display: "inline-flex", alignItems: "center", gap: m.gap, ...wrap }, role: props.interactive ? "group" : "img", "aria-label": `Rating, ${summary}`, "data-a11y-value": summary, children: Array.from({ length: max }).map((_, i) => {
33970
+ const cv = Number.isFinite(val) ? Math.max(0, Math.min(max, val)) : 0, summary2 = `${Number.isInteger(cv) ? cv : cv.toFixed(1)} of ${max}`;
33971
+ return /* @__PURE__ */ jsx8("span", { style: { display: "inline-flex", alignItems: "center", gap: m.gap, ...wrap }, role: props.interactive ? "group" : "img", "aria-label": `Rating, ${summary2}`, "data-a11y-value": summary2, children: Array.from({ length: max }).map((_, i) => {
33972
33972
  const filled = i < filledCount;
33973
33973
  return /* @__PURE__ */ jsx8("span", { onClick: onClickStar(i), style: { display: "inline-grid", placeItems: "center", width: m.cell, height: m.cell, cursor: props.interactive ? "pointer" : "default", opacity: filled ? 1 : 0.28 }, children: iconSvg(filled ? `${base}_fill` : base, { size: m.glyph, color: col }) }, i);
33974
33974
  }) });
@@ -35720,8 +35720,8 @@ function buildRenderTree(node, path2 = "$", provider = null, itemScope = void 0,
35720
35720
  const asText3 = VALUE_PATH_TEXT.get(type);
35721
35721
  if (typeof valuePath === "string" && asText3 && (valuePath.startsWith("$service:") || /^\$item\.[^.]/.test(valuePath))) {
35722
35722
  const r = resolveTreeScalar(valuePath, provider, itemScope);
35723
- const text6 = asText3(r, props);
35724
- if (text6 !== void 0) values.value = text6;
35723
+ const text8 = asText3(r, props);
35724
+ if (text8 !== void 0) values.value = text8;
35725
35725
  else if (r !== void 0 && r !== null) {
35726
35726
  delete values.value;
35727
35727
  }
@@ -35902,7 +35902,7 @@ async function stabilizePngPage(page, scheme) {
35902
35902
  const browser = globalThis;
35903
35903
  browser.document.documentElement.style.colorScheme = selected;
35904
35904
  await browser.document.fonts?.ready;
35905
- await new Promise((resolve52) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve52())));
35905
+ await new Promise((resolve53) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve53())));
35906
35906
  }, scheme);
35907
35907
  }
35908
35908
  async function renderPngBatch(items) {
@@ -37916,14 +37916,14 @@ function discoverNativeActions(appDir3) {
37916
37916
  const roots = NATIVE_SOURCE_ROOTS.filter(({ directory }) => existsSync38(resolve31(appDir3, directory)));
37917
37917
  const sources = roots.flatMap(({ directory, extension, buildDirMaxDepth }) => nativeSourceFiles(resolve31(appDir3, directory), extension, buildDirMaxDepth));
37918
37918
  const registered = sources.flatMap((source) => {
37919
- let text6;
37919
+ let text8;
37920
37920
  try {
37921
- text6 = readFileSync40(source, "utf8");
37921
+ text8 = readFileSync40(source, "utf8");
37922
37922
  } catch (err) {
37923
37923
  if (!vanished(err)) throw err;
37924
37924
  return [];
37925
37925
  }
37926
- return registeredActions(text6);
37926
+ return registeredActions(text8);
37927
37927
  });
37928
37928
  return {
37929
37929
  registered: new Set(registered),
@@ -38022,11 +38022,11 @@ function strip(line) {
38022
38022
  function scalar(v) {
38023
38023
  return v.trim().replace(/^["']|["']$/g, "");
38024
38024
  }
38025
- function parseRolloutYaml(text6) {
38025
+ function parseRolloutYaml(text8) {
38026
38026
  const cfg = { app: "", rings: [] };
38027
38027
  let cur = null;
38028
38028
  let inRings = false;
38029
- for (const raw of text6.split("\n")) {
38029
+ for (const raw of text8.split("\n")) {
38030
38030
  const line = strip(raw);
38031
38031
  if (!line.trim()) continue;
38032
38032
  const top = /^([a-zA-Z_]+):\s*(.*)$/.exec(line);
@@ -38057,10 +38057,10 @@ function assignRing(r, key2, val) {
38057
38057
  else if (key2 === "percent") r.percent = Number(v);
38058
38058
  else if (key2 === "minBinaryVersion") r.minBinaryVersion = v;
38059
38059
  }
38060
- function parseRevocationsYaml(text6) {
38060
+ function parseRevocationsYaml(text8) {
38061
38061
  const out2 = { app: "", revoked: [] };
38062
38062
  let inList = false;
38063
- for (const raw of text6.split("\n")) {
38063
+ for (const raw of text8.split("\n")) {
38064
38064
  const line = strip(raw);
38065
38065
  if (!line.trim()) continue;
38066
38066
  const top = /^([a-zA-Z_]+):\s*(.*)$/.exec(line);
@@ -38417,7 +38417,7 @@ async function runScreenDiagnostics(state, screenId, descriptor) {
38417
38417
  state.app?.module.config,
38418
38418
  state.tier5Dir ?? TIER5_ROOT2
38419
38419
  );
38420
- const report2 = validateScreenDescriptor2(screenId, descriptor, {
38420
+ const report3 = validateScreenDescriptor2(screenId, descriptor, {
38421
38421
  tokens,
38422
38422
  allowedComponents,
38423
38423
  bundleJs,
@@ -38430,7 +38430,7 @@ async function runScreenDiagnostics(state, screenId, descriptor) {
38430
38430
  });
38431
38431
  const telemetry = state.telemetryEvents.filter((e) => e.screenId === screenId && (/^worker_/.test(e.type) || e.type === "bundle_load_revoked")).slice(-20);
38432
38432
  const lastError = [...telemetry].reverse().find((e) => /crash|revoked|error|fail/i.test(e.type)) ?? null;
38433
- const legacy = { ...report2, bundle: bundleName ?? null, telemetry, lastError };
38433
+ const legacy = { ...report3, bundle: bundleName ?? null, telemetry, lastError };
38434
38434
  return foldLegacyReport(legacy, {
38435
38435
  source: "diagnostics",
38436
38436
  screenId,
@@ -38639,11 +38639,11 @@ async function handleOwnerChatRequest(req, res) {
38639
38639
  return sendJson(res, 400, { error: "invalid_json" }, cors);
38640
38640
  }
38641
38641
  const chatroomId = (parsed.chatroomId ?? "").trim();
38642
- const text6 = (parsed.text ?? "").trim();
38643
- if (!chatroomId || !text6) return sendJson(res, 400, { error: "chatroomId_and_text_required" }, cors);
38642
+ const text8 = (parsed.text ?? "").trim();
38643
+ if (!chatroomId || !text8) return sendJson(res, 400, { error: "chatroomId_and_text_required" }, cors);
38644
38644
  const metaSiteId = (parsed.metaSiteId ?? "").trim() || await resolveMetaSiteId();
38645
38645
  if (!metaSiteId) return sendJson(res, 400, { error: "no_meta_site" }, cors);
38646
- const result = await sendChatMessageLive(metaSiteId, chatroomId, text6);
38646
+ const result = await sendChatMessageLive(metaSiteId, chatroomId, text8);
38647
38647
  if (result.ok) return sendJson(res, 200, { ok: true, message: result.message }, cors);
38648
38648
  return sendJson(res, result.status >= 400 && result.status < 600 ? result.status : 502, { ok: false, status: result.status, error: result.error }, cors);
38649
38649
  }
@@ -38904,13 +38904,13 @@ function invalidate(state, ...screenIds) {
38904
38904
  publishSSE(state, "screen.invalidated", { screenIds });
38905
38905
  }
38906
38906
  function publishSSE(state, type, payload) {
38907
- const text6 = `event: ${type}
38907
+ const text8 = `event: ${type}
38908
38908
  data: ${JSON.stringify(payload)}
38909
38909
 
38910
38910
  `;
38911
38911
  for (const res of [...state.sseClients]) {
38912
38912
  try {
38913
- res.write(text6);
38913
+ res.write(text8);
38914
38914
  } catch {
38915
38915
  state.sseClients.delete(res);
38916
38916
  }
@@ -38926,13 +38926,13 @@ function publishAdminSSE(state, type, payload) {
38926
38926
  state.lastDeviceScreen.set(key2, screenId);
38927
38927
  }
38928
38928
  }
38929
- const text6 = `event: ${type}
38929
+ const text8 = `event: ${type}
38930
38930
  data: ${JSON.stringify(payload)}
38931
38931
 
38932
38932
  `;
38933
38933
  for (const res of [...state.adminClients]) {
38934
38934
  try {
38935
- res.write(text6);
38935
+ res.write(text8);
38936
38936
  } catch {
38937
38937
  state.adminClients.delete(res);
38938
38938
  }
@@ -38953,12 +38953,12 @@ function publishDevReady(state, res, extra = {}) {
38953
38953
  hotReloadEnabled: state.hotReloadEnabled,
38954
38954
  ...extra
38955
38955
  };
38956
- const text6 = `event: dev.ready
38956
+ const text8 = `event: dev.ready
38957
38957
  data: ${JSON.stringify(payload)}
38958
38958
 
38959
38959
  `;
38960
38960
  if (res) {
38961
- res.write(text6);
38961
+ res.write(text8);
38962
38962
  } else {
38963
38963
  publishSSE(state, "dev.ready", payload);
38964
38964
  }
@@ -39543,7 +39543,7 @@ async function handleWebWix(req, res, state) {
39543
39543
  }
39544
39544
  if (match) {
39545
39545
  const mocked = match.rule.response;
39546
- if (mocked.delayMs) await new Promise((resolve52) => setTimeout(resolve52, mocked.delayMs));
39546
+ if (mocked.delayMs) await new Promise((resolve53) => setTimeout(resolve53, mocked.delayMs));
39547
39547
  const responseBody = mocked.template ? renderTemplate(mocked.body, match.captures) : mocked.body;
39548
39548
  record2("mock", mocked.status, responseBody, match.rule.id, mocked.headers);
39549
39549
  return reply(200, { status: mocked.status, body: responseBody ?? "" });
@@ -39709,7 +39709,7 @@ async function handleDev(req, res, state) {
39709
39709
  idiomContext
39710
39710
  );
39711
39711
  const legacy = { screenId, scheme, ...render, diagnostics };
39712
- const report2 = foldLegacyReport(legacy, {
39712
+ const report3 = foldLegacyReport(legacy, {
39713
39713
  source: "render",
39714
39714
  screenId,
39715
39715
  ok: diagnostics.ok !== false && render.renderable !== false,
@@ -39721,8 +39721,8 @@ async function handleDev(req, res, state) {
39721
39721
  ],
39722
39722
  evidence: { runId: `dev:${state.startedAt}:${screenId}`, ts: (/* @__PURE__ */ new Date()).toISOString() }
39723
39723
  });
39724
- const status = body.envelope === 1 && !report2.ok ? 422 : 200;
39725
- return sendJson(res, status, report2);
39724
+ const status = body.envelope === 1 && !report3.ok ? 422 : 200;
39725
+ return sendJson(res, status, report3);
39726
39726
  }
39727
39727
  {
39728
39728
  const diagMatch = /^\/__dev\/screen\/(.+?)\/diagnostics(?:\?|$)/.exec(url);
@@ -40183,7 +40183,7 @@ async function handleAdminPlayground(req, res, state) {
40183
40183
  state.app?.module.config,
40184
40184
  state.tier5Dir ?? TIER5_ROOT2
40185
40185
  );
40186
- const report2 = validateScreenDescriptor2(screenId, descriptor, {
40186
+ const report3 = validateScreenDescriptor2(screenId, descriptor, {
40187
40187
  tokens,
40188
40188
  allowedComponents,
40189
40189
  bundleJs,
@@ -40193,7 +40193,7 @@ async function handleAdminPlayground(req, res, state) {
40193
40193
  workerSubtreeScreens: new Set(uiConfig(state.app?.module.config).workerSubtreeScreens ?? []),
40194
40194
  a11y: uiConfig(state.app?.module.config).a11y
40195
40195
  });
40196
- return sendJson(res, report2.ok ? 200 : 422, report2);
40196
+ return sendJson(res, report3.ok ? 200 : 422, report3);
40197
40197
  }
40198
40198
  const detailMatch = /^\/v1\/admin\/screens\/([^/]+)$/.exec(path2);
40199
40199
  if (detailMatch && req.method === "GET") {
@@ -40648,9 +40648,9 @@ async function handleLiveSubscription(req, res, state) {
40648
40648
  },
40649
40649
  body: JSON.stringify({ ...body, app })
40650
40650
  });
40651
- const text6 = await upstream.text();
40651
+ const text8 = await upstream.text();
40652
40652
  res.writeHead(upstream.status, { "Content-Type": "application/json", ...cors });
40653
- res.end(text6 || JSON.stringify({ ok: upstream.ok }));
40653
+ res.end(text8 || JSON.stringify({ ok: upstream.ok }));
40654
40654
  } catch (error) {
40655
40655
  sendJson(res, 502, { error: "admin_server_unreachable", detail: String(error) }, cors);
40656
40656
  }
@@ -41642,12 +41642,12 @@ var init_query = __esm({
41642
41642
  });
41643
41643
 
41644
41644
  // ../../core/dev-server/src/crawl-input.ts
41645
- function resolved(v, resolve52) {
41646
- if (typeof v === "string") return v.startsWith("$service:") ? resolve52(v) : v;
41645
+ function resolved(v, resolve53) {
41646
+ if (typeof v === "string") return v.startsWith("$service:") ? resolve53(v) : v;
41647
41647
  if (Array.isArray(v)) {
41648
41648
  const out2 = v.flatMap((el) => {
41649
41649
  if (typeof el !== "string" || !el.startsWith("$service:")) return [el];
41650
- const r = resolve52(el);
41650
+ const r = resolve53(el);
41651
41651
  return Array.isArray(r) ? r : [r];
41652
41652
  });
41653
41653
  return out2;
@@ -41661,9 +41661,9 @@ function hasRowBinding(props) {
41661
41661
  return itemToken(v) || Array.isArray(v) && v.some(itemToken);
41662
41662
  });
41663
41663
  }
41664
- function declaredOptionIds(props, resolve52) {
41664
+ function declaredOptionIds(props, resolve53) {
41665
41665
  const literal = props.options ?? props.tabs ?? props.chips;
41666
- const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath, resolve52) : void 0;
41666
+ const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath, resolve53) : void 0;
41667
41667
  const raw = Array.isArray(bound) ? bound : literal;
41668
41668
  if (!Array.isArray(raw)) return [];
41669
41669
  const out2 = [];
@@ -41706,24 +41706,24 @@ function seedTokens(state, limit = 48) {
41706
41706
  walk2(state, 0);
41707
41707
  return out2;
41708
41708
  }
41709
- function synthesizeInput(control, resolve52, tokens) {
41709
+ function synthesizeInput(control, resolve53, tokens) {
41710
41710
  const id = `${control.type}.${control.callback}`;
41711
41711
  const row = SYNTHESIZED_CONTROLS[id];
41712
41712
  if (!row) return null;
41713
41713
  const props = control.props;
41714
41714
  if (hasRowBinding(props)) return null;
41715
41715
  if (row.from === "declared-options") {
41716
- const ids = declaredOptionIds(props, resolve52);
41716
+ const ids = declaredOptionIds(props, resolve53);
41717
41717
  if (!ids.length) return null;
41718
41718
  if (row.encoding === "string-array") {
41719
- const currentRaw2 = resolved(props.selectedIds, resolve52);
41719
+ const currentRaw2 = resolved(props.selectedIds, resolve53);
41720
41720
  const current3 = (Array.isArray(currentRaw2) ? currentRaw2 : []).filter((x) => typeof x === "string");
41721
41721
  const pick4 = ids.find((o) => !current3.includes(o));
41722
41722
  if (pick4 === void 0) return null;
41723
41723
  const value = props.multiSelect === true ? [...current3, pick4] : [pick4];
41724
41724
  return { key: row.key, value, from: row.from, current: current3, control: id };
41725
41725
  }
41726
- const currentRaw = resolved(props.selectedId, resolve52);
41726
+ const currentRaw = resolved(props.selectedId, resolve53);
41727
41727
  const current2 = typeof currentRaw === "string" ? currentRaw : void 0;
41728
41728
  const pick3 = ids.find((o) => o !== current2);
41729
41729
  if (pick3 === void 0) return null;
@@ -41731,7 +41731,7 @@ function synthesizeInput(control, resolve52, tokens) {
41731
41731
  }
41732
41732
  if (!acceptsWords(props) || !acceptsWords(control.wrapper ?? {})) return null;
41733
41733
  const binding2 = typeof props.valuePath === "string" ? props.valuePath : typeof props.value === "string" && props.value.startsWith("$service:") ? props.value : void 0;
41734
- const bound = binding2 === void 0 ? void 0 : resolve52(binding2);
41734
+ const bound = binding2 === void 0 ? void 0 : resolve53(binding2);
41735
41735
  const literal = typeof props.value === "string" && !props.value.startsWith("$") ? props.value : void 0;
41736
41736
  const current = typeof bound === "string" ? bound : typeof bound === "number" ? String(bound) : literal ?? "";
41737
41737
  const max = typeof props.maxLength === "number" && props.maxLength > 0 ? props.maxLength : void 0;
@@ -42095,10 +42095,10 @@ function netTransport(rules) {
42095
42095
  if (res.needsUpstream) {
42096
42096
  throw new Error(`net fixture rule ${res.ruleId} is a \`transform\` rule, which needs a real upstream \u2014 not usable in a hermetic crawl`);
42097
42097
  }
42098
- const { status, body: text6 } = res.resolved;
42098
+ const { status, body: text8 } = res.resolved;
42099
42099
  if (status < 200 || status >= 300) throw new Error(`Wix ${status} for ${method} ${bare}`);
42100
42100
  try {
42101
- return text6 ? JSON.parse(text6) : {};
42101
+ return text8 ? JSON.parse(text8) : {};
42102
42102
  } catch {
42103
42103
  return {};
42104
42104
  }
@@ -42142,10 +42142,10 @@ function layeredTransport(layers2) {
42142
42142
  });
42143
42143
  if (res.matched) {
42144
42144
  if (res.needsUpstream) throw new Error(`net fixture rule ${res.ruleId} is a \`transform\` rule, which needs a real upstream \u2014 not usable in a hermetic crawl`);
42145
- const { status, body: text6 } = res.resolved;
42145
+ const { status, body: text8 } = res.resolved;
42146
42146
  if (status < 200 || status >= 300) throw new Error(`Wix ${status} for ${m} ${bare}`);
42147
42147
  try {
42148
- return text6 ? JSON.parse(text6) : {};
42148
+ return text8 ? JSON.parse(text8) : {};
42149
42149
  } catch {
42150
42150
  return {};
42151
42151
  }
@@ -44167,13 +44167,13 @@ var init_build2 = __esm({
44167
44167
  });
44168
44168
 
44169
44169
  // ../mobile-dist/release-pin.ts
44170
- function withPinnedRelease(text6, releaseId) {
44171
- if (!releaseId) return text6;
44170
+ function withPinnedRelease(text8, releaseId) {
44171
+ if (!releaseId) return text8;
44172
44172
  let cfg;
44173
44173
  try {
44174
- cfg = JSON.parse(text6);
44174
+ cfg = JSON.parse(text8);
44175
44175
  } catch {
44176
- return text6;
44176
+ return text8;
44177
44177
  }
44178
44178
  cfg.releaseId = releaseId;
44179
44179
  cfg.releasePinned = true;
@@ -44291,10 +44291,10 @@ async function bakeCatalogs(app, locale, fetchCatalog, putDoc) {
44291
44291
  if (!declared.length) return out2;
44292
44292
  const tags = [.../* @__PURE__ */ new Set([...locale?.default ? [locale.default] : [], ...declared])];
44293
44293
  for (const tag of tags) {
44294
- const text6 = await fetchCatalog(tag);
44295
- if (!text6) continue;
44296
- const hash = sha2564(text6);
44297
- await putDoc(app, hash, text6);
44294
+ const text8 = await fetchCatalog(tag);
44295
+ if (!text8) continue;
44296
+ const hash = sha2564(text8);
44297
+ await putDoc(app, hash, text8);
44298
44298
  out2[tag] = hash;
44299
44299
  }
44300
44300
  return out2;
@@ -44386,9 +44386,9 @@ async function snapshotTokens(app, base, fetchTokens, put) {
44386
44386
  }
44387
44387
  };
44388
44388
  }
44389
- const text6 = await res.text();
44390
- await put(text6);
44391
- return { hash: sha2564(text6) };
44389
+ const text8 = await res.text();
44390
+ await put(text8);
44391
+ return { hash: sha2564(text8) };
44392
44392
  }
44393
44393
  function tokensSnapshotMessage(app, base, status) {
44394
44394
  const why = status === 400 ? `the dev-server rejected the app id as malformed (400 bad_app). It must be lowercase letters, digits and hyphens, starting with a letter or digit, at most 63 characters, with at most one interior dot \u2014 so a leading underscore or an uppercase letter fails, on every build of that app. A single dot is FINE (an owner-namespaced slug), so do not remove one to get past this` : `${status} from the tokens route`;
@@ -44482,23 +44482,23 @@ function maximumBinaryVersion(current, candidate) {
44482
44482
  }
44483
44483
  return current;
44484
44484
  }
44485
- async function withStoreNavBundle(text6, address) {
44485
+ async function withStoreNavBundle(text8, address) {
44486
44486
  let cfg;
44487
44487
  try {
44488
- cfg = JSON.parse(text6);
44488
+ cfg = JSON.parse(text8);
44489
44489
  } catch {
44490
- return text6;
44490
+ return text8;
44491
44491
  }
44492
44492
  const refs = [cfg?.navigation?.navLogicBundle, cfg?.navLogicBundle].filter(
44493
44493
  (r) => !!r && typeof r === "object" && typeof r.url === "string"
44494
44494
  );
44495
- if (refs.length === 0) return text6;
44495
+ if (refs.length === 0) return text8;
44496
44496
  const resolved2 = [];
44497
44497
  for (const ref of refs) {
44498
44498
  const name = bundleNameFromUrl(ref.url);
44499
- if (!name) return text6;
44499
+ if (!name) return text8;
44500
44500
  const addressed = await address(name);
44501
- if (!addressed) return text6;
44501
+ if (!addressed) return text8;
44502
44502
  resolved2.push({ ref, url: addressed.url, sri: addressed.sri });
44503
44503
  }
44504
44504
  for (const { ref, url, sri: integrity2 } of resolved2) {
@@ -44507,10 +44507,10 @@ async function withStoreNavBundle(text6, address) {
44507
44507
  }
44508
44508
  return JSON.stringify(cfg);
44509
44509
  }
44510
- function linkableScreenIdsFrom(text6) {
44510
+ function linkableScreenIdsFrom(text8) {
44511
44511
  let cfg;
44512
44512
  try {
44513
- cfg = JSON.parse(text6);
44513
+ cfg = JSON.parse(text8);
44514
44514
  } catch {
44515
44515
  return [];
44516
44516
  }
@@ -44522,24 +44522,24 @@ function linkableScreenIdsFrom(text6) {
44522
44522
  }
44523
44523
  return [...ids];
44524
44524
  }
44525
- function withoutDevOnlyAppConfig(text6) {
44525
+ function withoutDevOnlyAppConfig(text8) {
44526
44526
  let cfg;
44527
44527
  try {
44528
- cfg = JSON.parse(text6);
44528
+ cfg = JSON.parse(text8);
44529
44529
  } catch {
44530
- return text6;
44530
+ return text8;
44531
44531
  }
44532
- if (!cfg || typeof cfg !== "object" || !("devGatewayConfig" in cfg)) return text6;
44532
+ if (!cfg || typeof cfg !== "object" || !("devGatewayConfig" in cfg)) return text8;
44533
44533
  delete cfg.devGatewayConfig;
44534
44534
  return JSON.stringify(cfg);
44535
44535
  }
44536
- function withProdServeAppConfig(text6, prod) {
44537
- if (!prod?.serve) return text6;
44536
+ function withProdServeAppConfig(text8, prod) {
44537
+ if (!prod?.serve) return text8;
44538
44538
  let cfg;
44539
44539
  try {
44540
- cfg = JSON.parse(text6);
44540
+ cfg = JSON.parse(text8);
44541
44541
  } catch {
44542
- return text6;
44542
+ return text8;
44543
44543
  }
44544
44544
  cfg.useProdServe = true;
44545
44545
  cfg.prodServeBaseUrl = prod.serve;
@@ -44760,10 +44760,10 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
44760
44760
  if (bytes2.length === 0 || bytes2.length > MAX_AUTHORING_DOC_BYTES) {
44761
44761
  throw new Error(`${file} must be non-empty and at most ${MAX_AUTHORING_DOC_BYTES} bytes to ship with a release.`);
44762
44762
  }
44763
- const text6 = bytes2.toString("utf8");
44764
- if (!Buffer.from(text6, "utf8").equals(bytes2)) throw new Error(`${file} must be canonical UTF-8 Markdown.`);
44763
+ const text8 = bytes2.toString("utf8");
44764
+ if (!Buffer.from(text8, "utf8").equals(bytes2)) throw new Error(`${file} must be canonical UTF-8 Markdown.`);
44765
44765
  const hash = sha2564(bytes2);
44766
- await store.putDoc(app, hash, text6);
44766
+ await store.putDoc(app, hash, text8);
44767
44767
  authoringDocs[name] = { sha256: hash, sri: sri2(bytes2), bytes: bytes2.length, contentType: "text/markdown; charset=utf-8" };
44768
44768
  }
44769
44769
  }
@@ -44962,7 +44962,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
44962
44962
  }
44963
44963
  if (collect2?.lint) {
44964
44964
  const bundleJs = bundleName ? readBuiltBundle(tier5Dir, bundleName) : void 0;
44965
- const report2 = validateScreenDescriptor(screenId, descriptor, {
44965
+ const report3 = validateScreenDescriptor(screenId, descriptor, {
44966
44966
  tokens: lintTokens,
44967
44967
  allowedComponents,
44968
44968
  allowedIcons: KNOWN_ICONS,
@@ -44976,7 +44976,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
44976
44976
  // default, "error"; an in-repo app with ratcheted debt declares "warn".
44977
44977
  a11y: config.a11y
44978
44978
  });
44979
- lint.push({ screenId, ok: report2.ok, issues: report2.issues });
44979
+ lint.push({ screenId, ok: report3.ok, issues: report3.issues });
44980
44980
  }
44981
44981
  if (collect2?.render && (!collect2.render.screenId || collect2.render.screenId === screenId)) {
44982
44982
  const { services, liveCalls, liveReturned, liveErrors } = await renderServicesFor(bundleName, descriptor);
@@ -44994,7 +44994,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
44994
44994
  const bundleName = lb ? bundleNameFromUrl(lb.url) : null;
44995
44995
  if (collect2?.lint) {
44996
44996
  const bundleJs = bundleName ? readBuiltBundle(tier5Dir, bundleName) : void 0;
44997
- const report2 = validateScreenDescriptor(wantedRender, descriptor, {
44997
+ const report3 = validateScreenDescriptor(wantedRender, descriptor, {
44998
44998
  tokens: lintTokens,
44999
44999
  allowedComponents,
45000
45000
  allowedIcons: KNOWN_ICONS,
@@ -45005,7 +45005,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
45005
45005
  workerSubtreeScreens: new Set(config.workerSubtreeScreens ?? []),
45006
45006
  a11y: config.a11y
45007
45007
  });
45008
- lint.push({ screenId: wantedRender, ok: report2.ok, issues: report2.issues });
45008
+ lint.push({ screenId: wantedRender, ok: report3.ok, issues: report3.issues });
45009
45009
  }
45010
45010
  const { services, liveCalls, liveReturned, liveErrors } = await renderServicesFor(bundleName, descriptor);
45011
45011
  const rr = await renderDescriptorWeb(descriptor, renderTokens, renderScheme, collect2.render.png === true, services, collect2.render.width, collect2.render.rtl === true);
@@ -45123,11 +45123,11 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
45123
45123
  ok: res.ok,
45124
45124
  status: res.status,
45125
45125
  text: async () => {
45126
- const text6 = await res.text();
45126
+ const text8 = await res.text();
45127
45127
  try {
45128
- const doc = JSON.parse(text6);
45128
+ const doc = JSON.parse(text8);
45129
45129
  if (!publishedFontPlan) {
45130
- if (!("fontFaces" in doc)) return text6;
45130
+ if (!("fontFaces" in doc)) return text8;
45131
45131
  const kept = publishableFontFaces(doc.fontFaces);
45132
45132
  if (kept) doc.fontFaces = kept;
45133
45133
  else delete doc.fontFaces;
@@ -45136,12 +45136,12 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
45136
45136
  doc.fontFaces = servedProjection(publishedFontPlan);
45137
45137
  return JSON.stringify(doc);
45138
45138
  } catch {
45139
- return text6;
45139
+ return text8;
45140
45140
  }
45141
45141
  }
45142
45142
  };
45143
45143
  },
45144
- (text6) => store.putTokens(app, text6)
45144
+ (text8) => store.putTokens(app, text8)
45145
45145
  );
45146
45146
  if (snapshot2.hash) tokensHash = snapshot2.hash;
45147
45147
  if (snapshot2.failure) {
@@ -45171,14 +45171,14 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
45171
45171
  if (streamPolicyErrors.length) {
45172
45172
  throw new Error(`invalid streamPolicy for release ${app}: ${streamPolicyErrors.join("; ")}`);
45173
45173
  }
45174
- const text6 = await withStoreNavBundle(prodText, async (name) => {
45174
+ const text8 = await withStoreNavBundle(prodText, async (name) => {
45175
45175
  const hash = await addressBundle(name) ?? null;
45176
45176
  const entry = hash ? bundles[name] : void 0;
45177
45177
  return entry ? { url: store.bundleUrl(app, entry.sha256), sri: entry.sri } : null;
45178
45178
  });
45179
- await store.putAppConfig(app, text6);
45180
- appConfigHash = sha2564(text6);
45181
- if (collect2?.descriptors) for (const id of linkableScreenIdsFrom(text6)) linkable.add(id);
45179
+ await store.putAppConfig(app, text8);
45180
+ appConfigHash = sha2564(text8);
45181
+ if (collect2?.descriptors) for (const id of linkableScreenIdsFrom(text8)) linkable.add(id);
45182
45182
  }
45183
45183
  const ahRes = await devFetch(`${base}/v1/action-handlers/${encodeURIComponent(app)}`, { headers: { "X-Himalaya-App": app } });
45184
45184
  if (ahRes.ok) {
@@ -46044,14 +46044,14 @@ function headline(changes) {
46044
46044
  function boardLines(changes) {
46045
46045
  const lines = [];
46046
46046
  for (const c of changes.items) {
46047
- const text6 = lineOf(c);
46048
- const same3 = lines.find((l) => l.text === text6);
46047
+ const text8 = lineOf(c);
46048
+ const same3 = lines.find((l) => l.text === text8);
46049
46049
  if (same3) {
46050
46050
  same3.n++;
46051
46051
  continue;
46052
46052
  }
46053
46053
  lines.push({
46054
- text: text6,
46054
+ text: text8,
46055
46055
  n: 1,
46056
46056
  ...c.kind === "token" && c.from && HEX.test(c.from) ? { from: c.from } : {},
46057
46057
  ...c.kind === "token" && c.to && HEX.test(c.to) ? { to: c.to } : {}
@@ -46371,12 +46371,12 @@ function testRuns(dir) {
46371
46371
  if (!f.endsWith(".json") || f === "latest.json") continue;
46372
46372
  const r = obj(readJson3(join41(att, f)));
46373
46373
  if (!r || r.tool !== "himi-test" || typeof r.runId !== "string") continue;
46374
- const report2 = obj(r.report);
46374
+ const report3 = obj(r.report);
46375
46375
  const coverage = obj(r.coverage);
46376
46376
  runs.push({
46377
46377
  runId: r.runId,
46378
- ok: report2?.ok === true,
46379
- errors: num(obj(report2?.counts)?.errors),
46378
+ ok: report3?.ok === true,
46379
+ errors: num(obj(report3?.counts)?.errors),
46380
46380
  screens: num(coverage?.screens),
46381
46381
  actions: num(coverage?.actionsDispatched),
46382
46382
  gaps: num(coverage?.gaps)
@@ -46495,7 +46495,7 @@ function focusScreen(memory) {
46495
46495
  }
46496
46496
  function buildView(dir, memory, now) {
46497
46497
  const { entries } = readProgress(dir);
46498
- const summary = summarizeProgress(entries);
46498
+ const summary2 = summarizeProgress(entries);
46499
46499
  const { name, iconFile } = appIdentity(dir);
46500
46500
  const iconArchived = iconFile ? archiveFile(dir, memory, iconFile) : null;
46501
46501
  const icon = iconArchived ? historyUrl(iconArchived.file) : null;
@@ -46524,12 +46524,12 @@ function buildView(dir, memory, now) {
46524
46524
  }
46525
46525
  }
46526
46526
  const firstShot = screens.map((s) => s.firstSeen).sort()[0];
46527
- const startedAt = [summary.startedAt, firstShot, memory.createdAt].filter((x) => !!x).sort()[0] ?? null;
46527
+ const startedAt = [summary2.startedAt, firstShot, memory.createdAt].filter((x) => !!x).sort()[0] ?? null;
46528
46528
  const view = {
46529
46529
  generatedAt: now,
46530
46530
  app: { name, icon, palette: palette(dir) },
46531
46531
  steps: JOURNEY_STEPS,
46532
- current: summary.current ?? null,
46532
+ current: summary2.current ?? null,
46533
46533
  startedAt,
46534
46534
  journal: entries.slice(-MAX_JOURNAL).reverse().map((e) => ({
46535
46535
  ts: e.ts,
@@ -47194,16 +47194,16 @@ function pushSetupBodyBytes(body) {
47194
47194
  return Buffer.byteLength(JSON.stringify(body), "utf8");
47195
47195
  }
47196
47196
  async function pushSetupRequest(options) {
47197
- const refuse4 = (error) => ({ ok: false, status: 0, body: null, error });
47198
- if (!options.target.controlToken) return refuse4("control_token_required");
47199
- if (!options.wixToken) return refuse4("wix_account_token_required");
47200
- if (credentialHostRefusal(options.target.control)) return refuse4("insecure_target");
47201
- if (options.previewTag !== void 0 && !PREVIEW_TAG.test(options.previewTag)) return refuse4("invalid_preview_tag");
47197
+ const refuse5 = (error) => ({ ok: false, status: 0, body: null, error });
47198
+ if (!options.target.controlToken) return refuse5("control_token_required");
47199
+ if (!options.wixToken) return refuse5("wix_account_token_required");
47200
+ if (credentialHostRefusal(options.target.control)) return refuse5("insecure_target");
47201
+ if (options.previewTag !== void 0 && !PREVIEW_TAG.test(options.previewTag)) return refuse5("invalid_preview_tag");
47202
47202
  const setup = options.operation === "setup";
47203
- if (setup && !options.body) return refuse4("push_setup_body_required");
47204
- if (!setup && (!options.query?.app || !options.query?.site)) return refuse4("push_setup_query_required");
47203
+ if (setup && !options.body) return refuse5("push_setup_body_required");
47204
+ if (!setup && (!options.query?.app || !options.query?.site)) return refuse5("push_setup_query_required");
47205
47205
  if (setup && pushSetupBodyBytes(options.body) > MAX_PUSH_SETUP_BODY_BYTES) {
47206
- return refuse4("push_setup_body_too_large");
47206
+ return refuse5("push_setup_body_too_large");
47207
47207
  }
47208
47208
  const base = options.target.control.replace(/\/+$/, "");
47209
47209
  let path2 = "/v1/admin/push/setup";
@@ -47228,10 +47228,10 @@ async function pushSetupRequest(options) {
47228
47228
  signal: AbortSignal.timeout(options.timeoutMs ?? (setup ? 12e4 : 3e4)),
47229
47229
  ...setup ? { body: JSON.stringify(options.body) } : {}
47230
47230
  });
47231
- const text6 = await response.text();
47231
+ const text8 = await response.text();
47232
47232
  let parsed = null;
47233
47233
  try {
47234
- const value = text6 ? JSON.parse(text6) : null;
47234
+ const value = text8 ? JSON.parse(text8) : null;
47235
47235
  parsed = value && typeof value === "object" && !Array.isArray(value) ? value : null;
47236
47236
  } catch {
47237
47237
  parsed = null;
@@ -47271,6 +47271,41 @@ var init_push_setup_apple_credentials = __esm({
47271
47271
  }
47272
47272
  });
47273
47273
 
47274
+ // src/hosted-owner.ts
47275
+ async function hostedOwnerSession(flags, deps = {}) {
47276
+ let target;
47277
+ try {
47278
+ target = resolveTarget({ target: text3(flags.target), defaultTarget: "wix", controlUrl: text3(flags["control-url"]), controlToken: text3(flags["control-token"]), ownerIssueUrl: text3(flags["owner-issue-url"]) });
47279
+ } catch {
47280
+ return refused("unknown_target", "Select a configured serve target.");
47281
+ }
47282
+ if (credentialHostRefusal(target.control)) return refused("insecure_target");
47283
+ const previewTag = text3(flags["preview-tag"]) ?? process.env.HIMI_SERVE_PREVIEW_TAG;
47284
+ if (previewTag !== void 0 && !/^dp-[a-z0-9]+$/.test(previewTag)) return refused("invalid_preview_tag");
47285
+ const controlToken = target.controlToken;
47286
+ if (!controlToken || !decodeControlTokenClaims(controlToken)?.sub) return refused("owner_login_required", "Run himi login --browser --target wix.");
47287
+ let wixToken;
47288
+ try {
47289
+ wixToken = await (deps.wixToken ?? accountToken)();
47290
+ } catch {
47291
+ return refused("wix_account_token_required", "Browser login supplies a Himi control token only. Sign into the Wix CLI with wix login, using the same Wix account, then retry. You can continue building without push setup.", 1);
47292
+ }
47293
+ if (!wixToken) return refused("wix_account_token_required", "Run wix login using the same Wix account.", 1);
47294
+ if (!target.ownerIssue) return refused("owner_issuer_required");
47295
+ return { ok: true, session: { target, controlToken, wixToken, ownerIssue: target.ownerIssue, ...previewTag ? { previewTag } : {} } };
47296
+ }
47297
+ var text3, refused;
47298
+ var init_hosted_owner = __esm({
47299
+ "src/hosted-owner.ts"() {
47300
+ init_config();
47301
+ init_credential_hosts();
47302
+ init_owner_claim();
47303
+ init_wix_owner();
47304
+ text3 = (v) => typeof v === "string" && v.length > 0 ? v : void 0;
47305
+ refused = (error, hint, exit = 2) => ({ ok: false, error, ...hint ? { hint } : {}, exit });
47306
+ }
47307
+ });
47308
+
47274
47309
  // src/push-onboarding.ts
47275
47310
  import { existsSync as existsSync44, mkdirSync as mkdirSync20, readFileSync as readFileSync48, statSync as statSync9, writeFileSync as writeFileSync15, chmodSync as chmodSync2 } from "node:fs";
47276
47311
  import { basename as basename12, dirname as dirname25, join as join42, resolve as resolve37 } from "node:path";
@@ -47294,26 +47329,26 @@ function pushInputsFromContent(dir) {
47294
47329
  // autoClaimSlug's docblock describes as the project-declared slug. Without the fallback a
47295
47330
  // package with no `name` sent a body missing `app` and earned `400 invalid_app_id` with both
47296
47331
  // private keys already on the wire.
47297
- app: text3(content.name) ?? basename12(root),
47298
- ...text3(provisioning.siteId) ? { site: text3(provisioning.siteId) } : {},
47299
- ...text3(native.iosBundleId) ? { bundleId: text3(native.iosBundleId) } : {},
47300
- ...text3(native.androidApplicationId) ? { androidApplicationId: text3(native.androidApplicationId) } : {}
47332
+ app: text4(content.name) ?? basename12(root),
47333
+ ...text4(provisioning.siteId) ? { site: text4(provisioning.siteId) } : {},
47334
+ ...text4(native.iosBundleId) ? { bundleId: text4(native.iosBundleId) } : {},
47335
+ ...text4(native.androidApplicationId) ? { androidApplicationId: text4(native.androidApplicationId) } : {}
47301
47336
  };
47302
47337
  }
47303
47338
  function mergePushInputs(content, flags) {
47304
47339
  const merged = { ...content };
47305
47340
  for (const [flag, apply] of FLAG_SETTERS) {
47306
- const value = text3(flags[flag]);
47341
+ const value = text4(flags[flag]);
47307
47342
  if (value !== void 0) apply(merged, value);
47308
47343
  }
47309
47344
  return merged;
47310
47345
  }
47311
47346
  function missingPushInputs(i, scope) {
47312
47347
  const needed = scope === "push_and_signing" ? [...REQUIRED_ORDER, ...ASC_ORDER] : REQUIRED_ORDER;
47313
- return needed.filter((name) => !text3(i[name]));
47348
+ return needed.filter((name) => !text4(i[name]));
47314
47349
  }
47315
47350
  function ascGroupError(i) {
47316
- const present = ASC_ORDER.filter((name) => text3(i[name])).length;
47351
+ const present = ASC_ORDER.filter((name) => text4(i[name])).length;
47317
47352
  return present === 0 || present === ASC_ORDER.length ? null : "incomplete_asc_group";
47318
47353
  }
47319
47354
  function localIdentityRefusal(i) {
@@ -47382,8 +47417,8 @@ function validateApnsAuthKey(body) {
47382
47417
  return { ok: true };
47383
47418
  }
47384
47419
  function buildPushSetupBody(i, keys) {
47385
- const missing = REQUIRED_ORDER.filter((name) => !text3(i[name]));
47386
- const app = text3(i.app);
47420
+ const missing = REQUIRED_ORDER.filter((name) => !text4(i[name]));
47421
+ const app = text4(i.app);
47387
47422
  if (!app) return { ok: false, code: "app_not_initialized", missing };
47388
47423
  if (missing.length > 0) return { ok: false, code: "needs_input", missing };
47389
47424
  if (i.apnsEnvironment !== "development" && i.apnsEnvironment !== "production") {
@@ -47463,7 +47498,7 @@ function savePushSelection(dir, input) {
47463
47498
  if (input.androidApplicationId) selection.androidApplicationId = input.androidApplicationId;
47464
47499
  writeFile(dir, { ...readPushOnboarding(dir), selection });
47465
47500
  }
47466
- var PUSH_ONBOARDING_PATH, MAX_KEY_FILE_BYTES, SITE_RE, APP_RE, ANDROID_ID_RE, PLACEHOLDER_BUNDLE_RE, text3, FLAG_SETTERS, REQUIRED_ORDER, ASC_ORDER, NOTE;
47501
+ var PUSH_ONBOARDING_PATH, MAX_KEY_FILE_BYTES, SITE_RE, APP_RE, ANDROID_ID_RE, PLACEHOLDER_BUNDLE_RE, text4, FLAG_SETTERS, REQUIRED_ORDER, ASC_ORDER, NOTE;
47467
47502
  var init_push_onboarding = __esm({
47468
47503
  "src/push-onboarding.ts"() {
47469
47504
  PUSH_ONBOARDING_PATH = ".himi/push-onboarding.json";
@@ -47472,7 +47507,7 @@ var init_push_onboarding = __esm({
47472
47507
  APP_RE = /^[a-z0-9][a-z0-9._-]{0,63}$/i;
47473
47508
  ANDROID_ID_RE = /^[A-Za-z][A-Za-z0-9_]*(\.[A-Za-z][A-Za-z0-9_]*)+$/;
47474
47509
  PLACEHOLDER_BUNDLE_RE = /^com\.example\.|^__HIMI_APP_/;
47475
- text3 = (v) => typeof v === "string" && v.length > 0 ? v : void 0;
47510
+ text4 = (v) => typeof v === "string" && v.length > 0 ? v : void 0;
47476
47511
  FLAG_SETTERS = [
47477
47512
  ["app", (m, v) => {
47478
47513
  m.app = v;
@@ -47604,7 +47639,7 @@ async function runNotifySetup(pos, flags, io, deps = {}) {
47604
47639
  if (operation !== "setup" && operation !== "status") return refuse2(io, "invalid_notify_operation");
47605
47640
  const flagError = pushSetupFlagError(flags);
47606
47641
  if (flagError) return refuse2(io, flagError);
47607
- const dir = resolve38(text4(flags.content) ?? process.cwd());
47642
+ const dir = resolve38(text5(flags.content) ?? process.cwd());
47608
47643
  const local = readPushOnboarding(dir);
47609
47644
  const progress = local.push;
47610
47645
  const content = pushInputsFromContent(dir);
@@ -47636,26 +47671,10 @@ async function runNotifySetup(pos, flags, io, deps = {}) {
47636
47671
  return 2;
47637
47672
  }
47638
47673
  if (operation === "setup" && ascGroupError(input)) return refuse2(io, "incomplete_asc_group");
47639
- let target;
47640
- try {
47641
- target = resolveTarget({ target: text4(flags.target), defaultTarget: "wix", controlUrl: text4(flags["control-url"]), controlToken: text4(flags["control-token"]), ownerIssueUrl: text4(flags["owner-issue-url"]) });
47642
- } catch {
47643
- return refuse2(io, "unknown_target", "Select a configured serve target.");
47644
- }
47645
- if (credentialHostRefusal(target.control)) return refuse2(io, "insecure_target");
47646
- const previewTag = text4(flags["preview-tag"]) ?? process.env.HIMI_SERVE_PREVIEW_TAG;
47647
- if (previewTag !== void 0 && !/^dp-[a-z0-9]+$/.test(previewTag)) return refuse2(io, "invalid_preview_tag");
47648
- const token = target.controlToken;
47649
- if (!token || !decodeControlTokenClaims(token)?.sub) return refuse2(io, "owner_login_required", "Run himi login --browser --target wix.");
47650
- let wixToken;
47651
- try {
47652
- wixToken = await (deps.wixToken ?? accountToken)();
47653
- } catch {
47654
- return refuse2(io, "wix_account_token_required", "Browser login supplies a Himi control token only. Sign into the Wix CLI with wix login, using the same Wix account, then retry. You can continue building without push setup.", 1);
47655
- }
47656
- if (!wixToken) return refuse2(io, "wix_account_token_required", "Run wix login using the same Wix account.", 1);
47657
- if (!target.ownerIssue) return refuse2(io, "owner_issuer_required");
47658
- const ownershipArgs = { ownerIssue: target.ownerIssue, controlToken: token, declaredName: input.app, fetchImpl: deps.fetchImpl };
47674
+ const owner = await hostedOwnerSession(flags, deps);
47675
+ if (!owner.ok) return refuse2(io, owner.error, owner.hint, owner.exit);
47676
+ const { target, controlToken: token, wixToken, previewTag, ownerIssue } = owner.session;
47677
+ const ownershipArgs = { ownerIssue, controlToken: token, declaredName: input.app, fetchImpl: deps.fetchImpl };
47659
47678
  let ownership = await verifyAppOwnership(ownershipArgs);
47660
47679
  logOwnershipFailure(io, ownership);
47661
47680
  if (ownership.state !== "owned" && ownership.state !== "not_claimed") return refuse2(io, `app_ownership_${ownership.state}`, "Setup requires the app owner; retry after ownership is verified.", 1);
@@ -47701,7 +47720,7 @@ async function runNotifySetup(pos, flags, io, deps = {}) {
47701
47720
  }
47702
47721
  }
47703
47722
  if (ownership.state === "not_claimed") {
47704
- const claim = await autoClaimSlug({ ownerIssue: target.ownerIssue, controlToken: token, app: input.app, accountId: text4(flags["account-id"]), fetchImpl: deps.fetchImpl });
47723
+ const claim = await autoClaimSlug({ ownerIssue, controlToken: token, app: input.app, accountId: text5(flags["account-id"]), fetchImpl: deps.fetchImpl });
47705
47724
  if (claim.fatal) return refuse2(io, "app_claim_refused", "Check app ownership and the selected account.", 1);
47706
47725
  ownership = await verifyAppOwnership({ ...ownershipArgs, declaredName: claim.slug ?? input.app });
47707
47726
  logOwnershipFailure(io, ownership);
@@ -47751,17 +47770,15 @@ async function offerPushSetup(options) {
47751
47770
  return { status: "needs_attention", resume: resume(contentDir2) };
47752
47771
  }
47753
47772
  }
47754
- var text4, obj2, STATES, CHECKS, CHECK_STATES, STAGES, ERROR_CODES, PROMPTS, later, resume;
47773
+ var text5, obj2, STATES, CHECKS, CHECK_STATES, STAGES, ERROR_CODES, PROMPTS, later, resume;
47755
47774
  var init_notify_setup = __esm({
47756
47775
  "src/notify-setup.ts"() {
47757
- init_config();
47758
- init_credential_hosts();
47759
47776
  init_push_setup();
47760
47777
  init_push_setup_apple_credentials();
47761
- init_wix_owner();
47762
47778
  init_owner_claim();
47779
+ init_hosted_owner();
47763
47780
  init_push_onboarding();
47764
- text4 = (v) => typeof v === "string" && v.length > 0 ? v : void 0;
47781
+ text5 = (v) => typeof v === "string" && v.length > 0 ? v : void 0;
47765
47782
  obj2 = (v) => v && typeof v === "object" && !Array.isArray(v) ? v : {};
47766
47783
  STATES = /* @__PURE__ */ new Set(["not_configured", "provisioning", "ready", "needs_attention"]);
47767
47784
  CHECKS = ["brandedRecord", "pingApns", "pingFcm", "appleSigning", "nativeBuild", "himiRouting", "deviceDelivery"];
@@ -48456,7 +48473,7 @@ function thin(items, max) {
48456
48473
  function planReel(dir) {
48457
48474
  const memory = loadMemory2(dir);
48458
48475
  const { entries } = readProgress(dir);
48459
- const summary = summarizeProgress(entries);
48476
+ const summary2 = summarizeProgress(entries);
48460
48477
  const manifest = readJson5(join45(dir, "himalaya.content.json"));
48461
48478
  const tokens = readJson5(join45(dir, "tokens.json"));
48462
48479
  const accentToken = tokens?.colors?.accentPrimary;
@@ -48476,9 +48493,9 @@ function planReel(dir) {
48476
48493
  by: isCliEntry(e) ? CLI_AUTHOR : null,
48477
48494
  files: (Array.isArray(e.images) ? e.images : []).map((i) => isObj3(i) && typeof i.file === "string" ? basename13(i.file) : "").filter((f) => HISTORY_NAME.test(f))
48478
48495
  }));
48479
- const times = [summary.startedAt, ...timeline.map((t) => t.ts), memory?.createdAt].filter((x) => !!x).sort();
48496
+ const times = [summary2.startedAt, ...timeline.map((t) => t.ts), memory?.createdAt].filter((x) => !!x).sort();
48480
48497
  const startedAt = times[0] ?? null;
48481
- const endedAt = [summary.lastAt, ...timeline.map((t) => t.ts)].filter((x) => !!x).sort().pop() ?? null;
48498
+ const endedAt = [summary2.lastAt, ...timeline.map((t) => t.ts)].filter((x) => !!x).sort().pop() ?? null;
48482
48499
  return {
48483
48500
  app: typeof manifest?.name === "string" && manifest.name ? manifest.name : basename13(dir),
48484
48501
  accent,
@@ -48778,9 +48795,9 @@ async function firstLookAtInit(dir, opts) {
48778
48795
  child.on("error", (e) => finish2({ skipped: `the render did not start: ${e.message}` }));
48779
48796
  child.on("close", (code) => {
48780
48797
  clearTimeout(hardKill);
48781
- let report2 = null;
48798
+ let report3 = null;
48782
48799
  try {
48783
- report2 = JSON.parse(Buffer.concat(out2).toString("utf8"));
48800
+ report3 = JSON.parse(Buffer.concat(out2).toString("utf8"));
48784
48801
  } catch {
48785
48802
  }
48786
48803
  let fresh = false;
@@ -48789,7 +48806,7 @@ async function firstLookAtInit(dir, opts) {
48789
48806
  } catch {
48790
48807
  }
48791
48808
  if (code === 0 && fresh) return finish2({ image: `.himi/shots/${home}.png` });
48792
- if (report2?.pngUnavailable) return finish2({ skipped: "no headless browser to draw the PNG \u2014 `npx playwright install chromium`, then run the render step below" });
48809
+ if (report3?.pngUnavailable) return finish2({ skipped: "no headless browser to draw the PNG \u2014 `npx playwright install chromium`, then run the render step below" });
48793
48810
  let refusal = null;
48794
48811
  for (const line of errTail.trim().split("\n").reverse()) {
48795
48812
  try {
@@ -48799,7 +48816,7 @@ async function firstLookAtInit(dir, opts) {
48799
48816
  }
48800
48817
  if (refusal) break;
48801
48818
  }
48802
- const why = typeof report2?.reason === "string" ? report2.reason : typeof report2?.error === "string" ? report2.error : refusal;
48819
+ const why = typeof report3?.reason === "string" ? report3.reason : typeof report3?.error === "string" ? report3.error : refusal;
48803
48820
  finish2({ skipped: `the render made no picture (exit ${code ?? "killed"})${why ? `: ${why.slice(0, 200)}` : ""}` });
48804
48821
  });
48805
48822
  });
@@ -49754,9 +49771,9 @@ function bundlesOf(block) {
49754
49771
  walk2(block);
49755
49772
  return [...out2];
49756
49773
  }
49757
- function parseJson2(text6, what) {
49774
+ function parseJson2(text8, what) {
49758
49775
  try {
49759
- const value = JSON.parse(text6);
49776
+ const value = JSON.parse(text8);
49760
49777
  if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("not an object");
49761
49778
  return value;
49762
49779
  } catch (e) {
@@ -49991,25 +50008,25 @@ function pruneChrome(items, removed, ledger) {
49991
50008
  }
49992
50009
  function rewriteNav(nav, removed, homeId) {
49993
50010
  const next = structuredClone(nav);
49994
- const report2 = { linkable: [], tabs: [], drawer: [], sidebar: [], deepLinkPatterns: [], topBarActions: [], headerActions: [], surfaceDestinations: [], appIconBadgeSources: [], reparented: [] };
50011
+ const report3 = { linkable: [], tabs: [], drawer: [], sidebar: [], deepLinkPatterns: [], topBarActions: [], headerActions: [], surfaceDestinations: [], appIconBadgeSources: [], reparented: [] };
49995
50012
  const tabItems = asItems(next.tabBar);
49996
50013
  const hadTabs = !!tabItems?.length;
49997
- if (tabItems) next.tabBar.items = pruneChrome(tabItems, removed, report2.tabs);
50014
+ if (tabItems) next.tabBar.items = pruneChrome(tabItems, removed, report3.tabs);
49998
50015
  const drawerItems = asItems(next.drawer);
49999
- if (drawerItems) next.drawer.items = pruneChrome(drawerItems, removed, report2.drawer);
50016
+ if (drawerItems) next.drawer.items = pruneChrome(drawerItems, removed, report3.drawer);
50000
50017
  const sidebarItems = asItems(next.sidebar);
50001
- if (sidebarItems) next.sidebar.items = pruneChrome(sidebarItems, removed, report2.sidebar);
50018
+ if (sidebarItems) next.sidebar.items = pruneChrome(sidebarItems, removed, report3.sidebar);
50002
50019
  if (hadTabs && !asItems(next.tabBar).length) {
50003
- throw new TrimRefusal(`no tab would remain \u2014 every tabBar item opens a screen this trim removes (${report2.tabs.join(", ")}); keep at least one tab's screen`, { removedTabs: report2.tabs });
50020
+ throw new TrimRefusal(`no tab would remain \u2014 every tabBar item opens a screen this trim removes (${report3.tabs.join(", ")}); keep at least one tab's screen`, { removedTabs: report3.tabs });
50004
50021
  }
50005
50022
  const remainingRoots = [...asItems(next.tabBar) ?? [], ...asItems(next.sidebar) ?? []].filter((i) => i.role !== "section");
50006
50023
  const remainingRootIds = new Set(remainingRoots.map((i) => i.id).filter((id) => typeof id === "string"));
50007
- const removedRootIds = /* @__PURE__ */ new Set([...report2.tabs, ...report2.sidebar]);
50024
+ const removedRootIds = /* @__PURE__ */ new Set([...report3.tabs, ...report3.sidebar]);
50008
50025
  if (Array.isArray(next.deepLinkPatterns)) {
50009
50026
  next.deepLinkPatterns = next.deepLinkPatterns.filter((p) => {
50010
50027
  const id = p?.params?.screenId ?? p?.screenId;
50011
50028
  if (typeof id === "string" && removed(id)) {
50012
- report2.deepLinkPatterns.push(String(p.pattern ?? id));
50029
+ report3.deepLinkPatterns.push(String(p.pattern ?? id));
50013
50030
  return false;
50014
50031
  }
50015
50032
  return true;
@@ -50020,7 +50037,7 @@ function rewriteNav(nav, removed, homeId) {
50020
50037
  if (!Array.isArray(actions)) continue;
50021
50038
  next[key2].header.actions = actions.filter((a) => {
50022
50039
  if (!(typeof a?.screenId === "string" && removed(a.screenId))) return true;
50023
- report2.headerActions.push(`${key2}:${String(a.icon ?? a.screenId)}`);
50040
+ report3.headerActions.push(`${key2}:${String(a.icon ?? a.screenId)}`);
50024
50041
  return false;
50025
50042
  });
50026
50043
  }
@@ -50029,7 +50046,7 @@ function rewriteNav(nav, removed, homeId) {
50029
50046
  next.topBarDefault.actions = topActions.filter((a) => {
50030
50047
  const to = openTarget(a?.onTap) ?? openTarget(a?.action);
50031
50048
  if (to && removed(to)) {
50032
- report2.topBarActions.push(entryLabel(a));
50049
+ report3.topBarActions.push(entryLabel(a));
50033
50050
  return false;
50034
50051
  }
50035
50052
  return true;
@@ -50044,7 +50061,7 @@ function rewriteNav(nav, removed, homeId) {
50044
50061
  for (const [dest, screenId] of Object.entries(cfg.screenIds)) {
50045
50062
  if (goneDest(dest) || typeof screenId === "string" && removed(screenId)) {
50046
50063
  delete cfg.screenIds[dest];
50047
- report2.surfaceDestinations.push(`${surface}:${dest}`);
50064
+ report3.surfaceDestinations.push(`${surface}:${dest}`);
50048
50065
  if (!remainingRootIds.has(dest)) unmapped.add(dest);
50049
50066
  }
50050
50067
  }
@@ -50054,24 +50071,24 @@ function rewriteNav(nav, removed, homeId) {
50054
50071
  const gone = goneDest(id) || typeof id === "string" && unmapped.has(id);
50055
50072
  if (!gone) return true;
50056
50073
  const entry = `${surface}:${String(id)}`;
50057
- if (!report2.surfaceDestinations.includes(entry)) report2.surfaceDestinations.push(entry);
50074
+ if (!report3.surfaceDestinations.includes(entry)) report3.surfaceDestinations.push(entry);
50058
50075
  return false;
50059
50076
  });
50060
50077
  }
50061
50078
  }
50062
50079
  }
50063
50080
  if (Array.isArray(next.appIconBadgeSources)) {
50064
- const goneActions = new Set(report2.topBarActions);
50081
+ const goneActions = new Set(report3.topBarActions);
50065
50082
  const idsOf = (items) => new Set((items ?? []).map((i) => i.id).filter((x) => typeof x === "string"));
50066
- const removedTabs = new Set(report2.tabs);
50067
- const removedDrawer = new Set(report2.drawer);
50083
+ const removedTabs = new Set(report3.tabs);
50084
+ const removedDrawer = new Set(report3.drawer);
50068
50085
  const remainingTabIds = idsOf(asItems(next.tabBar));
50069
50086
  const remainingDrawerIds = idsOf(asItems(next.drawer));
50070
50087
  next.appIconBadgeSources = next.appIconBadgeSources.filter((s) => {
50071
50088
  if (typeof s !== "string") return true;
50072
50089
  const [kind, id] = [s.slice(0, s.indexOf(":")), s.slice(s.indexOf(":") + 1)];
50073
50090
  const gone = kind === "topBarAction" ? goneActions.has(id) : kind === "tab" ? removedTabs.has(id) && !remainingTabIds.has(id) : kind === "drawer" ? removedDrawer.has(id) && !remainingDrawerIds.has(id) : false;
50074
- if (gone) report2.appIconBadgeSources.push(s);
50091
+ if (gone) report3.appIconBadgeSources.push(s);
50075
50092
  return !gone;
50076
50093
  });
50077
50094
  }
@@ -50081,7 +50098,7 @@ function rewriteNav(nav, removed, homeId) {
50081
50098
  for (const l of original) if (typeof l.screenId === "string") byId.set(l.screenId, l);
50082
50099
  const kept = original.filter((l) => {
50083
50100
  if (typeof l.screenId === "string" && removed(l.screenId)) {
50084
- report2.linkable.push(l.screenId);
50101
+ report3.linkable.push(l.screenId);
50085
50102
  return false;
50086
50103
  }
50087
50104
  return true;
@@ -50125,7 +50142,7 @@ function rewriteNav(nav, removed, homeId) {
50125
50142
  const entry = { screenId: String(l.screenId) };
50126
50143
  if (toParent !== fromParent) entry.parentScreenId = { from: fromParent, to: toParent };
50127
50144
  if (toTab !== fromTab) entry.tabId = { from: fromTab, to: toTab };
50128
- report2.reparented.push(entry);
50145
+ report3.reparented.push(entry);
50129
50146
  }
50130
50147
  for (const l of kept) {
50131
50148
  if (typeof l.parentScreenId === "string") l.parentScreenId = newParent(l);
@@ -50133,7 +50150,7 @@ function rewriteNav(nav, removed, homeId) {
50133
50150
  }
50134
50151
  next.linkableScreens = kept;
50135
50152
  }
50136
- return { nav: next, report: report2 };
50153
+ return { nav: next, report: report3 };
50137
50154
  }
50138
50155
  function leftoverNavRefs(nav, removedIds) {
50139
50156
  const gone = new Set(removedIds);
@@ -50292,9 +50309,9 @@ function planTrim(src, keepIds, links) {
50292
50309
  for (const r of keptRoutes) for (const b of r.bundles) keptWorkers.add(b);
50293
50310
  const importsOf = (dir) => {
50294
50311
  const out2 = [];
50295
- for (const [rel, text6] of Object.entries(src.workerFiles)) {
50312
+ for (const [rel, text8] of Object.entries(src.workerFiles)) {
50296
50313
  if (!rel.startsWith(`tier5-src/${dir}/`)) continue;
50297
- for (const m of text6.matchAll(/(?:\bfrom\s*|\bimport\s*\(?\s*|\brequire\s*\(\s*)["']\.\.\/([A-Za-z0-9_.-]+)(?:\/|["'])/g)) out2.push(m[1]);
50314
+ for (const m of text8.matchAll(/(?:\bfrom\s*|\bimport\s*\(?\s*|\brequire\s*\(\s*)["']\.\.\/([A-Za-z0-9_.-]+)(?:\/|["'])/g)) out2.push(m[1]);
50298
50315
  }
50299
50316
  return out2;
50300
50317
  };
@@ -50340,9 +50357,9 @@ function planTrim(src, keepIds, links) {
50340
50357
  continue;
50341
50358
  }
50342
50359
  const block = edited.get(r);
50343
- let text6 = block ? serializeAt(block, app.dev, r.open) : void 0;
50344
- if (r === app.home && homeModules?.text !== void 0) text6 = homeModules.text;
50345
- if (text6 !== void 0) cut2(r.open, r.close, text6);
50360
+ let text8 = block ? serializeAt(block, app.dev, r.open) : void 0;
50361
+ if (r === app.home && homeModules?.text !== void 0) text8 = homeModules.text;
50362
+ if (text8 !== void 0) cut2(r.open, r.close, text8);
50346
50363
  }
50347
50364
  if (templatedEmptied) cut2(templatedEmptied[0], templatedEmptied[1], "\n");
50348
50365
  dev += app.dev.slice(cursor);
@@ -50358,7 +50375,7 @@ function planTrim(src, keepIds, links) {
50358
50375
  for (const e of edits.sort((a, b) => b.start - a.start)) config = config.slice(0, e.start) + e.text + config.slice(e.end);
50359
50376
  const keptExact = keptRoutes.filter((r) => r.kind === "screen");
50360
50377
  const keptTemplated = keptRoutes.filter((r) => r.kind === "templated");
50361
- const report2 = {
50378
+ const report3 = {
50362
50379
  ...links ? { links } : {},
50363
50380
  kept: { screens: sorted(keptExact.map((r) => r.label)), templated: sorted(keptTemplated.map((r) => r.label)) },
50364
50381
  implicit: implicit.map((r) => r.label),
@@ -50388,16 +50405,16 @@ function planTrim(src, keepIds, links) {
50388
50405
  },
50389
50406
  bytes: { before: Buffer.byteLength(app.dev), after: Buffer.byteLength(dev) }
50390
50407
  };
50391
- return { dev, config, removedWorkers, removedIds, report: report2 };
50408
+ return { dev, config, removedWorkers, removedIds, report: report3 };
50392
50409
  }
50393
50410
  function homeModulesPass(app, kept, edited) {
50394
50411
  const verticals = Object.entries(EXPLORE_CARDS).filter(([, card2]) => app.exact.has(card2.screenId));
50395
50412
  const removedVertical = verticals.some(([, card2]) => !kept.has(app.exact.get(card2.screenId)));
50396
50413
  if (!removedVertical) return { dropped: [] };
50397
50414
  const block = edited.get(app.home);
50398
- const text6 = block ? serializeAt(block, app.dev, app.home.open) : app.dev.slice(app.home.open, app.home.close);
50415
+ const text8 = block ? serializeAt(block, app.dev, app.home.open) : app.dev.slice(app.home.open, app.home.close);
50399
50416
  const installed = verticals.filter(([, card2]) => kept.has(app.exact.get(card2.screenId))).map(([v]) => v);
50400
- const patched = patchHomeModules(text6, installed);
50417
+ const patched = patchHomeModules(text8, installed);
50401
50418
  if (!patched.droppedModules.length) return { dropped: [] };
50402
50419
  return { text: patched.src, dropped: patched.droppedModules };
50403
50420
  }
@@ -51111,8 +51128,8 @@ function isNoneEntry(entry) {
51111
51128
  const head = entryHead(entry);
51112
51129
  return NONE.test(entry) || head !== "" && NONE.test(head);
51113
51130
  }
51114
- function parseDataAccess(text6, from) {
51115
- const body = text6.replace(/<!--[\s\S]*?(?:-->|$)/g, "");
51131
+ function parseDataAccess(text8, from) {
51132
+ const body = text8.replace(/<!--[\s\S]*?(?:-->|$)/g, "");
51116
51133
  const heading = new RegExp(`(?:^|\\n)##[ \\t]+${DATA_ACCESS_HEADING}\\b[^\\n]*([\\s\\S]*?)(?=\\n##[ \\t]|$)`, "i").exec(body);
51117
51134
  if (!heading) return null;
51118
51135
  const lines = heading[1].split("\n").map((l) => l.trim()).filter((l) => l.startsWith("|"));
@@ -51139,13 +51156,13 @@ function readDataAccess(dir) {
51139
51156
  for (const name of ["SPEC.md", "MOBILE-UX.md"]) {
51140
51157
  const p = join49(dir, name);
51141
51158
  if (!existsSync50(p)) continue;
51142
- let text6;
51159
+ let text8;
51143
51160
  try {
51144
- text6 = readFileSync55(p, "utf8");
51161
+ text8 = readFileSync55(p, "utf8");
51145
51162
  } catch {
51146
51163
  continue;
51147
51164
  }
51148
- const plan = parseDataAccess(text6, name);
51165
+ const plan = parseDataAccess(text8, name);
51149
51166
  if (plan) return plan;
51150
51167
  }
51151
51168
  return null;
@@ -51298,7 +51315,7 @@ function readTestConfig(dir) {
51298
51315
  if (input !== void 0 && (!input || typeof input !== "object" || Array.isArray(input) || Object.values(input).some((v) => typeof v !== "string"))) {
51299
51316
  throw new Error(`${TEST_CONFIG_FILE}: journeys[${i}].input must be an object of string values \u2014 the screen input a nav edge would send, e.g. { "id": "svc-0001" }`);
51300
51317
  }
51301
- if (!Array.isArray(journey.expectText) || !journey.expectText.length || journey.expectText.some((text6) => typeof text6 !== "string" || !text6.trim())) {
51318
+ if (!Array.isArray(journey.expectText) || !journey.expectText.length || journey.expectText.some((text8) => typeof text8 !== "string" || !text8.trim())) {
51302
51319
  throw new Error(`${TEST_CONFIG_FILE}: journeys[${i}] needs non-empty expectText values that prove a visible result`);
51303
51320
  }
51304
51321
  });
@@ -51359,16 +51376,16 @@ function readCannedResponses() {
51359
51376
  }
51360
51377
  function makeRecordingWixCall(send2, token, app) {
51361
51378
  const events = [];
51362
- const refused = [];
51379
+ const refused2 = [];
51363
51380
  let id = 0;
51364
51381
  const call = async (method, path2, body) => {
51365
51382
  const verb = method.toUpperCase();
51366
51383
  if (/[#\x00-\x1F\x7F]/.test(path2)) {
51367
- refused.push(`${verb} ${path2}`);
51384
+ refused2.push(`${verb} ${path2}`);
51368
51385
  throw new Error(`--record refused ${verb} ${path2}: the path carries a fragment or control character \u2014 not a provable read`);
51369
51386
  }
51370
51387
  if (!isProvenRead(verb, path2)) {
51371
- refused.push(`${verb} ${path2}`);
51388
+ refused2.push(`${verb} ${path2}`);
51372
51389
  throw new Error(`--record refused ${verb} ${path2}: recording sends only proven reads (GET, or POST ending in /query, /search, /list*, /get*, /count, /aggregate, /facets, /connections) \u2014 if this IS a read, add its rule to dev/net-mocks.json by hand`);
51373
51390
  }
51374
51391
  const bodyStr = body === void 0 ? void 0 : typeof body === "string" ? body : JSON.stringify(body);
@@ -51395,7 +51412,7 @@ function makeRecordingWixCall(send2, token, app) {
51395
51412
  return r.body;
51396
51413
  }
51397
51414
  };
51398
- return { call, events, refused };
51415
+ return { call, events, refused: refused2 };
51399
51416
  }
51400
51417
  async function runRecordPass(opts) {
51401
51418
  const bootErrors = [];
@@ -51799,9 +51816,9 @@ function formatReport(r) {
51799
51816
  out2.push(`transport: ${r.transport}`);
51800
51817
  if (r.nativeDecode) {
51801
51818
  for (const platform of ["ios", "android"]) {
51802
- const summary = r.nativeDecode[platform];
51803
- if (!summary) continue;
51804
- out2.push("unavailable" in summary ? `native decode ${platform}: unavailable \u2014 ${summary.reason}` : `native decode ${platform}: ${summary.checked} checked, ${summary.failed} failed in ${r.nativeDecode.wallMs}ms`);
51819
+ const summary2 = r.nativeDecode[platform];
51820
+ if (!summary2) continue;
51821
+ out2.push("unavailable" in summary2 ? `native decode ${platform}: unavailable \u2014 ${summary2.reason}` : `native decode ${platform}: ${summary2.checked} checked, ${summary2.failed} failed in ${r.nativeDecode.wallMs}ms`);
51805
51822
  }
51806
51823
  }
51807
51824
  out2.push("");
@@ -51944,14 +51961,14 @@ import { join as join51 } from "node:path";
51944
51961
  function mobileUxIssues(dir, strict) {
51945
51962
  const file = join51(dir, "MOBILE-UX.md");
51946
51963
  if (!existsSync52(file)) return [];
51947
- let text6;
51964
+ let text8;
51948
51965
  try {
51949
- text6 = readFileSync57(file, "utf8");
51966
+ text8 = readFileSync57(file, "utf8");
51950
51967
  } catch {
51951
51968
  return [];
51952
51969
  }
51953
- if (!text6) return [];
51954
- return mobileUxMarkerFindings(text6, recordedRenderWidths(dir)).map((finding) => {
51970
+ if (!text8) return [];
51971
+ return mobileUxMarkerFindings(text8, recordedRenderWidths(dir)).map((finding) => {
51955
51972
  const scaffoldAdvisory = finding.code === "missing-width-evidence";
51956
51973
  return {
51957
51974
  screen: null,
@@ -52246,7 +52263,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
52246
52263
  const headers2 = Object.fromEntries(new Headers(init.headers).entries());
52247
52264
  const request = url.protocol === "https:" ? httpsRequest : httpRequest;
52248
52265
  const hostname2 = url.hostname.replace(/^\[|\]$/g, "");
52249
- return await new Promise((resolve52, reject) => {
52266
+ return await new Promise((resolve53, reject) => {
52250
52267
  let settled = false;
52251
52268
  const finish2 = (fn) => {
52252
52269
  if (settled) return;
@@ -52283,7 +52300,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
52283
52300
  }
52284
52301
  const responseHeaders = new Headers();
52285
52302
  for (const [key2, value] of Object.entries(response.headers)) if (value !== void 0) responseHeaders.set(key2, Array.isArray(value) ? value.join(", ") : value);
52286
- resolve52(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
52303
+ resolve53(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
52287
52304
  }));
52288
52305
  });
52289
52306
  req.once("error", (error) => finish2(() => reject(error)));
@@ -52583,7 +52600,7 @@ function createLocalTestSandbox() {
52583
52600
  }
52584
52601
  })();
52585
52602
  `;
52586
- return await new Promise((resolve52, reject) => {
52603
+ return await new Promise((resolve53, reject) => {
52587
52604
  const { port1, port2 } = new MessageChannel();
52588
52605
  const serializableContext = {
52589
52606
  auth: context.auth,
@@ -52659,7 +52676,7 @@ function createLocalTestSandbox() {
52659
52676
  timer = setTimeout(() => finish2(() => reject(new SandboxError("timeout", `execution exceeded ${limits.timeoutMs}ms`))), Math.max(1, limits.timeoutMs));
52660
52677
  return;
52661
52678
  }
52662
- if (message.ok) finish2(() => resolve52({ value: message.value, durationMs: Date.now() - started }));
52679
+ if (message.ok) finish2(() => resolve53({ value: message.value, durationMs: Date.now() - started }));
52663
52680
  else finish2(() => reject(new SandboxError("execution_failed", message.message ?? "handler failed")));
52664
52681
  });
52665
52682
  worker.once("error", (error) => finish2(() => reject(new SandboxError("execution_failed", error.message))));
@@ -53775,12 +53792,12 @@ async function runRemoteFunctionOperation(input) {
53775
53792
  if (input.boCookie) headers2.cookie = input.boCookie;
53776
53793
  if (input.previewToken) headers2["x-himalaya-preview-token"] = input.previewToken;
53777
53794
  const response = await (input.fetchImpl ?? fetch)(url, { method, headers: headers2 });
53778
- const text6 = await response.text();
53795
+ const text8 = await response.text();
53779
53796
  let body;
53780
53797
  try {
53781
- body = JSON.parse(text6);
53798
+ body = JSON.parse(text8);
53782
53799
  } catch {
53783
- body = text6;
53800
+ body = text8;
53784
53801
  }
53785
53802
  return { ok: response.ok, status: response.status, body };
53786
53803
  }
@@ -53868,7 +53885,7 @@ function flagShapedInputs(args) {
53868
53885
  function guarded(h) {
53869
53886
  return async (args, deps) => {
53870
53887
  const bad2 = flagShapedInputs(args);
53871
- if (bad2.length) return text5(`refused: ${bad2.join(", ")} may not start with "-" (it would be read as a himi flag)`, true);
53888
+ if (bad2.length) return text6(`refused: ${bad2.join(", ")} may not start with "-" (it would be read as a himi flag)`, true);
53872
53889
  return h(args, deps);
53873
53890
  };
53874
53891
  }
@@ -54021,7 +54038,7 @@ function rawTools() {
54021
54038
  return json3({ ...await d.preview.start(await appDir2(a, d)), hint: PREVIEW_HINT });
54022
54039
  } catch (e) {
54023
54040
  const log = e.log;
54024
- return text5(`${e.message}${typeof log === "string" && log ? `
54041
+ return text6(`${e.message}${typeof log === "string" && log ? `
54025
54042
 
54026
54043
  ${log}` : ""}`, true);
54027
54044
  }
@@ -54097,14 +54114,14 @@ ${log}` : ""}`, true);
54097
54114
  }
54098
54115
  ];
54099
54116
  }
54100
- var MAX_TEXT2, clip, text5, json3, opt, sw, DIR, LEARN, CHECK, LOCAL_WRITE, PUBLISH, PREVIEW_HINT, LOGIN_HINT;
54117
+ var MAX_TEXT2, clip, text6, json3, opt, sw, DIR, LEARN, CHECK, LOCAL_WRITE, PUBLISH, PREVIEW_HINT, LOGIN_HINT;
54101
54118
  var init_tools = __esm({
54102
54119
  "src/mcp/tools.ts"() {
54103
54120
  MAX_TEXT2 = 8e4;
54104
54121
  clip = (s) => s.length <= MAX_TEXT2 ? s : `${s.slice(0, MAX_TEXT2)}
54105
54122
  \u2026 [truncated ${s.length - MAX_TEXT2} chars \u2014 re-run the command in a terminal for the full output]`;
54106
- text5 = (t, isError = false) => ({ content: [{ type: "text", text: t }], ...isError ? { isError: true } : {} });
54107
- json3 = (o) => text5(JSON.stringify(o, null, 2));
54123
+ text6 = (t, isError = false) => ({ content: [{ type: "text", text: t }], ...isError ? { isError: true } : {} });
54124
+ json3 = (o) => text6(JSON.stringify(o, null, 2));
54108
54125
  opt = (flag, v) => typeof v === "string" && v ? [flag, v] : typeof v === "number" ? [flag, String(v)] : [];
54109
54126
  sw = (flag, v) => v === true ? [flag] : [];
54110
54127
  DIR = z.string().optional().describe("The app (content package) directory. Default: the workspace root the host opened, else the server's working directory.");
@@ -54180,9 +54197,9 @@ async function startMcpServer(opts) {
54180
54197
  },
54181
54198
  readFile: (p) => readFileSync59(p)
54182
54199
  };
54183
- const closed = new Promise((resolve52) => {
54184
- stdin.once("end", resolve52);
54185
- stdin.once("close", resolve52);
54200
+ const closed = new Promise((resolve53) => {
54201
+ stdin.once("end", resolve53);
54202
+ stdin.once("close", resolve53);
54186
54203
  });
54187
54204
  const handle = serveStdio(
54188
54205
  () => {
@@ -54424,7 +54441,7 @@ function fieldAt(path2) {
54424
54441
  if (path2 === null) return void 0;
54425
54442
  return path2.match(/\.([^.[\]]+)$/)?.[1];
54426
54443
  }
54427
- function mergeNativeDecode(report2, run2) {
54444
+ function mergeNativeDecode(report3, run2) {
54428
54445
  const platformLabel = run2.platform === "ios" ? "iOS" : "Android";
54429
54446
  const nativeFailures = run2.verdicts.flatMap((verdict) => verdict.errors.map((error) => ({
54430
54447
  screen: verdict.screenId,
@@ -54437,18 +54454,18 @@ function mergeNativeDecode(report2, run2) {
54437
54454
  ...error.actual ? { actual: error.actual } : {},
54438
54455
  hint: `This descriptor ships as a full-screen \u201CCouldn't load\u201D; fix the typed field and rerun \`himi test --native ${run2.platform}\`.`
54439
54456
  })));
54440
- const failures = [...report2.failures, ...nativeFailures];
54457
+ const failures = [...report3.failures, ...nativeFailures];
54441
54458
  const failedScreens = new Set(failures.map((finding) => finding.screen));
54442
54459
  return {
54443
- ...report2,
54444
- ok: report2.ok && nativeFailures.length === 0,
54460
+ ...report3,
54461
+ ok: report3.ok && nativeFailures.length === 0,
54445
54462
  failures,
54446
- counts: { ...report2.counts, errors: failures.length },
54447
- screens: { ...report2.screens, clean: report2.screens.total - failedScreens.size, failed: failedScreens.size },
54463
+ counts: { ...report3.counts, errors: failures.length },
54464
+ screens: { ...report3.screens, clean: report3.screens.total - failedScreens.size, failed: failedScreens.size },
54448
54465
  nativeDecode: {
54449
- ...report2.nativeDecode,
54466
+ ...report3.nativeDecode,
54450
54467
  [run2.platform]: { checked: run2.verdicts.length, failed: run2.verdicts.filter((verdict) => !verdict.ok).length },
54451
- wallMs: (report2.nativeDecode?.wallMs ?? 0) + run2.wallMs
54468
+ wallMs: (report3.nativeDecode?.wallMs ?? 0) + run2.wallMs
54452
54469
  }
54453
54470
  };
54454
54471
  }
@@ -54561,10 +54578,10 @@ function collectSdkModules(files, resolveSubpath) {
54561
54578
  for (const source of Object.values(files)) visit(source);
54562
54579
  return { modules, unsupported };
54563
54580
  }
54564
- function sdkSubpathReader(resolve52) {
54581
+ function sdkSubpathReader(resolve53) {
54565
54582
  return (sub) => {
54566
54583
  try {
54567
- return readFileSync61(resolve52(`@wix/himalaya/${sub}`), "utf8");
54584
+ return readFileSync61(resolve53(`@wix/himalaya/${sub}`), "utf8");
54568
54585
  } catch {
54569
54586
  return null;
54570
54587
  }
@@ -54642,7 +54659,7 @@ async function runBrowserAuthoring(opts) {
54642
54659
  const token = mintToken2(payload);
54643
54660
  const unusable = await probeAuthoringPage(opts.authoringBase, opts.fetchImpl, opts.probeTimeoutMs);
54644
54661
  if (unusable) throw new Error(unusable);
54645
- return await new Promise((resolve52, reject) => {
54662
+ return await new Promise((resolve53, reject) => {
54646
54663
  let settled = false;
54647
54664
  let url = "";
54648
54665
  const server = createServer5();
@@ -54693,8 +54710,8 @@ async function runBrowserAuthoring(opts) {
54693
54710
  return;
54694
54711
  }
54695
54712
  res.writeHead(200, { "content-type": "text/plain" }).end("ok");
54696
- const report2 = body.result;
54697
- finish2(() => resolve52({ report: report2, url }));
54713
+ const report3 = body.result;
54714
+ finish2(() => resolve53({ report: report3, url }));
54698
54715
  })();
54699
54716
  });
54700
54717
  server.on("error", (e) => finish2(() => reject(e)));
@@ -55371,10 +55388,10 @@ async function hostedAuthUrl(req, visitorToken, fetchImpl = fetch) {
55371
55388
  }
55372
55389
  })
55373
55390
  });
55374
- const text6 = await res.text();
55391
+ const text8 = await res.text();
55375
55392
  let parsed = {};
55376
55393
  try {
55377
- parsed = text6 ? JSON.parse(text6) : {};
55394
+ parsed = text8 ? JSON.parse(text8) : {};
55378
55395
  } catch {
55379
55396
  }
55380
55397
  const fullUrl = parsed.redirectSession?.fullUrl;
@@ -55394,10 +55411,10 @@ async function exchangeAuthCode(cfg, code, verifier, fetchImpl = fetch) {
55394
55411
  redirectUri: cfg.redirectUri
55395
55412
  })
55396
55413
  });
55397
- const text6 = await res.text();
55414
+ const text8 = await res.text();
55398
55415
  let parsed = {};
55399
55416
  try {
55400
- parsed = text6 ? JSON.parse(text6) : {};
55417
+ parsed = text8 ? JSON.parse(text8) : {};
55401
55418
  } catch {
55402
55419
  }
55403
55420
  if (res.status !== 200 || !parsed.access_token) throw new Error(`token exchange failed (${res.status})`);
@@ -56611,11 +56628,11 @@ async function localizeConfigResponse(res, kind, header) {
56611
56628
  header
56612
56629
  )
56613
56630
  };
56614
- const text6 = JSON.stringify(next);
56631
+ const text8 = JSON.stringify(next);
56615
56632
  const headers2 = new Headers(res.headers);
56616
56633
  headers2.delete("etag");
56617
- headers2.set("content-length", String(new TextEncoder().encode(text6).length));
56618
- return new Response(text6, { status: 200, headers: headers2 });
56634
+ headers2.set("content-length", String(new TextEncoder().encode(text8).length));
56635
+ return new Response(text8, { status: 200, headers: headers2 });
56619
56636
  }
56620
56637
  function makeRunHandler(opts) {
56621
56638
  const mount = opts.chrome === "app" ? "/app" : "/preview";
@@ -56803,8 +56820,8 @@ var init_node_adapter = __esm({
56803
56820
  function authConfigOf(appConfig) {
56804
56821
  if (!appConfig) return void 0;
56805
56822
  try {
56806
- const text6 = typeof appConfig === "string" ? appConfig : new TextDecoder().decode(appConfig);
56807
- return JSON.parse(text6)?.authConfig ?? void 0;
56823
+ const text8 = typeof appConfig === "string" ? appConfig : new TextDecoder().decode(appConfig);
56824
+ return JSON.parse(text8)?.authConfig ?? void 0;
56808
56825
  } catch {
56809
56826
  return void 0;
56810
56827
  }
@@ -57414,16 +57431,16 @@ async function releasePayloadFromDir(root, app, header) {
57414
57431
  const manifest = await store.getManifest(app);
57415
57432
  if (!manifest) throw new Error(`no release manifest for ${app} under ${root}`);
57416
57433
  const b64 = (b) => b ? Buffer.from(b).toString("base64") : void 0;
57417
- const text6 = (b) => b ? new TextDecoder().decode(b) : void 0;
57434
+ const text8 = (b) => b ? new TextDecoder().decode(b) : void 0;
57418
57435
  const screens = {};
57419
57436
  const docs = {};
57420
57437
  const addDoc = async (hash) => {
57421
57438
  if (!hash || docs[hash] !== void 0) return;
57422
- const d = text6(await store.getDoc?.(app, hash) ?? null);
57439
+ const d = text8(await store.getDoc?.(app, hash) ?? null);
57423
57440
  if (d !== void 0) docs[hash] = d;
57424
57441
  };
57425
57442
  for (const [id, meta] of Object.entries(manifest.screens ?? {})) {
57426
- const s = text6(await store.getScreen(app, id));
57443
+ const s = text8(await store.getScreen(app, id));
57427
57444
  if (s !== void 0) screens[id] = s;
57428
57445
  await addDoc(meta.descriptorHash);
57429
57446
  }
@@ -57444,10 +57461,10 @@ async function releasePayloadFromDir(root, app, header) {
57444
57461
  }
57445
57462
  const widgets = {};
57446
57463
  for (const id of Object.keys(manifest.widgets ?? {})) {
57447
- const w = text6(await store.getWidget?.(app, id) ?? null);
57464
+ const w = text8(await store.getWidget?.(app, id) ?? null);
57448
57465
  if (w !== void 0) widgets[id] = w;
57449
57466
  }
57450
- const appConfig = text6(await store.getAppConfig(app));
57467
+ const appConfig = text8(await store.getAppConfig(app));
57451
57468
  const wixClientId = appConfigWixClientId(appConfig);
57452
57469
  return {
57453
57470
  app,
@@ -57457,7 +57474,7 @@ async function releasePayloadFromDir(root, app, header) {
57457
57474
  docs,
57458
57475
  assets,
57459
57476
  widgets,
57460
- tokens: text6(await store.getTokens(app)),
57477
+ tokens: text8(await store.getTokens(app)),
57461
57478
  appConfig,
57462
57479
  icon: b64(await store.getIcon?.(app) ?? null),
57463
57480
  header,
@@ -57987,10 +58004,10 @@ function scalar3(v) {
57987
58004
  }
57988
58005
  return t;
57989
58006
  }
57990
- function parseStoreConfig(text6) {
58007
+ function parseStoreConfig(text8) {
57991
58008
  const cfg = {};
57992
58009
  let section2 = null;
57993
- for (const raw of text6.split("\n")) {
58010
+ for (const raw of text8.split("\n")) {
57994
58011
  const line = strip2(raw);
57995
58012
  if (!line.trim()) continue;
57996
58013
  const indented = /^\s+/.test(raw);
@@ -58049,10 +58066,10 @@ function profilePath(name, home = homedir5()) {
58049
58066
  }
58050
58067
  return join59(credentialsDir(home), `${name}.json`);
58051
58068
  }
58052
- function parseProfile(text6, label2) {
58069
+ function parseProfile(text8, label2) {
58053
58070
  let doc;
58054
58071
  try {
58055
- doc = JSON.parse(text6);
58072
+ doc = JSON.parse(text8);
58056
58073
  } catch (e) {
58057
58074
  throw new Error(`${label2} is not valid JSON: ${e.message}`);
58058
58075
  }
@@ -58661,11 +58678,11 @@ async function registerBundleId(opts) {
58661
58678
  const j = await res.json();
58662
58679
  return { status: "created", id: j.data?.id };
58663
58680
  }
58664
- const text6 = await res.text();
58665
- if (res.status === 409 || /already (exists|in use)|duplicate|ENTITY_ERROR.*identifier/i.test(text6)) {
58681
+ const text8 = await res.text();
58682
+ if (res.status === 409 || /already (exists|in use)|duplicate|ENTITY_ERROR.*identifier/i.test(text8)) {
58666
58683
  return { status: "exists" };
58667
58684
  }
58668
- throw new Error(`POST /v1/bundleIds \u2192 ${res.status}: ${text6.slice(0, 300)}`);
58685
+ throw new Error(`POST /v1/bundleIds \u2192 ${res.status}: ${text8.slice(0, 300)}`);
58669
58686
  }
58670
58687
  async function main2() {
58671
58688
  const [app, ...rest] = process.argv.slice(2);
@@ -58943,12 +58960,12 @@ async function runRemoteSecretsCommand(operation, flags, io, options) {
58943
58960
  body = JSON.stringify({ value });
58944
58961
  }
58945
58962
  const response = await (options.fetchImpl ?? fetch)(url, { method: operation === "list" ? "GET" : operation === "set" ? "PUT" : "POST", headers: headers2, body });
58946
- const text6 = await response.text();
58963
+ const text8 = await response.text();
58947
58964
  let output;
58948
58965
  try {
58949
- output = JSON.parse(text6);
58966
+ output = JSON.parse(text8);
58950
58967
  } catch {
58951
- output = text6;
58968
+ output = text8;
58952
58969
  }
58953
58970
  if (!response.ok) throw new Error(typeof output === "string" ? output : JSON.stringify(output));
58954
58971
  io.log(JSON.stringify(output));
@@ -58964,6 +58981,217 @@ var init_secrets2 = __esm({
58964
58981
  }
58965
58982
  });
58966
58983
 
58984
+ // ../serve-cli/src/push-send.ts
58985
+ async function pushSendRequest(options) {
58986
+ const refusal = localRefusal(options);
58987
+ if (refusal) return { ok: false, status: 0, body: null, error: refusal };
58988
+ try {
58989
+ const response = await (options.fetchImpl ?? fetch)(`${options.target.control.replace(/\/+$/, "")}/v1/admin/push/send`, {
58990
+ method: "POST",
58991
+ headers: headersFor(options),
58992
+ redirect: "error",
58993
+ signal: AbortSignal.timeout(TIMEOUT_MS),
58994
+ body: JSON.stringify(options.body)
58995
+ });
58996
+ const retryAfterSec = response.status === 429 ? Number(response.headers.get("retry-after")) : NaN;
58997
+ return {
58998
+ ok: response.ok,
58999
+ status: response.status,
59000
+ body: objectFrom(await response.text()),
59001
+ ...Number.isFinite(retryAfterSec) && retryAfterSec > 0 ? { retryAfterSec } : {}
59002
+ };
59003
+ } catch {
59004
+ return { ok: false, status: 0, body: null, error: "push_send_unreachable" };
59005
+ }
59006
+ }
59007
+ function localRefusal(options) {
59008
+ if (!options.target.controlToken) return "control_token_required";
59009
+ if (!options.wixToken) return "wix_account_token_required";
59010
+ if (!options.siteToken) return "site_token_required";
59011
+ if (credentialHostRefusal(options.target.control)) return "insecure_target";
59012
+ if (options.previewTag !== void 0 && !PREVIEW_TAG2.test(options.previewTag)) return "invalid_preview_tag";
59013
+ return void 0;
59014
+ }
59015
+ function headersFor(options) {
59016
+ return {
59017
+ "x-control-token": options.target.controlToken,
59018
+ // RAW, never `Bearer ` — what normalizeWixAuthorization and token-info expect.
59019
+ Authorization: options.wixToken,
59020
+ [SITE_TOKEN_HEADER]: options.siteToken,
59021
+ accept: "application/json",
59022
+ "content-type": "application/json",
59023
+ ...options.previewTag ? { "x-wix-route-serve": options.previewTag } : {}
59024
+ };
59025
+ }
59026
+ function objectFrom(text8) {
59027
+ try {
59028
+ const value = text8 ? JSON.parse(text8) : null;
59029
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
59030
+ } catch {
59031
+ return null;
59032
+ }
59033
+ }
59034
+ var SITE_TOKEN_HEADER, PREVIEW_TAG2, TIMEOUT_MS;
59035
+ var init_push_send = __esm({
59036
+ "../serve-cli/src/push-send.ts"() {
59037
+ init_credential_hosts();
59038
+ SITE_TOKEN_HEADER = "x-himi-site-token";
59039
+ PREVIEW_TAG2 = /^dp-[a-z0-9]+$/;
59040
+ TIMEOUT_MS = 6e4;
59041
+ }
59042
+ });
59043
+
59044
+ // ../../core/serve-control/src/push-send-service.ts
59045
+ var PUSH_SEND_ERROR_CODES;
59046
+ var init_push_send_service = __esm({
59047
+ "../../core/serve-control/src/push-send-service.ts"() {
59048
+ PUSH_SEND_ERROR_CODES = [
59049
+ "unauthorized",
59050
+ "token_revoked",
59051
+ "revocation_check_unavailable",
59052
+ "method_not_allowed",
59053
+ "rate_limited",
59054
+ "forbidden_cross_tenant",
59055
+ "forbidden_site",
59056
+ "site_check_unavailable",
59057
+ "push_send_unconfigured",
59058
+ "push_send_unavailable",
59059
+ "invalid_input",
59060
+ "payload_too_large",
59061
+ "unknown_field",
59062
+ "invalid_app_id",
59063
+ "invalid_site_id",
59064
+ "invalid_member_email",
59065
+ "invalid_title",
59066
+ "invalid_body",
59067
+ "invalid_link",
59068
+ "invalid_request_id",
59069
+ "invalid_dry_run",
59070
+ "link_not_routable",
59071
+ "app_config_unavailable",
59072
+ "push_not_ready",
59073
+ "site_token_required",
59074
+ "site_token_invalid",
59075
+ "site_token_unverifiable",
59076
+ "member_not_found",
59077
+ "member_ambiguous",
59078
+ "member_not_active",
59079
+ "member_read_forbidden",
59080
+ "member_lookup_unavailable",
59081
+ "ping_unconfigured",
59082
+ "ping_permission_denied",
59083
+ "ping_rejected",
59084
+ "ping_rate_limited",
59085
+ "send_outcome_unknown"
59086
+ ];
59087
+ }
59088
+ });
59089
+
59090
+ // src/notify-ping.ts
59091
+ var notify_ping_exports = {};
59092
+ __export(notify_ping_exports, {
59093
+ runNotifyPing: () => runNotifyPing
59094
+ });
59095
+ import { randomUUID as randomUUID5 } from "node:crypto";
59096
+ import { resolve as resolve49 } from "node:path";
59097
+ function refuse4(io, error, hint, exit = 2, extra = {}) {
59098
+ io.error(JSON.stringify({ ok: false, error, ...hint ? { hint } : {}, ...extra }));
59099
+ return exit;
59100
+ }
59101
+ async function runNotifyPing(flags, io, deps = {}) {
59102
+ const flagError = flagRefusal(flags);
59103
+ if (flagError) return refuse4(io, flagError);
59104
+ const input = mergePushInputs(pushInputsFromContent(resolve49(text7(flags.content) ?? process.cwd())), flags);
59105
+ const missing = [...input.app ? [] : ["app"], ...input.site ? [] : ["site"], ...REQUIRED_FLAGS.filter((f) => !text7(flags[f]))];
59106
+ if (missing.length) return refuse4(io, "needs_input", "Name the app and site (or --content), the member's login email, a title and a link.", 2, { missing });
59107
+ const requestId2 = text7(flags["request-id"]) ?? (deps.newRequestId ?? randomUUID5)();
59108
+ if (!UUID_RE.test(requestId2)) return refuse4(io, "invalid_request_id", "Reuse the requestId a previous send printed.");
59109
+ const owner = await hostedOwnerSession(flags, deps);
59110
+ if (!owner.ok) return refuse4(io, owner.error, owner.hint, owner.exit);
59111
+ const { session } = owner;
59112
+ const ownership = await verifyAppOwnership({ ownerIssue: session.ownerIssue, controlToken: session.controlToken, declaredName: input.app, fetchImpl: deps.fetchImpl });
59113
+ if (ownership.state !== "owned") return refuse4(io, `app_ownership_${ownership.state}`, "Sending requires the app owner.", 1);
59114
+ let siteToken2;
59115
+ try {
59116
+ siteToken2 = await (deps.siteToken ?? siteToken)(input.site);
59117
+ } catch {
59118
+ return refuse4(io, "wix_site_token_required", "Run wix login as the site owner; the site token reads this site's members.", 1);
59119
+ }
59120
+ const body = {
59121
+ app: ownership.slug,
59122
+ site: input.site,
59123
+ memberEmail: text7(flags["member-email"]),
59124
+ title: text7(flags.title),
59125
+ ...text7(flags.body) ? { body: text7(flags.body) } : {},
59126
+ link: text7(flags.link),
59127
+ requestId: requestId2,
59128
+ ...flags["dry-run"] === true ? { dryRun: true } : {}
59129
+ };
59130
+ const http = await pushSendRequest({ target: session.target, wixToken: session.wixToken, siteToken: siteToken2, body, previewTag: session.previewTag, fetchImpl: deps.fetchImpl });
59131
+ return report2(http, body, flags, io);
59132
+ }
59133
+ function flagRefusal(flags) {
59134
+ if (LOCAL_SENDER_FLAGS.some((f) => flags[f] !== void 0)) return "flag_not_supported_with_ping";
59135
+ if (SWITCHES.some((f) => flags[f] !== void 0 && typeof flags[f] !== "boolean")) return "invalid_boolean_flag";
59136
+ return void 0;
59137
+ }
59138
+ function report2(http, sent, flags, io) {
59139
+ const code = refusalCode(http);
59140
+ if (code === "send_outcome_unknown") {
59141
+ return refuse4(io, code, `Ping may have accepted it. Re-run the same command with --request-id ${sent.requestId}: Ping runs one request at most once per site for 24 hours.`, 1, { requestId: sent.requestId });
59142
+ }
59143
+ if (code === "rate_limited" && http.retryAfterSec) {
59144
+ return refuse4(io, code, `Test sends are limited per owner; retry in ${http.retryAfterSec} seconds.`, 1, { retryAfterSec: http.retryAfterSec });
59145
+ }
59146
+ if (code) return refuse4(io, code, HINTS[code], 1);
59147
+ if (flags.json === true) io.log(JSON.stringify(http.body, null, 2));
59148
+ else io.log(summary(http.body ?? {}, sent));
59149
+ return 0;
59150
+ }
59151
+ function refusalCode(http) {
59152
+ if (http.error) return http.error === "push_send_unreachable" ? "send_outcome_unknown" : http.error;
59153
+ if (http.ok && (http.body?.state === "accepted" || http.body?.state === "dry_run")) return void 0;
59154
+ const code = String(http.body?.error ?? "");
59155
+ if (KNOWN_CODES.has(code)) return code;
59156
+ return http.ok || http.status >= 500 ? "send_outcome_unknown" : "push_send_failed";
59157
+ }
59158
+ function summary(result, sent) {
59159
+ if (result.state === "dry_run") {
59160
+ return `Dry run passed: ${sent.memberEmail} is an approved member, the link routes, and push is ready for ${sent.app}. No notification was sent.`;
59161
+ }
59162
+ if (result.deduplicated === true) {
59163
+ return `Ping already ran request ${sent.requestId}; the earlier send stands and no second notification was sent.`;
59164
+ }
59165
+ return `Ping accepted request ${sent.requestId} for ${sent.memberEmail}. Ping does not confirm delivery: it reaches the member's signed-in devices with notifications allowed.`;
59166
+ }
59167
+ var LOCAL_SENDER_FLAGS, SWITCHES, REQUIRED_FLAGS, UUID_RE, KNOWN_CODES, HINTS, text7;
59168
+ var init_notify_ping = __esm({
59169
+ "src/notify-ping.ts"() {
59170
+ init_push_send();
59171
+ init_push_send_service();
59172
+ init_hosted_owner();
59173
+ init_owner_claim();
59174
+ init_push_onboarding();
59175
+ init_wix_owner();
59176
+ LOCAL_SENDER_FLAGS = ["token", "device", "all", "admin-url", "admin-session", "silent", "badge", "data", "category", "channel", "platform", "bundle-id"];
59177
+ SWITCHES = ["json", "dry-run"];
59178
+ REQUIRED_FLAGS = ["member-email", "title", "link"];
59179
+ UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
59180
+ KNOWN_CODES = new Set(PUSH_SEND_ERROR_CODES);
59181
+ HINTS = {
59182
+ push_not_ready: "Run himi notify setup for this app and site first; status must be ready.",
59183
+ member_not_found: "Use the login email of an approved member of this site.",
59184
+ member_ambiguous: "More than one member has this login email; resolve it in the site's Members.",
59185
+ member_not_active: "The member must be approved before they can be notified.",
59186
+ link_not_routable: "Link to a screen this app's published release ships, e.g. <scheme>://screen/<screenId>?id=\u2026.",
59187
+ forbidden_site: "The Wix account from wix login must own this site.",
59188
+ site_token_invalid: "Run wix login as the site owner; the site token must belong to the app owner's account.",
59189
+ ping_permission_denied: "Himi Serve is not permitted to send through Ping; this is a platform issue, not your setup."
59190
+ };
59191
+ text7 = (v) => typeof v === "string" && v.length > 0 ? v : void 0;
59192
+ }
59193
+ });
59194
+
58967
59195
  // src/notify.ts
58968
59196
  var notify_exports = {};
58969
59197
  __export(notify_exports, {
@@ -59066,7 +59294,7 @@ async function runNotify(pos, flags, io, deps = {}) {
59066
59294
  } catch {
59067
59295
  reachable = false;
59068
59296
  }
59069
- const report2 = {
59297
+ const report3 = {
59070
59298
  // BOTH platforms must be ready. Considering only iOS meant a server with an APNs
59071
59299
  // key but no Firebase credentials reported ok and exited 0, while every Android
59072
59300
  // send would fail — from the command whose whole job is to answer that question.
@@ -59079,15 +59307,15 @@ async function runNotify(pos, flags, io, deps = {}) {
59079
59307
  ...reachable && authed && !senders ? { hint: "this admin-server predates /v1/admin/push-doctor \u2014 upgrade it to see sender readiness" } : {}
59080
59308
  };
59081
59309
  if (json6) {
59082
- print(report2);
59083
- return report2.ok ? 0 : 1;
59310
+ print(report3);
59311
+ return report3.ok ? 0 : 1;
59084
59312
  }
59085
59313
  io.log(
59086
59314
  `admin ${adminUrl} ${reachable ? authed ? "reachable, authenticated" : "reachable, NOT authenticated" : "UNREACHABLE"}`
59087
59315
  );
59088
59316
  if (!senders) {
59089
59317
  io.log("senders unknown \u2014 credentials live on the admin-server, and it did not report them");
59090
- if (report2.hint) io.log(` ${report2.hint}`);
59318
+ if (report3.hint) io.log(` ${report3.hint}`);
59091
59319
  return 1;
59092
59320
  }
59093
59321
  for (const [platform, r] of [
@@ -59097,7 +59325,7 @@ async function runNotify(pos, flags, io, deps = {}) {
59097
59325
  io.log(`${platform.padEnd(11)} ${r.sender}${r.note ? ` \u2014 ${r.note}` : ""}`);
59098
59326
  if (r.missing.length) io.log(` missing on the server: ${r.missing.join(", ")}`);
59099
59327
  }
59100
- return report2.ok ? 0 : 1;
59328
+ return report3.ok ? 0 : 1;
59101
59329
  }
59102
59330
  const app = str9(flags.app);
59103
59331
  if (!app) {
@@ -59276,10 +59504,10 @@ function makeTransport(fetchImpl, auth, timeoutMs = DEFAULT_TIMEOUT_MS4) {
59276
59504
  body: body === void 0 ? void 0 : JSON.stringify(body),
59277
59505
  signal: AbortSignal.timeout(timeoutMs)
59278
59506
  });
59279
- const text6 = await res.text();
59280
- let parsed = text6;
59507
+ const text8 = await res.text();
59508
+ let parsed = text8;
59281
59509
  try {
59282
- parsed = text6 ? JSON.parse(text6) : null;
59510
+ parsed = text8 ? JSON.parse(text8) : null;
59283
59511
  } catch {
59284
59512
  }
59285
59513
  if (!res.ok) throw new WixApiError2(res.status, method, path2, parsed);
@@ -59376,10 +59604,10 @@ async function mintVisitorToken(fetchImpl, clientId) {
59376
59604
  body: JSON.stringify({ clientId, grantType: "anonymous" }),
59377
59605
  signal: AbortSignal.timeout(8e3)
59378
59606
  });
59379
- const text6 = await res.text();
59380
- let parsed = text6;
59607
+ const text8 = await res.text();
59608
+ let parsed = text8;
59381
59609
  try {
59382
- parsed = text6 ? JSON.parse(text6) : null;
59610
+ parsed = text8 ? JSON.parse(text8) : null;
59383
59611
  } catch {
59384
59612
  }
59385
59613
  if (!res.ok) throw new WixApiError2(res.status, "POST", "/oauth2/token", parsed);
@@ -59394,28 +59622,28 @@ var init_visitor_auth = __esm({
59394
59622
  });
59395
59623
 
59396
59624
  // src/site-analyze/copy-clean.ts
59397
- function isTemplatePlaceholder(text6) {
59398
- return PLACEHOLDER_RE.test(text6);
59625
+ function isTemplatePlaceholder(text8) {
59626
+ return PLACEHOLDER_RE.test(text8);
59399
59627
  }
59400
59628
  function cleanText(raw, cap) {
59401
59629
  const s = String(raw ?? "").replace(/[\u0000-\u001F\u007F]/g, " ").replace(/\s+/g, " ").trim();
59402
59630
  return s.length > cap ? `${s.slice(0, cap - 1).trimEnd()}\u2026` : s;
59403
59631
  }
59404
- function stripPii(text6) {
59405
- return text6.replace(EMAIL_RE2, "").replace(PHONE_SHAPE_RE, (m) => {
59632
+ function stripPii(text8) {
59633
+ return text8.replace(EMAIL_RE2, "").replace(PHONE_SHAPE_RE, (m) => {
59406
59634
  const digits2 = (m.match(ANY_DIGIT_RE) ?? []).length;
59407
59635
  return digits2 >= PHONE_MIN_DIGITS && PHONE_DIGIT_RUN_RE.test(m) ? "" : m;
59408
59636
  }).replace(/\s+/g, " ").trim();
59409
59637
  }
59410
- function isBoilerplate(text6) {
59411
- return BOILERPLATE_RE.test(text6) || PLACEHOLDER_RE.test(text6);
59638
+ function isBoilerplate(text8) {
59639
+ return BOILERPLATE_RE.test(text8) || PLACEHOLDER_RE.test(text8);
59412
59640
  }
59413
59641
  function copyOrDrop(raw, cap) {
59414
- const text6 = stripPii(cleanText(raw, cap));
59415
- if (text6.length < 2) return "";
59416
- if (isBoilerplate(text6)) return "";
59417
- if (!/[A-Za-zͰ-῿぀-힯]/.test(text6)) return "";
59418
- return text6;
59642
+ const text8 = stripPii(cleanText(raw, cap));
59643
+ if (text8.length < 2) return "";
59644
+ if (isBoilerplate(text8)) return "";
59645
+ if (!/[A-Za-zͰ-῿぀-힯]/.test(text8)) return "";
59646
+ return text8;
59419
59647
  }
59420
59648
  function dedupe2(values, cap) {
59421
59649
  const out2 = [];
@@ -59449,9 +59677,9 @@ var init_copy_clean = __esm({
59449
59677
  function genericDescription(it) {
59450
59678
  for (const field of DESCRIPTION_FIELDS) {
59451
59679
  const raw = it[field];
59452
- const text6 = typeof raw === "string" ? raw : str6(raw?.text);
59453
- if (!text6) continue;
59454
- const plain2 = text6.replace(/<[^>]*>/g, " ").replace(/&nbsp;/g, " ");
59680
+ const text8 = typeof raw === "string" ? raw : str6(raw?.text);
59681
+ if (!text8) continue;
59682
+ const plain2 = text8.replace(/<[^>]*>/g, " ").replace(/&nbsp;/g, " ");
59455
59683
  if (plain2.trim()) return plain2;
59456
59684
  }
59457
59685
  return void 0;
@@ -59564,7 +59792,7 @@ function formLabels(x, depth = 0, out2 = []) {
59564
59792
  if (typeof x !== "object") return out2;
59565
59793
  const o = x;
59566
59794
  const label2 = str6(o.label ?? o.displayName ?? o.fieldTitle ?? o.title);
59567
- if (label2 && !UUID_RE.test(label2) && label2.length < 80 && !out2.includes(label2)) out2.push(label2);
59795
+ if (label2 && !UUID_RE2.test(label2) && label2.length < 80 && !out2.includes(label2)) out2.push(label2);
59568
59796
  for (const k of ["fields", "formFields", "form", "schema", "properties"]) {
59569
59797
  if (o[k] != null) formLabels(o[k], depth + 1, out2);
59570
59798
  }
@@ -59682,7 +59910,7 @@ function sampleTitle(data) {
59682
59910
  for (const [k, v] of Object.entries(data)) {
59683
59911
  if (k.startsWith("_") || typeof v !== "string") continue;
59684
59912
  const s = v.trim();
59685
- if (s.length > 2 && s.length < 80 && !s.includes("@") && !/^https?:/i.test(s) && !UUID_RE.test(s)) return s;
59913
+ if (s.length > 2 && s.length < 80 && !s.includes("@") && !/^https?:/i.test(s) && !UUID_RE2.test(s)) return s;
59686
59914
  }
59687
59915
  return void 0;
59688
59916
  }
@@ -59781,7 +60009,7 @@ async function readMemberRoles(call) {
59781
60009
  if (sawAuthError) return { names: [], status: "error" };
59782
60010
  return { names: [], status: "empty" };
59783
60011
  }
59784
- var asArr, str6, DESCRIPTION_FIELDS, UUID_RE, CORE_PROBES, OPTIONAL_PROBES, ALL, CMS_LIST_LIMIT;
60012
+ var asArr, str6, DESCRIPTION_FIELDS, UUID_RE2, CORE_PROBES, OPTIONAL_PROBES, ALL, CMS_LIST_LIMIT;
59785
60013
  var init_probes = __esm({
59786
60014
  "src/site-analyze/probes.ts"() {
59787
60015
  init_rest();
@@ -59789,7 +60017,7 @@ var init_probes = __esm({
59789
60017
  asArr = (x) => Array.isArray(x) ? x : [];
59790
60018
  str6 = (x) => typeof x === "string" ? x : "";
59791
60019
  DESCRIPTION_FIELDS = ["plainDescription", "description", "shortDescription", "excerpt", "tagLine", "subtitle"];
59792
- UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
60020
+ UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
59793
60021
  CORE_PROBES = [
59794
60022
  {
59795
60023
  vertical: "store",
@@ -60496,12 +60724,12 @@ function mergeWst(pages) {
60496
60724
  return acc;
60497
60725
  }
60498
60726
  function fontSlug(value) {
60499
- let text6 = value;
60727
+ let text8 = value;
60500
60728
  try {
60501
- text6 = decodeURIComponent(value);
60729
+ text8 = decodeURIComponent(value);
60502
60730
  } catch {
60503
60731
  }
60504
- return text6.toLowerCase().replace(/[^a-z0-9]+/g, "");
60732
+ return text8.toLowerCase().replace(/[^a-z0-9]+/g, "");
60505
60733
  }
60506
60734
  function fontUrlSlug(url) {
60507
60735
  const last = url.split("?")[0].split("#")[0].split("/").pop() ?? "";
@@ -60675,8 +60903,8 @@ function parsePublishedHtml(html) {
60675
60903
  const rawHeadings = [];
60676
60904
  HEADING_RE.lastIndex = 0;
60677
60905
  while (m = HEADING_RE.exec(html)) {
60678
- const text6 = copyOrDrop(textFromHtml(m[1] ?? ""), 120);
60679
- if (text6) rawHeadings.push(text6);
60906
+ const text8 = copyOrDrop(textFromHtml(m[1] ?? ""), 120);
60907
+ if (text8) rawHeadings.push(text8);
60680
60908
  if (rawHeadings.length >= 40) break;
60681
60909
  }
60682
60910
  const headings = dedupe2(rawHeadings, 20);
@@ -61503,16 +61731,16 @@ function isPrivateV4([a, b, c]) {
61503
61731
  return a >= 224;
61504
61732
  }
61505
61733
  function v6Groups(host) {
61506
- let text6 = host;
61507
- const dotted = /:((?:\d{1,3}\.){3}\d{1,3})$/.exec(text6);
61734
+ let text8 = host;
61735
+ const dotted = /:((?:\d{1,3}\.){3}\d{1,3})$/.exec(text8);
61508
61736
  if (dotted) {
61509
61737
  const octets = ipv4Octets(dotted[1]);
61510
61738
  if (!octets) return null;
61511
61739
  const hi = (octets[0] << 8 | octets[1]).toString(16);
61512
61740
  const lo = (octets[2] << 8 | octets[3]).toString(16);
61513
- text6 = `${text6.slice(0, dotted.index)}:${hi}:${lo}`;
61741
+ text8 = `${text8.slice(0, dotted.index)}:${hi}:${lo}`;
61514
61742
  }
61515
- const halves = text6.split("::");
61743
+ const halves = text8.split("::");
61516
61744
  if (halves.length > 2) return null;
61517
61745
  const parts = (part) => part ? part.split(":") : [];
61518
61746
  const head = parts(halves[0]);
@@ -61594,10 +61822,10 @@ function assertPublicSiteUrl(raw) {
61594
61822
  if (refusal) throw new Error(refusal);
61595
61823
  }
61596
61824
  function resolveAll(hostname2) {
61597
- return new Promise((resolve52, reject) => {
61825
+ return new Promise((resolve53, reject) => {
61598
61826
  dnsLookup(hostname2, { all: true, verbatim: true }, (err, addresses) => {
61599
61827
  if (err) reject(err);
61600
- else resolve52(addresses);
61828
+ else resolve53(addresses);
61601
61829
  });
61602
61830
  });
61603
61831
  }
@@ -61605,13 +61833,13 @@ function withAbort(start, signal, what) {
61605
61833
  if (signal?.aborted) return Promise.reject(new Error(`${what} aborted`));
61606
61834
  const work = start();
61607
61835
  if (!signal) return work;
61608
- return new Promise((resolve52, reject) => {
61836
+ return new Promise((resolve53, reject) => {
61609
61837
  const onAbort = () => reject(new Error(`${what} aborted`));
61610
61838
  signal.addEventListener("abort", onAbort, { once: true });
61611
- work.then(resolve52, reject).finally(() => signal.removeEventListener("abort", onAbort));
61839
+ work.then(resolve53, reject).finally(() => signal.removeEventListener("abort", onAbort));
61612
61840
  });
61613
61841
  }
61614
- async function pinAddress(url, resolve52 = resolveAll, signal) {
61842
+ async function pinAddress(url, resolve53 = resolveAll, signal) {
61615
61843
  const host = url.hostname.replace(/^\[|\]$/g, "");
61616
61844
  if (ipv4Octets(host)) {
61617
61845
  if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
@@ -61621,7 +61849,7 @@ async function pinAddress(url, resolve52 = resolveAll, signal) {
61621
61849
  if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
61622
61850
  return { address: host, family: 6 };
61623
61851
  }
61624
- const addresses = await withAbort(() => resolve52(host), signal, `${host} lookup`);
61852
+ const addresses = await withAbort(() => resolve53(host), signal, `${host} lookup`);
61625
61853
  if (!addresses.length) throw new Error(`${host} resolved to no address`);
61626
61854
  const blocked = addresses.filter((a) => isBlockedAddress(a.address)).map((a) => a.address);
61627
61855
  if (blocked.length) throw new Error(`${host} resolves to a blocked address (${blocked.join(", ")})`);
@@ -61661,7 +61889,7 @@ function copyIncomingHeaders(headers2) {
61661
61889
  return out2;
61662
61890
  }
61663
61891
  function requestOnce(url, pinned, init) {
61664
- return new Promise((resolve52, reject) => {
61892
+ return new Promise((resolve53, reject) => {
61665
61893
  const headers2 = { host: url.host, "accept-encoding": "identity" };
61666
61894
  new Headers(init.headers ?? {}).forEach((value, key2) => {
61667
61895
  if (key2.toLowerCase() !== "host") headers2[key2] = value;
@@ -61691,7 +61919,7 @@ function requestOnce(url, pinned, init) {
61691
61919
  reject(err);
61692
61920
  return;
61693
61921
  }
61694
- resolve52(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out2 }));
61922
+ resolve53(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out2 }));
61695
61923
  }
61696
61924
  );
61697
61925
  req.on("error", reject);
@@ -61767,8 +61995,8 @@ var init_net_guard = __esm({
61767
61995
  function textFields(look) {
61768
61996
  if (look.unavailable) return [];
61769
61997
  const out2 = [];
61770
- const add = (text6, where, narrative = false) => {
61771
- if (text6 && text6.trim()) out2.push({ text: text6, where, narrative });
61998
+ const add = (text8, where, narrative = false) => {
61999
+ if (text8 && text8.trim()) out2.push({ text: text8, where, narrative });
61772
62000
  };
61773
62001
  for (const label2 of look.navLabels) add(label2, "nav");
61774
62002
  for (const p of look.pages) {
@@ -62159,8 +62387,8 @@ async function analyzeSite(input, ports) {
62159
62387
  if (locale) plan.provisioning.locale = locale;
62160
62388
  const velo = buildVeloChapter({ look, owner: ownerVelo });
62161
62389
  const veloFiles = ownerVelo.files.flatMap((f) => {
62162
- const text6 = f.content ?? f.excerpt;
62163
- return text6 ? [{ path: f.path, text: text6 }] : [];
62390
+ const text8 = f.content ?? f.excerpt;
62391
+ return text8 ? [{ path: f.path, text: text8 }] : [];
62164
62392
  }).slice(0, 80);
62165
62393
  const permissions = buildPermissionsChapter({
62166
62394
  cms,
@@ -62382,8 +62610,8 @@ function cmsStatusNote(taxonomy) {
62382
62610
  function yn(v) {
62383
62611
  return v == null || v === "" ? "\u2014" : String(v);
62384
62612
  }
62385
- function isAuthPhrase(text6) {
62386
- const t = text6.trim();
62613
+ function isAuthPhrase(text8) {
62614
+ const t = text8.trim();
62387
62615
  return AUTH_ONLY_ASCII.test(t) || LOGIN_HE.includes(t);
62388
62616
  }
62389
62617
  function looksGated(page) {
@@ -62760,9 +62988,9 @@ function attachVeloSources(book, sources, put) {
62760
62988
  if (isSecretVeloPath(f.path)) continue;
62761
62989
  const rel = veloArtifactRelPath(f.path);
62762
62990
  if (!rel) continue;
62763
- const text6 = byPath.get(f.path) ?? f.excerpt;
62764
- if (!text6) continue;
62765
- put(rel, text6);
62991
+ const text8 = byPath.get(f.path) ?? f.excerpt;
62992
+ if (!text8) continue;
62993
+ put(rel, text8);
62766
62994
  f.localPath = rel;
62767
62995
  }
62768
62996
  }
@@ -63007,14 +63235,14 @@ var init_customer_build = __esm({
63007
63235
 
63008
63236
  // src/site-analyze/apply.ts
63009
63237
  import { existsSync as existsSync64, readFileSync as readFileSync76, writeFileSync as writeFileSync27, copyFileSync as copyFileSync3, mkdirSync as mkdirSync31, realpathSync as realpathSync9, statSync as statSync17 } from "node:fs";
63010
- import { dirname as dirname35, isAbsolute as isAbsolute6, join as join63, resolve as resolve49, sep as sep16 } from "node:path";
63238
+ import { dirname as dirname35, isAbsolute as isAbsolute6, join as join63, resolve as resolve50, sep as sep16 } from "node:path";
63011
63239
  import { spawnSync as spawnSync4 } from "node:child_process";
63012
63240
  function unpairedRedirectNote(overlay) {
63013
63241
  if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
63014
63242
  return `no OAuth redirect paired with client ${overlay.wix.clientId} \u2014 the app (and prepare:customer) will refuse to start until one is set. Register it with \`himi site client ensure --site ${overlay.siteId?.trim() || "<msid>"} --redirect-uri <uri> --yes\`, then re-run analyze with \`--redirect-uri <uri>\` (or export HIMI_BRANDED_LITE_WIX_REDIRECT_URI)`;
63015
63243
  }
63016
63244
  function posix3(p) {
63017
- return resolve49(p).replace(/\\/g, "/");
63245
+ return resolve50(p).replace(/\\/g, "/");
63018
63246
  }
63019
63247
  function committedShellProvisioning(path2) {
63020
63248
  return committedShellFor(posix3(path2));
@@ -63048,7 +63276,7 @@ function assertNotCommitted(path2, forbidden) {
63048
63276
  `refusing to overwrite committed ${committedProvisioningPath(committed)} \u2014 use prepare:customer --contract`
63049
63277
  );
63050
63278
  }
63051
- if (forbidden && resolve49(path2) === resolve49(forbidden)) {
63279
+ if (forbidden && resolve50(path2) === resolve50(forbidden)) {
63052
63280
  const named = committedShellProvisioning(forbidden);
63053
63281
  throw new Error(
63054
63282
  `refusing to overwrite committed ${named ? committedProvisioningPath(named) : forbidden} \u2014 pass a content-package provisioning.json or use prepare:customer --contract`
@@ -63104,8 +63332,8 @@ function buildMergedContract(options) {
63104
63332
  const staged = [];
63105
63333
  const contained = (root, rel) => {
63106
63334
  if (isAbsolute6(rel)) return void 0;
63107
- const full = resolve49(root, rel);
63108
- return full.startsWith(resolve49(root) + sep16) ? full : void 0;
63335
+ const full = resolve50(root, rel);
63336
+ return full.startsWith(resolve50(root) + sep16) ? full : void 0;
63109
63337
  };
63110
63338
  const stage = (fromRel, toRel) => {
63111
63339
  const from = contained(packageDir, fromRel);
@@ -63194,7 +63422,7 @@ function catalogTypography(overlay, template) {
63194
63422
  function staticFaqFor(overlay, overlayPath) {
63195
63423
  const own3 = overlay.faq;
63196
63424
  if (own3 !== void 0) return deriveStaticFaq(own3);
63197
- const bookPath = join63(dirname35(resolve49(overlayPath)), "book.json");
63425
+ const bookPath = join63(dirname35(resolve50(overlayPath)), "book.json");
63198
63426
  if (!existsSync64(bookPath)) return void 0;
63199
63427
  try {
63200
63428
  const book = JSON.parse(readFileSync76(bookPath, "utf8"));
@@ -63208,7 +63436,7 @@ function staticFaqFor(overlay, overlayPath) {
63208
63436
  }
63209
63437
  }
63210
63438
  async function applyOverlays(input) {
63211
- const cwd = resolve49(input.cwd);
63439
+ const cwd = resolve50(input.cwd);
63212
63440
  const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
63213
63441
  assertKnownShell(shell);
63214
63442
  const overlay = JSON.parse(readFileSync76(input.overlayPath, "utf8"));
@@ -63232,7 +63460,7 @@ async function applyOverlays(input) {
63232
63460
  `shell "${shell}" is a site shell: its contract names the customer's website (a \`site\` block), and this overlay has none. Re-run \`himi site analyze --url <site> --shell ${shell}\` to derive the site's page map (edit \`site.pages\` in provisioning.overlay.json if needed), then --apply.`
63233
63461
  );
63234
63462
  }
63235
- const packageDir = dirname35(resolve49(input.overlayPath));
63463
+ const packageDir = dirname35(resolve50(input.overlayPath));
63236
63464
  const { path: contract, staged } = buildMergedContract({ appDir: appDir3, packageDir, overlay });
63237
63465
  wrote.push(...staged);
63238
63466
  const r = spawnSync4("npm", ["run", "prepare:customer", "--", "--contract", contract], {
@@ -63327,7 +63555,7 @@ async function applyOverlays(input) {
63327
63555
  }
63328
63556
  }
63329
63557
  if (!input.iconPath || !existsSync64(input.iconPath)) {
63330
- const book = input.iconPath ? dirname35(dirname35(resolve49(input.iconPath))) : void 0;
63558
+ const book = input.iconPath ? dirname35(dirname35(resolve50(input.iconPath))) : void 0;
63331
63559
  notes.push(
63332
63560
  book ? `no icon installed \u2014 ${siteLogoAbsence(book).hint}` : "no icon installed and no business book to say why \u2014 `himi icon generate` draws one from the accent, or `himi icon set <file.png>` installs the customer's own mark"
63333
63561
  );
@@ -64446,10 +64674,10 @@ function permuteDomain(domain, allowSpecialUseDomain) {
64446
64674
  }
64447
64675
  function createPromiseCallback(cb) {
64448
64676
  let callback;
64449
- let resolve52;
64677
+ let resolve53;
64450
64678
  let reject;
64451
64679
  const promise = new Promise((_resolve, _reject) => {
64452
- resolve52 = _resolve;
64680
+ resolve53 = _resolve;
64453
64681
  reject = _reject;
64454
64682
  });
64455
64683
  if (typeof cb === "function") {
@@ -64465,7 +64693,7 @@ function createPromiseCallback(cb) {
64465
64693
  callback = (err, result) => {
64466
64694
  try {
64467
64695
  if (err) reject(err);
64468
- else resolve52(result);
64696
+ else resolve53(result);
64469
64697
  } catch (e) {
64470
64698
  reject(e instanceof Error ? e : new Error());
64471
64699
  }
@@ -66532,8 +66760,8 @@ function copyFromEval(evaled) {
66532
66760
  evaled.meta?.ogTitle,
66533
66761
  evaled.meta?.ogDescription
66534
66762
  ].map((raw) => {
66535
- const text6 = cleanText(raw, 400);
66536
- return text6 && isTemplatePlaceholder(text6) ? stripPii(cleanText(text6, 90)) : "";
66763
+ const text8 = cleanText(raw, 400);
66764
+ return text8 && isTemplatePlaceholder(text8) ? stripPii(cleanText(text8, 90)) : "";
66537
66765
  }),
66538
66766
  8
66539
66767
  );
@@ -67065,7 +67293,7 @@ var init_crawl_look = __esm({
67065
67293
  });
67066
67294
 
67067
67295
  // src/site-analyze/site-function.ts
67068
- import { randomUUID as randomUUID5 } from "node:crypto";
67296
+ import { randomUUID as randomUUID6 } from "node:crypto";
67069
67297
  function createRevisionUrl(msid, esi) {
67070
67298
  const q = new URLSearchParams({ editorSessionId: esi, esi, metaSiteId: msid });
67071
67299
  return `https://editor.wix.com/html/v1/create_revision?${q}`;
@@ -67432,13 +67660,13 @@ async function veloCall(fetchImpl, method, url, opts = {}) {
67432
67660
  body: opts.body === void 0 ? void 0 : JSON.stringify(opts.body),
67433
67661
  signal: AbortSignal.timeout(opts.timeoutMs ?? 3e4)
67434
67662
  });
67435
- const text6 = await res.text();
67436
- let json6 = text6;
67663
+ const text8 = await res.text();
67664
+ let json6 = text8;
67437
67665
  try {
67438
- json6 = text6 ? JSON.parse(text6) : null;
67666
+ json6 = text8 ? JSON.parse(text8) : null;
67439
67667
  } catch {
67440
67668
  }
67441
- return { status: res.status, json: json6, text: text6 };
67669
+ return { status: res.status, json: json6, text: text8 };
67442
67670
  }
67443
67671
  function snippet2(x, cap = 180) {
67444
67672
  const s = typeof x === "string" ? x : JSON.stringify(x) ?? "";
@@ -67510,7 +67738,7 @@ function codeAppIdFromRevision(json6) {
67510
67738
  async function snapshotAndPublish(fetchImpl, token, msid, opts = {}) {
67511
67739
  const production = opts.production !== false;
67512
67740
  const initiator = opts.initiator ?? "himi";
67513
- const esi = randomUUID5();
67741
+ const esi = randomUUID6();
67514
67742
  const rev = await veloCall(fetchImpl, "POST", createRevisionUrl(msid, esi), {
67515
67743
  token,
67516
67744
  msid,
@@ -67607,7 +67835,7 @@ async function runSiteFunction(opts) {
67607
67835
  if (!httpOk(patched)) {
67608
67836
  return { ...base, error: `UpdateFiles ${patched.status}: ${snippet2(patched.json ?? patched.text)}` };
67609
67837
  }
67610
- let report2 = {
67838
+ let report3 = {
67611
67839
  ...base,
67612
67840
  ok: true,
67613
67841
  source: extractHttpFunction(next, method, name),
@@ -67616,21 +67844,21 @@ async function runSiteFunction(opts) {
67616
67844
  if (opts.publish) {
67617
67845
  const snap = await snapshotAndPublish(fetchImpl, opts.token, opts.msid, { production: true, initiator: "himi" });
67618
67846
  const pubOk = httpOk(snap.rev) && httpOk(snap.live);
67619
- report2 = {
67620
- ...report2,
67621
- ok: report2.ok && pubOk,
67847
+ report3 = {
67848
+ ...report3,
67849
+ ok: report3.ok && pubOk,
67622
67850
  revision: snap.revision,
67623
67851
  codeAppId: snap.codeAppId,
67624
67852
  publish: { revision: httpOk(snap.rev), rc: httpOk(snap.rc), live: httpOk(snap.live), status: snap.live?.status },
67625
- error: pubOk ? report2.error : snippet2(snap.live?.json ?? snap.rev.json)
67853
+ error: pubOk ? report3.error : snippet2(snap.live?.json ?? snap.rev.json)
67626
67854
  };
67627
67855
  }
67628
67856
  if (opts.invoke) {
67629
- if (!opts.siteUrl) return { ...report2, ok: false, error: "put --invoke needs --url" };
67630
- const invoked = await invokeAndReport(fetchImpl, opts, report2, name, method);
67631
- return { ...report2, ...invoked, op: "put", ok: report2.ok && invoked.ok };
67857
+ if (!opts.siteUrl) return { ...report3, ok: false, error: "put --invoke needs --url" };
67858
+ const invoked = await invokeAndReport(fetchImpl, opts, report3, name, method);
67859
+ return { ...report3, ...invoked, op: "put", ok: report3.ok && invoked.ok };
67632
67860
  }
67633
- return report2;
67861
+ return report3;
67634
67862
  }
67635
67863
  async function invokeAndReport(fetchImpl, opts, base, name, method) {
67636
67864
  const siteUrl = opts.siteUrl;
@@ -67695,7 +67923,7 @@ __export(cli_exports, {
67695
67923
  runSiteFunctionCli: () => runSiteFunctionCli
67696
67924
  });
67697
67925
  import { readFileSync as readFileSync77 } from "node:fs";
67698
- import { resolve as resolve50 } from "node:path";
67926
+ import { resolve as resolve51 } from "node:path";
67699
67927
  function assetFetchFor(_opts) {
67700
67928
  return pinnedFetch2;
67701
67929
  }
@@ -67715,7 +67943,7 @@ async function runSiteAnalyze(opts) {
67715
67943
  const assetFetch = assetFetchFor(opts);
67716
67944
  const siteFetch = guardedSiteFetch;
67717
67945
  const cwd = opts.cwd ?? process.cwd();
67718
- const outDir = resolve50(cwd, opts.outDir ?? ".himi/business-book");
67946
+ const outDir = resolve51(cwd, opts.outDir ?? ".himi/business-book");
67719
67947
  let ownerAuth;
67720
67948
  let msid;
67721
67949
  const ownerSite = ownerSiteFor(opts);
@@ -67767,9 +67995,9 @@ async function runSiteAnalyze(opts) {
67767
67995
  if (opts.apply) {
67768
67996
  applied = await applyOverlays({
67769
67997
  cwd,
67770
- overlayPath: resolve50(outDir, "provisioning.overlay.json"),
67771
- tokensPath: resolve50(outDir, "tokens.overlay.json"),
67772
- iconPath: resolve50(outDir, "media/icon.png"),
67998
+ overlayPath: resolve51(outDir, "provisioning.overlay.json"),
67999
+ tokensPath: resolve51(outDir, "tokens.overlay.json"),
68000
+ iconPath: resolve51(outDir, "media/icon.png"),
67773
68001
  shell: opts.shell
67774
68002
  });
67775
68003
  const note = noteWithWarnings(applied.note, warnings);
@@ -67805,7 +68033,7 @@ async function runSiteFunctionCli(opts) {
67805
68033
  const token = opts.token ?? await siteToken(msid);
67806
68034
  let source;
67807
68035
  if (opts.sourcePath) {
67808
- const p = resolve50(opts.cwd ?? process.cwd(), opts.sourcePath);
68036
+ const p = resolve51(opts.cwd ?? process.cwd(), opts.sourcePath);
67809
68037
  source = readFileSync77(p, "utf8");
67810
68038
  }
67811
68039
  let body;
@@ -67861,7 +68089,7 @@ async function accountToken2(spawnImpl = spawn6) {
67861
68089
  cached2 = fromEnv;
67862
68090
  return fromEnv;
67863
68091
  }
67864
- const token = await new Promise((resolve52, reject) => {
68092
+ const token = await new Promise((resolve53, reject) => {
67865
68093
  let child;
67866
68094
  try {
67867
68095
  child = spawnImpl("wix", ["token"]);
@@ -67890,7 +68118,7 @@ async function accountToken2(spawnImpl = spawn6) {
67890
68118
  const scan = (d) => {
67891
68119
  out2 += String(d);
67892
68120
  const m = out2.match(TOKEN_RE2);
67893
- if (m) done(() => resolve52(m[0]));
68121
+ if (m) done(() => resolve53(m[0]));
67894
68122
  };
67895
68123
  child.stdout?.on("data", scan);
67896
68124
  child.stderr?.on("data", scan);
@@ -67933,10 +68161,10 @@ function accountTransport(fetchImpl = fetch, timeoutMs = DEFAULT_TIMEOUT_MS5, sp
67933
68161
  }
67934
68162
  throw new Error(`${method} ${path2} failed: ${err?.message ?? String(e)}`);
67935
68163
  }
67936
- const text6 = await res.text();
67937
- let parsed = text6;
68164
+ const text8 = await res.text();
68165
+ let parsed = text8;
67938
68166
  try {
67939
- parsed = text6 ? JSON.parse(text6) : null;
68167
+ parsed = text8 ? JSON.parse(text8) : null;
67940
68168
  } catch {
67941
68169
  }
67942
68170
  if (!res.ok) throw new WixApiError(res.status, method, path2, parsed);
@@ -67997,16 +68225,16 @@ async function installVerticals(msid, wanted, token, fetchImpl = fetch, timeoutM
67997
68225
  body: JSON.stringify({ apps: wanted.map((w) => ({ id: w.appDefId })) }),
67998
68226
  signal: AbortSignal.timeout(timeoutMs)
67999
68227
  });
68000
- const text6 = await res.text();
68228
+ const text8 = await res.text();
68001
68229
  if (!res.ok) {
68002
68230
  return {
68003
68231
  ...empty,
68004
- errors: wanted.map((w) => ({ ...w, message: `bulk-install -> ${res.status}: ${text6.slice(0, 200)}` }))
68232
+ errors: wanted.map((w) => ({ ...w, message: `bulk-install -> ${res.status}: ${text8.slice(0, 200)}` }))
68005
68233
  };
68006
68234
  }
68007
68235
  let body = {};
68008
68236
  try {
68009
- body = text6 ? JSON.parse(text6) : {};
68237
+ body = text8 ? JSON.parse(text8) : {};
68010
68238
  } catch {
68011
68239
  }
68012
68240
  const nameOf = (appDefId) => wanted.find((w) => w.appDefId === appDefId)?.vertical ?? appDefId;
@@ -68609,9 +68837,9 @@ function redactVeloSource(source, knownSecrets = []) {
68609
68837
  const visitLiterals = (node) => {
68610
68838
  if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node) || ts.isTemplateExpression(node)) {
68611
68839
  const start = node.getStart(clean2);
68612
- const text6 = source.slice(start, node.end);
68613
- const redacted = redactLiteral(text6, start);
68614
- if (redacted !== text6) {
68840
+ const text8 = source.slice(start, node.end);
68841
+ const redacted = redactLiteral(text8, start);
68842
+ if (redacted !== text8) {
68615
68843
  edits.push({ start, end: node.end, text: redacted });
68616
68844
  return;
68617
68845
  }
@@ -68892,9 +69120,9 @@ var init_context = __esm({
68892
69120
  import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync79, mkdirSync as mkdirSync32, writeFileSync as writeFileSync29, existsSync as existsSync66, rmSync as rmSync15, readdirSync as readdirSync30, statSync as statSync18, lstatSync as lstatSync13, accessSync, constants as constants2, renameSync as renameSync7, cpSync as cpSync3 } from "node:fs";
68893
69121
  import { execFile, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn7 } from "node:child_process";
68894
69122
  import { AsyncLocalStorage } from "node:async_hooks";
68895
- import { createHash as createHash31, randomUUID as randomUUID6 } from "node:crypto";
69123
+ import { createHash as createHash31, randomUUID as randomUUID7 } from "node:crypto";
68896
69124
  import { tmpdir as tmpdir5, homedir as homedir7, hostname } from "node:os";
68897
- import { join as join64, resolve as resolve51, relative as relative13, basename as basename17, dirname as dirname36 } from "node:path";
69125
+ import { join as join64, resolve as resolve52, relative as relative13, basename as basename17, dirname as dirname36 } from "node:path";
68898
69126
  import { fileURLToPath as fileURLToPath26 } from "node:url";
68899
69127
 
68900
69128
  // ../serve-cli/src/client.ts
@@ -68935,10 +69163,10 @@ var ServeCliClient = class {
68935
69163
  ...carriesCredential ? { redirect: "error" } : {},
68936
69164
  body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0
68937
69165
  });
68938
- const text6 = await res.text();
69166
+ const text8 = await res.text();
68939
69167
  let json6 = null;
68940
69168
  try {
68941
- json6 = text6 ? JSON.parse(text6) : null;
69169
+ json6 = text8 ? JSON.parse(text8) : null;
68942
69170
  } catch {
68943
69171
  json6 = null;
68944
69172
  }
@@ -68946,7 +69174,7 @@ var ServeCliClient = class {
68946
69174
  res.headers.forEach((v, k) => {
68947
69175
  h[k] = v;
68948
69176
  });
68949
- return { status: res.status, ok: res.ok, json: json6, text: text6, headers: h };
69177
+ return { status: res.status, ok: res.ok, json: json6, text: text8, headers: h };
68950
69178
  }
68951
69179
  // ---- serve (device-facing reads) ----
68952
69180
  health(plane) {
@@ -69511,8 +69739,8 @@ init_attestation();
69511
69739
 
69512
69740
  // ../../core/admin-web/src/utils/qr-terminal.ts
69513
69741
  init_qr();
69514
- function qrTerminal(text6, opts = {}) {
69515
- const { modules, size } = encodeQr(text6);
69742
+ function qrTerminal(text8, opts = {}) {
69743
+ const { modules, size } = encodeQr(text8);
69516
69744
  const quietZone = opts.quietZone ?? 4;
69517
69745
  const dim = size + quietZone * 2;
69518
69746
  const dark = (x, y) => x >= quietZone && x < quietZone + size && y >= quietZone && y < quietZone + size ? modules[y - quietZone][x - quietZone] : false;
@@ -69568,9 +69796,9 @@ function dpxSessionPresent(path2 = dpxSessionTokenPath()) {
69568
69796
  return false;
69569
69797
  }
69570
69798
  }
69571
- function isPortInUseError(text6) {
69572
- if (!text6) return false;
69573
- return /EADDRINUSE/i.test(text6) || new RegExp(`(:::|:)${DPX_SESSION_PORT}\\b`).test(text6);
69799
+ function isPortInUseError(text8) {
69800
+ if (!text8) return false;
69801
+ return /EADDRINUSE/i.test(text8) || new RegExp(`(:::|:)${DPX_SESSION_PORT}\\b`).test(text8);
69574
69802
  }
69575
69803
  function parseDpxAuthStatusIdentity(stdout) {
69576
69804
  if (!stdout) return void 0;
@@ -69635,7 +69863,7 @@ async function browserLogin(opts) {
69635
69863
  const log = opts.log ?? (() => {
69636
69864
  });
69637
69865
  const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
69638
- return await new Promise((resolve52, reject) => {
69866
+ return await new Promise((resolve53, reject) => {
69639
69867
  let settled = false;
69640
69868
  let loginUrl = "";
69641
69869
  const server = createServer();
@@ -69699,7 +69927,7 @@ async function browserLogin(opts) {
69699
69927
  return;
69700
69928
  }
69701
69929
  res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store", connection: "close" }).end(CLOSE_PAGE);
69702
- finish2(() => resolve52({ token, loginUrl }));
69930
+ finish2(() => resolve53({ token, loginUrl }));
69703
69931
  });
69704
69932
  });
69705
69933
  server.on("error", (err) => finish2(() => reject(err)));
@@ -69963,7 +70191,7 @@ async function queryCms(opts) {
69963
70191
  async function createCms(opts) {
69964
70192
  const { app, cms, call, dryRun = false, allowDestructive = false, applyPermissions = false } = opts;
69965
70193
  const prefix = namespacePrefix(app);
69966
- const report2 = {
70194
+ const report3 = {
69967
70195
  ok: true,
69968
70196
  app,
69969
70197
  namespace: prefix,
@@ -69985,19 +70213,19 @@ async function createCms(opts) {
69985
70213
  for (const spec of cms?.collections ?? []) {
69986
70214
  const id = physicalId(spec, app);
69987
70215
  if (spec.wixId) {
69988
- report2.skipped.push({
70216
+ report3.skipped.push({
69989
70217
  collection: id,
69990
70218
  reason: remoteById.has(id) ? "adopted (read-only) \u2014 himi never changes the schema of a collection it does not own" : `adopted but absent from this site \u2014 create it in the Wix dashboard, or declare it as owned ("${prefix}\u2026")`
69991
70219
  });
69992
- if (!remoteById.has(id)) report2.ok = false;
70220
+ if (!remoteById.has(id)) report3.ok = false;
69993
70221
  continue;
69994
70222
  }
69995
70223
  if (!spec.id?.startsWith(prefix)) {
69996
- report2.refused.push({
70224
+ report3.refused.push({
69997
70225
  collection: id || "<unnamed>",
69998
70226
  reason: `"${id}" is outside this app's namespace "${prefix}" \u2014 himi only writes collections it owns. Rename it in config.ts, or bind an existing collection read-only with \`wixId\`.`
69999
70227
  });
70000
- report2.ok = false;
70228
+ report3.ok = false;
70001
70229
  continue;
70002
70230
  }
70003
70231
  const existing = remoteById.get(id);
@@ -70005,35 +70233,35 @@ async function createCms(opts) {
70005
70233
  if (!dryRun) {
70006
70234
  await call("POST", "/data/v2/collections", { collection: toWixCollection(spec, app) });
70007
70235
  }
70008
- report2.created.push(id);
70236
+ report3.created.push(id);
70009
70237
  continue;
70010
70238
  }
70011
70239
  const permDrift = diffPermissions(spec, existing);
70012
- for (const d of permDrift) report2.permissionDrift.push({ collection: id, ...d });
70240
+ for (const d of permDrift) report3.permissionDrift.push({ collection: id, ...d });
70013
70241
  const applyingPermissions = applyPermissions && permDrift.length > 0;
70014
70242
  const drift = diffFields(spec, existing);
70015
70243
  const extras = drift.filter((d) => d.kind === "extra-field");
70016
70244
  const mismatches = drift.filter((d) => d.kind === "type-mismatch");
70017
70245
  const missing = drift.filter((d) => d.kind === "missing-field");
70018
70246
  for (const m of mismatches) {
70019
- report2.skipped.push({ collection: id, reason: m.detail });
70020
- report2.ok = false;
70247
+ report3.skipped.push({ collection: id, reason: m.detail });
70248
+ report3.ok = false;
70021
70249
  }
70022
70250
  for (const e of extras) {
70023
70251
  if (allowDestructive) continue;
70024
- report2.skipped.push({ collection: id, reason: e.detail });
70252
+ report3.skipped.push({ collection: id, reason: e.detail });
70025
70253
  }
70026
70254
  if (mismatches.length > 0) continue;
70027
70255
  if (missing.length === 0 && (extras.length === 0 || !allowDestructive) && !applyingPermissions) {
70028
- report2.unchanged.push(id);
70256
+ report3.unchanged.push(id);
70029
70257
  continue;
70030
70258
  }
70031
70259
  if (!allowDestructive && !Array.isArray(existing.fields)) {
70032
- report2.skipped.push({
70260
+ report3.skipped.push({
70033
70261
  collection: id,
70034
70262
  reason: "the site returned this collection without a `fields` array, so an update would drop every field (and its data) by omission. Re-run to retry the read; pass --allow-destructive only if narrowing to the declaration is genuinely what you want."
70035
70263
  });
70036
- report2.ok = false;
70264
+ report3.ok = false;
70037
70265
  continue;
70038
70266
  }
70039
70267
  if (applyingPermissions) {
@@ -70070,14 +70298,14 @@ async function createCms(opts) {
70070
70298
  }
70071
70299
  }
70072
70300
  }
70073
- report2.updated.push(id);
70301
+ report3.updated.push(id);
70074
70302
  }
70075
- return report2;
70303
+ return report3;
70076
70304
  }
70077
70305
  async function seedCms(opts) {
70078
70306
  const { app, cms, call, dryRun = false, force = false, only, dir } = opts;
70079
70307
  const prefix = namespacePrefix(app);
70080
- const report2 = { ok: true, app, inserted: {}, sources: {}, skipped: [], refused: [], dryRun };
70308
+ const report3 = { ok: true, app, inserted: {}, sources: {}, skipped: [], refused: [], dryRun };
70081
70309
  const fileRows = dir ? readSeedFile(dir) : {};
70082
70310
  const rowsFor = (id, spec) => fileRows[id]?.length ? { rows: fileRows[id], source: "cms-seed.json" } : { rows: spec.seed ?? [], source: "config.ts" };
70083
70311
  const remoteIds = /* @__PURE__ */ new Set();
@@ -70094,30 +70322,30 @@ async function seedCms(opts) {
70094
70322
  const { rows, source } = rowsFor(id, spec);
70095
70323
  considered++;
70096
70324
  if (!rows.length) {
70097
- report2.skipped.push({
70325
+ report3.skipped.push({
70098
70326
  collection: id,
70099
70327
  reason: `no seed rows \u2014 add a \`seed\` array to this collection in config.ts, or run \`himi cms seed --ai\` and refine ${dir ? "cms-seed.json" : "the generated cms-seed.json"}`
70100
70328
  });
70101
70329
  continue;
70102
70330
  }
70103
70331
  if (!spec.id?.startsWith(prefix)) {
70104
- report2.refused.push({ collection: id, reason: `"${id}" is outside this app's namespace "${prefix}" \u2014 himi only seeds collections it owns.` });
70105
- report2.ok = false;
70332
+ report3.refused.push({ collection: id, reason: `"${id}" is outside this app's namespace "${prefix}" \u2014 himi only seeds collections it owns.` });
70333
+ report3.ok = false;
70106
70334
  continue;
70107
70335
  }
70108
70336
  if (!remoteIds.has(id)) {
70109
- report2.skipped.push({ collection: id, reason: `not on the site yet \u2014 run \`himi cms create\` first` });
70110
- report2.ok = false;
70337
+ report3.skipped.push({ collection: id, reason: `not on the site yet \u2014 run \`himi cms create\` first` });
70338
+ report3.ok = false;
70111
70339
  continue;
70112
70340
  }
70113
70341
  const count2 = await countItems(call, id);
70114
70342
  if (count2 === null && !force) {
70115
- report2.skipped.push({ collection: id, reason: "could not read the current row count, so seeding might bury existing content. Re-run, or pass --force if you are sure." });
70116
- report2.ok = false;
70343
+ report3.skipped.push({ collection: id, reason: "could not read the current row count, so seeding might bury existing content. Re-run, or pass --force if you are sure." });
70344
+ report3.ok = false;
70117
70345
  continue;
70118
70346
  }
70119
70347
  if (count2 !== null && count2 > 0 && !force) {
70120
- report2.skipped.push({ collection: id, reason: `already has ${count2} items \u2014 seeding an already-populated collection needs --force so real content is never buried under sample rows` });
70348
+ report3.skipped.push({ collection: id, reason: `already has ${count2} items \u2014 seeding an already-populated collection needs --force so real content is never buried under sample rows` });
70121
70349
  continue;
70122
70350
  }
70123
70351
  if (!dryRun) {
@@ -70129,7 +70357,7 @@ async function seedCms(opts) {
70129
70357
  });
70130
70358
  const droppedKeys = [...new Set(rows.flatMap((r) => Object.keys(r).filter((k) => !declaredKeys.has(k))))];
70131
70359
  if (droppedKeys.length > 0) {
70132
- report2.skipped.push({
70360
+ report3.skipped.push({
70133
70361
  collection: id,
70134
70362
  reason: `ignored undeclared key(s) in seed rows: ${droppedKeys.join(", ")} \u2014 only declared fields are written (a row cannot set system keys such as _id or _owner)`
70135
70363
  });
@@ -70145,18 +70373,18 @@ async function seedCms(opts) {
70145
70373
  )
70146
70374
  );
70147
70375
  }
70148
- report2.inserted[id] = rows.length;
70149
- report2.sources[id] = source;
70376
+ report3.inserted[id] = rows.length;
70377
+ report3.sources[id] = source;
70150
70378
  }
70151
70379
  if (considered === 0) {
70152
70380
  const adopted = (cms?.collections ?? []).map((spec) => ({ spec, id: physicalId(spec, app) })).filter(({ spec, id }) => !!spec.wixId && (!only || id === only));
70153
- report2.skipped.push({
70381
+ report3.skipped.push({
70154
70382
  collection: only ?? "<none>",
70155
70383
  reason: adopted.length ? `the selected collection${adopted.length === 1 ? " is" : "s are"} adopted and read-only \u2014 himi never seeds ${adopted.map(({ id }) => `"${id}"`).join(", ")}. Add rows in Wix CMS, or declare an owned collection with an id beginning "${prefix}".` : only ? `--only "${only}" matched no owned collection declared by this app` : "this app declares no owned CMS collections to seed"
70156
70384
  });
70157
- report2.ok = false;
70385
+ report3.ok = false;
70158
70386
  }
70159
- return report2;
70387
+ return report3;
70160
70388
  }
70161
70389
  function readSeedFile(dir) {
70162
70390
  const file = join8(dir, "cms-seed.json");
@@ -70457,57 +70685,57 @@ function summarizeLint(app, bres, outcome, strict, extraIssues = []) {
70457
70685
  }
70458
70686
  };
70459
70687
  const record2 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
70460
- const text6 = (value) => typeof value === "string" && value ? value : void 0;
70688
+ const text8 = (value) => typeof value === "string" && value ? value : void 0;
70461
70689
  const message = (value) => {
70462
70690
  const item = record2(value);
70463
- if (text6(item.message)) return text6(item.message);
70464
- if (text6(item.error)) return text6(item.error);
70691
+ if (text8(item.message)) return text8(item.message);
70692
+ if (text8(item.error)) return text8(item.error);
70465
70693
  if (Array.isArray(item.errors)) {
70466
70694
  const diagnostics = item.errors.map((entry) => {
70467
70695
  const diagnostic = record2(entry);
70468
- return text6(diagnostic.text) ?? text6(diagnostic.message);
70696
+ return text8(diagnostic.text) ?? text8(diagnostic.message);
70469
70697
  }).filter((entry) => !!entry);
70470
70698
  if (diagnostics.length) return diagnostics.join("; ");
70471
70699
  }
70472
70700
  return typeof value === "string" ? value : JSON.stringify(value);
70473
70701
  };
70474
- const report2 = foldLegacyReport(legacy, {
70702
+ const report3 = foldLegacyReport(legacy, {
70475
70703
  source: "validate",
70476
70704
  evidence: { runId: `validate:${outcome.manifest.releaseId}`, ts: (/* @__PURE__ */ new Date()).toISOString() },
70477
70705
  findings: [
70478
70706
  ...issues,
70479
70707
  ...bres.compileErrors.map((value) => ({
70480
70708
  pass: "compile",
70481
- path: text6(record2(value).bundle),
70709
+ path: text8(record2(value).bundle),
70482
70710
  ruleCode: "compile-error",
70483
70711
  severity: "error",
70484
70712
  message: message(value)
70485
70713
  })),
70486
70714
  ...outcome.failedToBuild.map((value) => ({
70487
70715
  pass: "build",
70488
- screen: text6(record2(value).screenId),
70716
+ screen: text8(record2(value).screenId),
70489
70717
  ruleCode: "failed-to-build",
70490
70718
  severity: "error",
70491
70719
  message: message(value)
70492
70720
  })),
70493
70721
  ...outcome.missingBundles.map((value) => ({
70494
70722
  pass: "build",
70495
- screen: text6(record2(value).screen),
70496
- path: text6(record2(value).bundle),
70723
+ screen: text8(record2(value).screen),
70724
+ path: text8(record2(value).bundle),
70497
70725
  ruleCode: "missing-bundle",
70498
70726
  severity: "error",
70499
70727
  message: message(value)
70500
70728
  })),
70501
70729
  ...workerThrows.map((value) => ({
70502
70730
  pass: "worker",
70503
- path: text6(record2(value).bundle),
70731
+ path: text8(record2(value).bundle),
70504
70732
  ruleCode: "worker-threw",
70505
70733
  severity: "error",
70506
70734
  message: message(value.threw)
70507
70735
  }))
70508
70736
  ]
70509
70737
  });
70510
- return { report: report2, hasErrors };
70738
+ return { report: report3, hasErrors };
70511
70739
  }
70512
70740
 
70513
70741
  // src/cms-lint.ts
@@ -70631,8 +70859,8 @@ function surfaceIssues(dir, surfaceNav, strict) {
70631
70859
  if (requested.length) {
70632
70860
  const { rejected } = resolveSurfaceEnvelope(platforms, requested);
70633
70861
  for (const r of rejected) {
70634
- const report2 = surfaceById(r.id) ? warn : error;
70635
- report2(`navigation.surfaces: ${r.reason} \u2014 the server will drop this key (narrow-only rule, RFC 0051 \xA73.6)`);
70862
+ const report3 = surfaceById(r.id) ? warn : error;
70863
+ report3(`navigation.surfaces: ${r.reason} \u2014 the server will drop this key (narrow-only rule, RFC 0051 \xA73.6)`);
70636
70864
  }
70637
70865
  }
70638
70866
  return issues;
@@ -70779,18 +71007,18 @@ function walkSource(dir, root = dir) {
70779
71007
  const ext = entry.name.slice(entry.name.lastIndexOf("."));
70780
71008
  if (!SOURCE_EXTENSIONS.has(ext)) continue;
70781
71009
  const absolute = join25(dir, entry.name);
70782
- const text6 = readText2(absolute);
70783
- if (text6 !== null) found.push({ path: relative4(root, absolute), text: text6 });
71010
+ const text8 = readText2(absolute);
71011
+ if (text8 !== null) found.push({ path: relative4(root, absolute), text: text8 });
70784
71012
  }
70785
71013
  return found;
70786
71014
  }
70787
- function blankMatrixRows(text6) {
70788
- const acceptance = mobileUxSection(mobileUxDocumentBody(text6), "Implementation acceptance") ?? "";
71015
+ function blankMatrixRows(text8) {
71016
+ const acceptance = mobileUxSection(mobileUxDocumentBody(text8), "Implementation acceptance") ?? "";
70789
71017
  return /\|\s*(?:Ready|Empty|Add\s*\/\s*edit|Saved\s*\/\s*completed|Error\s*\/\s*recovery)\s*\|\s*\|\s*\|\s*\|\s*\|/i.test(acceptance);
70790
71018
  }
70791
71019
  function usesAppNetwork(source) {
70792
- const code = (text6) => text6.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/[^\n]*/g, "");
70793
- return source.some(({ text: text6 }) => /\bwixApi\b|(?:from|import)\s*["']@(?:himalaya|wix\/himalaya)\/wix-[^"']+["']/.test(code(text6)));
71020
+ const code = (text8) => text8.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/[^\n]*/g, "");
71021
+ return source.some(({ text: text8 }) => /\bwixApi\b|(?:from|import)\s*["']@(?:himalaya|wix\/himalaya)\/wix-[^"']+["']/.test(code(text8)));
70794
71022
  }
70795
71023
  function auditUx(content, strict = false) {
70796
71024
  const dir = resolve16(content);
@@ -71504,6 +71732,13 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
71504
71732
  Requires Himi owner login plus Wix CLI login for site authorization.
71505
71733
  himi notify status --content <dir> [--site <msid>] [--refresh] [--json]
71506
71734
  Reads server setup status. --refresh checks Branded/Ping live; it does not send push.
71735
+ himi notify send --provider ping --target wix --app <a> --site <msid> --member-email <email>
71736
+ --title <s> [--body <s>] --link <scheme>://screen/<id>[?\u2026] [--request-id <uuid>] [--dry-run] [--json]
71737
+ Hosted test notification to ONE site member's devices: Himi Serve sends it through Ping
71738
+ as Himalaya, so no Apple/Firebase keys or Fire Console. Needs himi login --browser and
71739
+ wix login as the site owner, and a ready notify setup. Acceptance is not delivery.
71740
+ --dry-run checks ownership, member, link and readiness without sending. After an unknown
71741
+ outcome, re-run the same command with the printed --request-id; Ping never runs it twice.
71507
71742
  himi notify send --app <a> (--token <t> | --device <id> | --all) --title <s> [--body <s>] [--link <url>]
71508
71743
  deliver a REAL push notification to registered devices \u2014
71509
71744
  APNs (.p8) for iOS, FCM v1 for Android. --all fans out to
@@ -71695,7 +71930,7 @@ var COMMANDS = [
71695
71930
  { name: "icon", summary: "the app's LAUNCHER icon \u2014 the home-screen / store mark, which is BINARY-floor and never over-the-air (distinct from `himi icons`, the in-screen glyph vocabulary). `status`/`check` report what this app would actually ship and validate it against both stores: exact 1024x1024, no tRNS chunk, non-interlaced, and \u2014 when the optional image toolchain is installed \u2014 no transparent regions (Apple permits an alpha channel but not transparent pixels: ITMS-90717), no pre-masked corners, no letterboxed wordmark; they also print the store-policy checklist no checker can decide. `set <file.png>` installs supplied art, `from-site` installs the logo `himi site analyze` downloaded, and `generate` makes a gradient tile + glyph \u2014 all three trim, flatten onto the app's accent, write the 1024 opaque master plus the 512 Play listing icon (Play wants 32-bit WITH alpha, so it is a separate file), and DECLARE it in himalaya.content.json, without which the release bakes no icon at all", required: "[status|check] | set <file.png> | from-site [--book <dir>] | generate [--glyph <g>] [--accent <hex>] | glyphs [--content <dir>] [--json]" },
71696
71931
  { name: "login", summary: "obtain a scoped serve-control token from Wix identity and store it in ~/.himalaya/serve-targets.json (so push/promote need no hand-pasted token). Three modes: --browser (your own Wix account, no VPN/BO), --wix (HEADLESS \u2014 the machine's own Wix CLI credential; the mode a CI pod or agent container can satisfy), --dpx (Wix employee, reads ~/.dpx/session/token). RFC 0026 WS3.", required: "[--browser|--wix|--dpx] [--target <t>] [--issue-url <url>]" },
71697
71932
  { name: "logout", summary: "remove the stored control token for a target", required: "[--target <t>]" },
71698
- { name: "notify", summary: "`setup` optionally configures Branded/Ping from local customer key files; `status --refresh` reads live backend readiness. Setup may be deferred while building. These use serve-control and require owner plus Wix account authentication. `send`, `tokens`, `doctor`: send a REAL push notification to registered devices (RFC 0036 WS5) \u2014 APNs .p8 over HTTP/2 for iOS, FCM v1 for Android. `send` targets one device (--token / --device <registry id>) or fans out to the whole app (--all), reporting a per-device result; a token the provider says is uninstalled (APNs 410 Unregistered / FCM UNREGISTERED) is auto-disabled, while a merely wrong one (BadDeviceToken \u2014 usually a sandbox/production mismatch) is recorded and left enabled. `tokens` lists the registry. `doctor` reports which credentials resolve and which sender each platform picks. Talks to the admin-server via --admin-url/HIMALAYA_ADMIN_URL, authenticated with --admin-session/HIMALAYA_ADMIN_SESSION. NOT `himi push`, which publishes a release.", required: "setup|status [--content <dir>] [--target <t>] [--refresh] [--yes] [--no-push-setup] | send|tokens|doctor [--app <a>] [--token <t> | --device <id> | --all] [--title <s>] [--body <s>] [--link <url>] [--platform ios|android] [--badge <n>] [--channel <id>] [--silent] [--dry-run] [--json]" },
71933
+ { name: "notify", summary: "`setup` optionally configures Branded/Ping from local customer key files; `status --refresh` reads live backend readiness. Setup may be deferred while building. These use serve-control and require owner plus Wix account authentication. `send`, `tokens`, `doctor`: send a REAL push notification to registered devices (RFC 0036 WS5) \u2014 APNs .p8 over HTTP/2 for iOS, FCM v1 for Android. `send` targets one device (--token / --device <registry id>) or fans out to the whole app (--all), reporting a per-device result; a token the provider says is uninstalled (APNs 410 Unregistered / FCM UNREGISTERED) is auto-disabled, while a merely wrong one (BadDeviceToken \u2014 usually a sandbox/production mismatch) is recorded and left enabled. `tokens` lists the registry. `doctor` reports which credentials resolve and which sender each platform picks. Talks to the admin-server via --admin-url/HIMALAYA_ADMIN_URL, authenticated with --admin-session/HIMALAYA_ADMIN_SESSION. `send --provider ping` is the hosted alternative: the serve plane sends one test notification to one site member through Ping as Himalaya, with owner login instead of provider keys, and reports acceptance, never delivery. NOT `himi push`, which publishes a release.", required: "setup|status [--content <dir>] [--target <t>] [--refresh] [--yes] [--no-push-setup] | send --provider ping [--content <dir>] [--app <a>] [--site <msid>] --member-email <email> --title <s> [--body <s>] --link <url> [--request-id <uuid>] [--dry-run] [--json] | send|tokens|doctor [--app <a>] [--token <t> | --device <id> | --all] [--title <s>] [--body <s>] [--link <url>] [--platform ios|android] [--badge <n>] [--channel <id>] [--silent] [--dry-run] [--json]" },
71699
71934
  { name: "site", summary: "PROVISION a Wix project, then analyze or extend it. `create` is the one door that makes a site instead of adopting one: POST /funnel/projects/v1/create (a WIX site, a HEADLESS backend, a BRANDED_APP, or a VIBE site), and for headless it also mints the OAuth app whose id IS the `WIX_CLIENT_ID` \u2014 with --redirect-uri already registered, because an unregistered redirect makes native signInDirect fail at redirect-session. `--verticals` REQUIRES `--template` and reports only what Wix confirmed: measured, installing onto a project created from the BLANK template returns 200 while the vertical's API answers 428 forever, because there is no site for it to attach to (the install asks for CREATE_SITE). A real template ships its verticals installed and populated, and installing further ones onto it then works. It MUTATES your Wix account and needs --yes; without it you get the payload and nothing is sent. `list` is the read-only site inventory (with each site's premium flag, which is what explains an installed-but-428 vertical). Auth is the account-scoped `wix token` (no --site), falling back to WIX_API_KEY + WIX_ACCOUNT_ID. `client` is the same OAuth step for a site that ALREADY exists \u2014 the one himi adopts rather than makes \u2014 so a clientId no longer means a manual trip to the dashboard: `client ensure` reconciles rather than mints, because a site can already carry a client with NO registered redirect and shipping that one fails signInDirect at runtime; it reuses a client that carries --redirect-uri, PATCHes one that matches --name but lacks it (unioning, so another app's redirect survives), and creates only when there is nothing to reuse (--new forces a fresh one). --name IS the idempotency key. `client` auth is SITE-scoped (`wix token --site <msid>`) because minting is owner-of-that-site, and --yes gates every mutation: a site that already has a usable client resolves WITHOUT it, but --write-provisioning needs --yes even then because it rewrites a manifest on disk (the dry run's planned.provisioning names the file). That query endpoint IGNORES paging (measured: query.paging, cursorPaging and a top-level paging all return the full set at offset 0), so when pagingMetadata reports more clients than came back, `ensure` REFUSES EVERY outcome \u2014 create, patch AND reuse. Reuse is refused too because pickClient breaks ties on the OLDEST createdDate, so an omitted older same-named MOBILE client with the same redirect would win a later complete read and the resolved clientId would MOVE between runs \u2014 and it gets written into provisioning.json; convergence is what makes a stray duplicate untidy rather than harmful. --name cannot narrow the query (no filter is sent; the name is applied to the rows after they arrive), so the recovery is the dashboard; --new skips the query entirely. A `patched` result is verified against what Wix STORED \u2014 the redirect list is read off the PATCH response, and re-read via GET when the response omits it, because falling back to the list himi just sent would make the guard pass vacuously on exactly the silent no-op it exists to catch. `client list` is the read-only inventory of a site's clients: act on its `shippable` column rather than `hasRedirect`, because shippable ALSO requires a MOBILE applicationType and `ensure` refuses a WEB client \u2014 a WEB one carrying your redirect looks right and is not a candidate \u2014 and it sets truncated:true rather than presenting a partial inventory as the whole one. `analyze --read-only` returns API-only generation context as JSON (identity, access probes, CMS permissions and selected redacted Velo source); it needs no URL/browser and never uploads or applies anything. `analyze` reads a site into a business-book folder (REST + Playwright, GET-only); `--url` alone is the visitor-only pass over the published pages, and `--client-id` adds the vertical probes and the app binding `--apply` requires; `site function` list/get/put/publish/invokes that site's Velo HTTP functions and is not `himi functions` (serve-plane jobs). `--apply` bakes into a brandable shell; `--shell` takes the same names `himi dist --shell` does and defaults to branded-lite, and a shell that ships no prepare:customer is refused by name rather than half-built. `--shell brandy` (the site shell, RFC 0062) also derives the site's page map from its published pages and header menu \u2014 Home first, up to four tabs for the pages a visitor returns to, the rest in the drawer \u2014 into the overlay's `site` block, so it can be edited before `--apply`; only a site shell ever receives that block. It never overwrites any shell's committed apps/<shell>/provisioning.json.", required: "create <name> [--type wix|headless|branded-app|vibe] [--template <guid>] [--verticals stores,bookings,\u2026] [--folder <guid>] [--redirect-uri <uri>] [--no-oauth-app] [--write-provisioning [path]] [--site-url <url>] [--json] --yes | list | client ensure|list --site <msid> [--name <name>] [--redirect-uri <uri>] [--new] [--write-provisioning [path]] [--site-url <url>] [--json] --yes | analyze --read-only [--site <msid>] [--client-id <id>] [--json] | analyze --url <https> [--client-id <id>] [--site <msid>] [--out <dir>] [--redirect-uri <uri>] [--apply] [--shell " + SHELL_ENUM + "] | function list|get|put|publish|invoke [--site <msid>] [--url <https>] [--method GET|POST|PUT|DELETE] [--source <file>] [--body <json>] [--publish] [--invoke]" },
71700
71935
  { name: "doctor", summary: 'off-VPN preflight in one shot: probe the PUBLIC data plane (www.wixapis.com \u2014 reachable off-VPN), the INTERNAL serve/control plane for the selected target (VPN-gated), and report auth state (dpx session on disk + stored control token). --dpx additionally runs a live, EADDRINUSE-safe `dpx whoami`. Machine-readable with --json (an unreachable internal plane carries a stable code:"needs_vpn" so an agent branches on the code, not the prose); human-readable otherwise. Never loads the authoring runtime \u2014 works off-repo.', required: "[--target <t>] [--dpx] [--json] [--data-url <url>] [--timeout <ms>]" },
71701
71936
  { name: "upgrade", summary: "install the newest published CLI (`npm i -g @wix/himalaya-cli@latest`) and report what moved. This is the explicit door: himi also updates itself when the running build is more than a week old \u2014 unattended it just does it and re-runs your command, at a terminal it asks first \u2014 and `HIMI_NO_UPDATE_CHECK=1` turns that off, leaving this command as the way to catch up. Reports `unchanged` rather than claiming success when npm exits 0 without moving the version, which is what a registry mirror serving its own pinned copy looks like.", required: "[--json]" },
@@ -71788,16 +72023,16 @@ function createScopedRegistryResolver(exec = execNpmConfig) {
71788
72023
  }
71789
72024
  var SCOPED_REGISTRY_TIMEOUT_MS = 5e3;
71790
72025
  function execNpmConfig(file, args, options) {
71791
- return new Promise((resolve52, reject) => {
71792
- execFile(file, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) : resolve52(String(stdout)));
72026
+ return new Promise((resolve53, reject) => {
72027
+ execFile(file, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) : resolve53(String(stdout)));
71793
72028
  });
71794
72029
  }
71795
72030
  var npmScopedWixRegistry = createScopedRegistryResolver();
71796
72031
  async function scopedRegistryBefore(lookup2, deadline) {
71797
72032
  let cancel = () => {
71798
72033
  };
71799
- const expired = new Promise((resolve52) => {
71800
- const timer = setTimeout(() => resolve52(void 0), Math.max(0, deadline - Date.now()));
72034
+ const expired = new Promise((resolve53) => {
72035
+ const timer = setTimeout(() => resolve53(void 0), Math.max(0, deadline - Date.now()));
71801
72036
  cancel = () => clearTimeout(timer);
71802
72037
  });
71803
72038
  try {
@@ -71862,7 +72097,7 @@ function packageVersion(path2) {
71862
72097
  }
71863
72098
  }
71864
72099
  function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
71865
- let dir = resolve51(fromDir);
72100
+ let dir = resolve52(fromDir);
71866
72101
  for (; ; ) {
71867
72102
  const version2 = packageVersion(join64(dir, "node_modules", "@wix", "himalaya", "package.json"));
71868
72103
  if (version2) return { version: version2, source: "local" };
@@ -72027,7 +72262,7 @@ function thisHost() {
72027
72262
  return hostname().replace(/\s+/g, "_");
72028
72263
  }
72029
72264
  function lockStamp(now) {
72030
- return `${now} ${process.pid} ${thisHost()} ${randomUUID6()}`;
72265
+ return `${now} ${process.pid} ${thisHost()} ${randomUUID7()}`;
72031
72266
  }
72032
72267
  function processAlive(pid) {
72033
72268
  try {
@@ -72181,21 +72416,21 @@ function loaderArgs(execArgv) {
72181
72416
  }
72182
72417
  var spawnUpdateRefresh = createUpdateRefreshSpawner();
72183
72418
  function createTrimValidator(deps = {}, spawnFn = spawn7) {
72184
- const outcome = (code, report2, said) => {
72419
+ const outcome = (code, report3, said) => {
72185
72420
  let counts;
72186
72421
  let errors;
72187
72422
  try {
72188
- const parsed = JSON.parse(report2);
72423
+ const parsed = JSON.parse(report3);
72189
72424
  counts = parsed.counts;
72190
72425
  if (Array.isArray(parsed.findings)) {
72191
- const text6 = (v) => typeof v === "string" && v ? v : void 0;
72426
+ const text8 = (v) => typeof v === "string" && v ? v : void 0;
72192
72427
  errors = parsed.findings.filter((f) => f && f.severity === "error" && typeof f.id === "string").map((f) => ({
72193
72428
  id: f.id,
72194
- message: text6(f.message) ?? "",
72195
- ...text6(f.pass) ? { pass: text6(f.pass) } : {},
72196
- ...text6(f.screen) ? { screen: text6(f.screen) } : {},
72197
- ...text6(f.path) ? { path: text6(f.path) } : {},
72198
- ...text6(f.ruleCode) ? { ruleCode: text6(f.ruleCode) } : {}
72429
+ message: text8(f.message) ?? "",
72430
+ ...text8(f.pass) ? { pass: text8(f.pass) } : {},
72431
+ ...text8(f.screen) ? { screen: text8(f.screen) } : {},
72432
+ ...text8(f.path) ? { path: text8(f.path) } : {},
72433
+ ...text8(f.ruleCode) ? { ruleCode: text8(f.ruleCode) } : {}
72199
72434
  }));
72200
72435
  }
72201
72436
  } catch {
@@ -72203,7 +72438,7 @@ function createTrimValidator(deps = {}, spawnFn = spawn7) {
72203
72438
  return { code, counts, ...errors ? { errors } : {}, ...code !== 0 ? { tail: said.slice(-4e3) } : {} };
72204
72439
  };
72205
72440
  return async (dir, opts = {}) => {
72206
- const argv = ["validate", "--content", resolve51(dir), "--strict", "--skip-version-check"];
72441
+ const argv = ["validate", "--content", resolve52(dir), "--strict", "--skip-version-check"];
72207
72442
  if (!opts.fresh) {
72208
72443
  const out2 = [];
72209
72444
  const err = [];
@@ -72819,7 +73054,7 @@ function keptPlan(kept) {
72819
73054
  return note ? { kept, note } : {};
72820
73055
  }
72821
73056
  async function initFromRemoteTemplate(name, parentDir, template, c) {
72822
- const dir = resolve51(parentDir, name);
73057
+ const dir = resolve52(parentDir, name);
72823
73058
  if (existsSync66(join64(dir, "himalaya.content.json"))) {
72824
73059
  throw new Error(`content package already exists at ${dir}`);
72825
73060
  }
@@ -72832,17 +73067,17 @@ async function initFromRemoteTemplate(name, parentDir, template, c) {
72832
73067
  return finishScaffold(materializeSource(archive.files, name, dir), template);
72833
73068
  }
72834
73069
  function contentDir(flags) {
72835
- return resolve51(str8(flags.content) ?? process.cwd());
73070
+ return resolve52(str8(flags.content) ?? process.cwd());
72836
73071
  }
72837
73072
  function renameRestoredSource(restored, declaredApp, renamed) {
72838
- const text6 = {};
73073
+ const text8 = {};
72839
73074
  for (const entry of restored) {
72840
73075
  const decoded = entry.bytes.toString("utf8");
72841
- if (Buffer.from(decoded, "utf8").equals(entry.bytes)) text6[entry.path] = decoded;
73076
+ if (Buffer.from(decoded, "utf8").equals(entry.bytes)) text8[entry.path] = decoded;
72842
73077
  }
72843
- const sentineled = sentinelizeArchive(text6, declaredApp);
73078
+ const sentineled = sentinelizeArchive(text8, declaredApp);
72844
73079
  for (const entry of restored) {
72845
- if (!(entry.path in text6)) continue;
73080
+ if (!(entry.path in text8)) continue;
72846
73081
  const body = sentineled[entry.path];
72847
73082
  if (body !== void 0) entry.bytes = Buffer.from(substituteIdentity(body, renamed), "utf8");
72848
73083
  }
@@ -72876,7 +73111,7 @@ function restoreDestinationIssue(dest, force) {
72876
73111
  return null;
72877
73112
  }
72878
73113
  function isHimalayaMonorepoCheckout(start) {
72879
- let dir = resolve51(start);
73114
+ let dir = resolve52(start);
72880
73115
  for (; ; ) {
72881
73116
  if (existsSync66(join64(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync66(join64(dir, "core", "serve", "src", "server.ts"))) return true;
72882
73117
  const parent = dirname36(dir);
@@ -72938,7 +73173,7 @@ function materializeForPreview(appDir3, slug, displayName) {
72938
73173
  const forBuild = Object.fromEntries(
72939
73174
  Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
72940
73175
  );
72941
- const repoRoot2 = resolve51(fileURLToPath26(new URL("../../..", import.meta.url)));
73176
+ const repoRoot2 = resolve52(fileURLToPath26(new URL("../../..", import.meta.url)));
72942
73177
  const root = join64(repoRoot2, "node_modules", ".cache", "himi-template-preview");
72943
73178
  const stillRunning = (pid) => {
72944
73179
  try {
@@ -73184,7 +73419,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
73184
73419
  return 0;
73185
73420
  }
73186
73421
  case "agent-init": {
73187
- const dir = resolve51(str8(flags.dir) ?? process.cwd());
73422
+ const dir = resolve52(str8(flags.dir) ?? process.cwd());
73188
73423
  const { seedAgentFiles: seedAgentFiles2, NotAContentPackage: NotAContentPackage2 } = await Promise.resolve().then(() => (init_agent_context(), agent_context_exports));
73189
73424
  let res;
73190
73425
  try {
@@ -73741,7 +73976,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
73741
73976
  return 2;
73742
73977
  }
73743
73978
  const template = str8(flags.template);
73744
- const parentDir = resolve51(str8(flags.dir) ?? process.cwd());
73979
+ const parentDir = resolve52(str8(flags.dir) ?? process.cwd());
73745
73980
  const withAgentFiles = async (dir) => {
73746
73981
  const seeded = await seedAgentFilesFor(dir, flags);
73747
73982
  if (!seeded.agent || "error" in seeded.agent) return seeded;
@@ -73902,8 +74137,8 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
73902
74137
  return 2;
73903
74138
  }
73904
74139
  }
73905
- const appDir3 = resolve51(str8(flags.dir) ?? process.cwd());
73906
- const sourceDir = resolve51(str8(flags["source-dir"]) ?? appDir3);
74140
+ const appDir3 = resolve52(str8(flags.dir) ?? process.cwd());
74141
+ const sourceDir = resolve52(str8(flags["source-dir"]) ?? appDir3);
73907
74142
  let meta;
73908
74143
  try {
73909
74144
  meta = JSON.parse(readFileSync79(join64(sourceDir, TEMPLATE_META_FILE), "utf8"));
@@ -73945,7 +74180,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
73945
74180
  ...hasWorkers ? { tier5Dir: bundleOutDir2(buildDir) } : {},
73946
74181
  collect: { lint: true, strict }
73947
74182
  });
73948
- const scaffoldSourceFindings = resolve51(sourceDir) === resolve51(appDir3) ? [] : [
74183
+ const scaffoldSourceFindings = resolve52(sourceDir) === resolve52(appDir3) ? [] : [
73949
74184
  ...tokenColorIssues(sourceDir),
73950
74185
  ...surfaceIssues(sourceDir, void 0, strict),
73951
74186
  ...await fontIssues(sourceDir, strict),
@@ -73957,7 +74192,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
73957
74192
  message: `scaffold source (--source-dir ${sourceDir}): ${issue2.message}`
73958
74193
  }));
73959
74194
  const { navIssues: navIssues2 } = await Promise.resolve().then(() => (init_nav_lint(), nav_lint_exports));
73960
- const { report: report2, hasErrors } = summarizeLint(app, bres, outcome, strict, [
74195
+ const { report: report3, hasErrors } = summarizeLint(app, bres, outcome, strict, [
73961
74196
  ...await cmsIssues(buildDir, app, strict, { local: true }),
73962
74197
  ...surfaceIssues(buildDir, outcome.surfaceNav, strict),
73963
74198
  ...tokenColorIssues(buildDir),
@@ -73967,7 +74202,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
73967
74202
  ...scaffoldSourceFindings
73968
74203
  ]);
73969
74204
  if (hasErrors && !force) {
73970
- print({ ...report2, published: false, hint: "lint found errors \u2014 fix them, or re-run with --force to publish anyway" });
74205
+ print({ ...report3, published: false, hint: "lint found errors \u2014 fix them, or re-run with --force to publish anyway" });
73971
74206
  return 1;
73972
74207
  }
73973
74208
  const payload = await loadReleaseFromDir(app, out2);
@@ -73988,7 +74223,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
73988
74223
  }));
73989
74224
  return 1;
73990
74225
  }
73991
- const iconPath = str8(flags.icon) ? resolve51(str8(flags.icon)) : templateIconPath(name);
74226
+ const iconPath = str8(flags.icon) ? resolve52(str8(flags.icon)) : templateIconPath(name);
73992
74227
  let iconHash;
73993
74228
  if (iconPath) {
73994
74229
  try {
@@ -74242,7 +74477,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74242
74477
  ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
74243
74478
  collect: { lint: true, strict }
74244
74479
  });
74245
- const { report: report2, hasErrors } = summarizeLint(app, bres, outcome, strict, [
74480
+ const { report: report3, hasErrors } = summarizeLint(app, bres, outcome, strict, [
74246
74481
  ...await cmsIssues(dir, app, strict, { local: true }),
74247
74482
  ...surfaceIssues(dir, outcome.surfaceNav, strict),
74248
74483
  ...tokenColorIssues(dir),
@@ -74259,10 +74494,10 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74259
74494
  if (authWarning) advisories.push(authWarning);
74260
74495
  advisories.push(...await nativeConfigAdvisories(app, configSource));
74261
74496
  const finalReport = advisories.length ? {
74262
- ...report2,
74263
- warnings: [...report2.warnings ?? [], ...advisories],
74264
- counts: { ...report2.counts, warnings: report2.counts.warnings + advisories.length }
74265
- } : report2;
74497
+ ...report3,
74498
+ warnings: [...report3.warnings ?? [], ...advisories],
74499
+ counts: { ...report3.counts, warnings: report3.counts.warnings + advisories.length }
74500
+ } : report3;
74266
74501
  await leaveForBoard(dir, "validate", {
74267
74502
  ok: !hasErrors,
74268
74503
  errors: finalReport.counts.errors,
@@ -74375,23 +74610,23 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74375
74610
  const app = str8(flags.app) ?? loaded.app;
74376
74611
  const invoked2 = await invokeRemoteFunction2({ baseUrl: target.baseUrl, app, definition, body: input, params, releaseId: remoteRelease, previewToken: str8(flags["preview-token"]), boCookie: boCookie() });
74377
74612
  const response = invoked2.response;
74378
- const text7 = await response.text();
74613
+ const text9 = await response.text();
74379
74614
  let body2;
74380
74615
  try {
74381
- body2 = JSON.parse(text7);
74616
+ body2 = JSON.parse(text9);
74382
74617
  } catch {
74383
- body2 = text7;
74618
+ body2 = text9;
74384
74619
  }
74385
74620
  print({ ok: response.ok, app, releaseId: remoteRelease ?? null, url: invoked2.url, status: response.status, body: body2 });
74386
74621
  return response.ok ? 0 : 1;
74387
74622
  }
74388
74623
  const invoked = await invokeLocalFunction2(loaded, name, input, params);
74389
- const text6 = await invoked.response.text();
74624
+ const text8 = await invoked.response.text();
74390
74625
  let body;
74391
74626
  try {
74392
- body = JSON.parse(text6);
74627
+ body = JSON.parse(text8);
74393
74628
  } catch {
74394
- body = text6;
74629
+ body = text8;
74395
74630
  }
74396
74631
  print({ ok: invoked.response.ok, app: loaded.app, releaseId: invoked.releaseId, status: invoked.response.status, body });
74397
74632
  return invoked.response.ok ? 0 : 1;
@@ -74410,7 +74645,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74410
74645
  return 1;
74411
74646
  }
74412
74647
  const { himiPluginFiles: himiPluginFiles2 } = await Promise.resolve().then(() => (init_claude_plugin(), claude_plugin_exports));
74413
- const dir = resolve51(out2);
74648
+ const dir = resolve52(out2);
74414
74649
  const files = himiPluginFiles2(skills.skillMd);
74415
74650
  for (const f of files) {
74416
74651
  mkdirSync32(dirname36(join64(dir, f.path)), { recursive: true });
@@ -74432,7 +74667,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74432
74667
  }
74433
74668
  if (pos[1] === "reel") {
74434
74669
  const { buildReel: buildReel2 } = await Promise.resolve().then(() => (init_studio_reel(), studio_reel_exports));
74435
- const out2 = resolve51(str8(flags.out) ?? join64(dir, ".himi", "making-of.html"));
74670
+ const out2 = resolve52(str8(flags.out) ?? join64(dir, ".himi", "making-of.html"));
74436
74671
  const { html, plan } = buildReel2(dir);
74437
74672
  mkdirSync32(dirname36(out2), { recursive: true });
74438
74673
  writeFileSync29(out2, html);
@@ -74444,7 +74679,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74444
74679
  openUrl2(url2);
74445
74680
  }
74446
74681
  const handover = { file: out2, hint: `hand ${basename17(out2)} to the owner at the handover \u2014 one self-contained page of their app taking shape; send it beside the preview link, never instead of it` };
74447
- const report2 = {
74682
+ const report3 = {
74448
74683
  ok: true,
74449
74684
  file: out2,
74450
74685
  url: url2,
@@ -74457,7 +74692,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74457
74692
  ...plan.dropped ? { dropped: plan.dropped, note: "pictures were left out to keep the file attachable" } : {},
74458
74693
  ...plan.frames.length === 0 ? { hint: "no screen versions were recorded \u2014 run `himi studio` before building so the board keeps them" } : {}
74459
74694
  };
74460
- if (flags.json === true || io.isTTY !== true) print(report2);
74695
+ if (flags.json === true || io.isTTY !== true) print(report3);
74461
74696
  else io.log(`The making-of: ${out2}
74462
74697
  ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
74463
74698
  return 0;
@@ -74543,10 +74778,10 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
74543
74778
  }
74544
74779
  if (flags.brief === true) {
74545
74780
  const { agentContextNote: agentContextNote2 } = await Promise.resolve().then(() => (init_agent_context(), agent_context_exports));
74546
- const summary = summarizeProgress2(readProgress2(dir).entries);
74781
+ const summary2 = summarizeProgress2(readProgress2(dir).entries);
74547
74782
  const open = openApprovals2(readApprovals2(dir).events);
74548
74783
  const note = agentContextNote2(dir, cliVersion());
74549
- io.log(formatBrief2({ appName: appLabel2(dir), isContentPackage, summary, open, ...note ? { agentContextNote: note } : {} }));
74784
+ io.log(formatBrief2({ appName: appLabel2(dir), isContentPackage, summary: summary2, open, ...note ? { agentContextNote: note } : {} }));
74550
74785
  return 0;
74551
74786
  }
74552
74787
  if (!message) {
@@ -74604,9 +74839,9 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
74604
74839
  const sub = pos[1] ?? "audit";
74605
74840
  const dir = contentDir(flags);
74606
74841
  if (sub === "audit") {
74607
- const report2 = auditUx(dir, flags.strict === true);
74608
- print(report2);
74609
- return report2.ok ? 0 : 1;
74842
+ const report3 = auditUx(dir, flags.strict === true);
74843
+ print(report3);
74844
+ return report3.ok ? 0 : 1;
74610
74845
  }
74611
74846
  if (sub !== "record") {
74612
74847
  io.error(JSON.stringify({ error: "ux needs audit | record" }));
@@ -74818,7 +75053,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
74818
75053
  }
74819
75054
  const authoringBase = serveBase();
74820
75055
  try {
74821
- const { report: report2 } = await (deps.browserAuthoring ?? runBrowserAuthoring2)({
75056
+ const { report: report3 } = await (deps.browserAuthoring ?? runBrowserAuthoring2)({
74822
75057
  authoringBase,
74823
75058
  job: {
74824
75059
  entry: sources.entry,
@@ -74835,10 +75070,10 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
74835
75070
  log: (line) => io.error(line)
74836
75071
  });
74837
75072
  const { afterBrowserTestRun: afterBrowserTestRun2, watchReminder: watchReminder3 } = await Promise.resolve().then(() => (init_milestones(), milestones_exports));
74838
- const afterRun2 = afterBrowserTestRun2(dir, { screen: screen.screenId, report: report2, boardOpen: boardOpen(dir) });
75073
+ const afterRun2 = afterBrowserTestRun2(dir, { screen: screen.screenId, report: report3, boardOpen: boardOpen(dir) });
74839
75074
  const browserReminder = watchReminder3(dir, { content: str8(flags.content) });
74840
75075
  print({
74841
- ...report2,
75076
+ ...report3,
74842
75077
  screen: screen.screenId,
74843
75078
  ranIn: "browser",
74844
75079
  liveRequested: jobWix !== void 0,
@@ -74847,7 +75082,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
74847
75082
  // Also the envelope's LAST key (`tailLast` keeps it there): an agent may read only the tail.
74848
75083
  ...browserReminder ? { reminder: browserReminder } : {}
74849
75084
  });
74850
- return report2.ok ? 0 : 1;
75085
+ return report3.ok ? 0 : 1;
74851
75086
  } catch (e) {
74852
75087
  io.error(JSON.stringify({ error: e.message }));
74853
75088
  return 1;
@@ -75193,7 +75428,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
75193
75428
  const pngTarget = typeof flags.png === "string" ? str8(flags.png) : flags.png === true ? shotPath : void 0;
75194
75429
  if (pngTarget && r.pngBase64) {
75195
75430
  pngFile = writePngFile(pngTarget, r.pngBase64);
75196
- attestationPngFile = resolve51(pngTarget) === resolve51(shotPath) ? pngFile : writePngFile(shotPath, r.pngBase64);
75431
+ attestationPngFile = resolve52(pngTarget) === resolve52(shotPath) ? pngFile : writePngFile(shotPath, r.pngBase64);
75197
75432
  }
75198
75433
  if (renderWidth !== void 0 && r.renderable) {
75199
75434
  recordRenderWidth(dir, {
@@ -75285,23 +75520,23 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
75285
75520
  return 2;
75286
75521
  }
75287
75522
  const { kitReport: kitReport2 } = await Promise.resolve().then(() => (init_design_kits(), design_kits_exports));
75288
- const report2 = kitReport2(pos[2]);
75289
- print(report2);
75290
- return report2.ok ? 0 : 1;
75523
+ const report3 = kitReport2(pos[2]);
75524
+ print(report3);
75525
+ return report3.ok ? 0 : 1;
75291
75526
  }
75292
75527
  case "fonts": {
75293
75528
  const sub = pos[1];
75294
75529
  const dir = contentDir(flags);
75295
75530
  const { listReport: listReport3, checkReport: checkReport2, addReport: addReport2 } = await Promise.resolve().then(() => (init_fonts(), fonts_exports));
75296
75531
  if (sub === void 0 || sub === "list") {
75297
- const report2 = listReport3({ licenses: flags.licenses === true });
75298
- print(report2);
75299
- return report2.ok ? 0 : 1;
75532
+ const report3 = listReport3({ licenses: flags.licenses === true });
75533
+ print(report3);
75534
+ return report3.ok ? 0 : 1;
75300
75535
  }
75301
75536
  if (sub === "check") {
75302
- const report2 = await checkReport2(dir);
75303
- print(report2);
75304
- return report2.ok ? 0 : 1;
75537
+ const report3 = await checkReport2(dir);
75538
+ print(report3);
75539
+ return report3.ok ? 0 : 1;
75305
75540
  }
75306
75541
  if (sub === "add") {
75307
75542
  const family = pos[2];
@@ -75309,9 +75544,9 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
75309
75544
  print({ ok: false, problems: ["usage: himi fonts add <Family>"] });
75310
75545
  return 2;
75311
75546
  }
75312
- const report2 = addReport2(dir, family);
75313
- print(report2);
75314
- return report2.ok ? 0 : 1;
75547
+ const report3 = addReport2(dir, family);
75548
+ print(report3);
75549
+ return report3.ok ? 0 : 1;
75315
75550
  }
75316
75551
  print({ ok: false, problems: [`unknown subcommand "${sub}"`], hint: "himi fonts [list|check|add]" });
75317
75552
  return 2;
@@ -75332,7 +75567,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
75332
75567
  summarize: summarize4
75333
75568
  } = await Promise.resolve().then(() => (init_icon(), icon_exports));
75334
75569
  const requireVerified = sub === "check";
75335
- const report2 = async (status, extra = {}) => {
75570
+ const report3 = async (status, extra = {}) => {
75336
75571
  const findings = [
75337
75572
  // Not a store rule, so it is not in byteIssues — but it is the one `himi dist`
75338
75573
  // will refuse, and the point of `check` is to say so before the build does.
@@ -75370,7 +75605,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
75370
75605
  }
75371
75606
  return blocksRelease2(status, { requireVerified }) ? 1 : 0;
75372
75607
  };
75373
- if (sub === "status" || sub === "check") return report2(await iconStatus2(dir));
75608
+ if (sub === "status" || sub === "check") return report3(await iconStatus2(dir));
75374
75609
  if (sub === "set") {
75375
75610
  const file = pos[2];
75376
75611
  if (!file) {
@@ -75378,7 +75613,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
75378
75613
  return 1;
75379
75614
  }
75380
75615
  const res = await installIcon2(dir, file, { derivePlay: true });
75381
- return report2(res.status, { wrote: res.wrote, normalized: res.normalized, playListingIcon: res.playDerived });
75616
+ return report3(res.status, { wrote: res.wrote, normalized: res.normalized, playListingIcon: res.playDerived });
75382
75617
  }
75383
75618
  if (sub === "from-site") {
75384
75619
  const book = str8(flags.book) ?? ".himi/business-book";
@@ -75393,11 +75628,11 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
75393
75628
  return 1;
75394
75629
  }
75395
75630
  const res = await installIcon2(dir, logo, { derivePlay: true });
75396
- return report2(res.status, { from: logo, wrote: res.wrote, normalized: res.normalized, playListingIcon: res.playDerived });
75631
+ return report3(res.status, { from: logo, wrote: res.wrote, normalized: res.normalized, playListingIcon: res.playDerived });
75397
75632
  }
75398
75633
  if (sub === "generate") {
75399
75634
  const res = await generateIcon2(dir, { glyph: str8(flags.glyph), background: str8(flags.accent), derivePlay: true });
75400
- return report2(res.status, { wrote: res.wrote });
75635
+ return report3(res.status, { wrote: res.wrote });
75401
75636
  }
75402
75637
  if (sub === "glyphs") {
75403
75638
  const names = glyphNames2();
@@ -75423,9 +75658,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
75423
75658
  const dir = contentDir(flags);
75424
75659
  const { listReport: listReport3, verifyReport: verifyReport2, addAssetPayload: addAssetPayload2, removeAssetPayload: removeAssetPayload2 } = await Promise.resolve().then(() => (init_assets(), assets_exports));
75425
75660
  if (sub === void 0 || sub === "list") {
75426
- const report2 = listReport3(dir);
75427
- print(report2);
75428
- return report2.ok ? 0 : 1;
75661
+ const report3 = listReport3(dir);
75662
+ print(report3);
75663
+ return report3.ok ? 0 : 1;
75429
75664
  }
75430
75665
  if (sub === "verify") {
75431
75666
  const app = str8(flags.app) ?? await appId(dir);
@@ -75434,9 +75669,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
75434
75669
  io.error(JSON.stringify(found));
75435
75670
  return 1;
75436
75671
  }
75437
- const report2 = verifyReport2(dir, app, found.manifest);
75438
- print(report2);
75439
- return report2.ok ? 0 : 1;
75672
+ const report3 = verifyReport2(dir, app, found.manifest);
75673
+ print(report3);
75674
+ return report3.ok ? 0 : 1;
75440
75675
  }
75441
75676
  if (sub === "add" || sub === "rm") {
75442
75677
  const app = str8(flags.app) ?? await appId(dir);
@@ -75529,7 +75764,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
75529
75764
  return 2;
75530
75765
  }
75531
75766
  const renamed = str8(flags.name);
75532
- const dest = resolve51(str8(flags.out) ?? process.cwd(), renamed ?? wanted);
75767
+ const dest = resolve52(str8(flags.out) ?? process.cwd(), renamed ?? wanted);
75533
75768
  const replace = flags.replace === true;
75534
75769
  const force = replace || flags.force === true;
75535
75770
  const linked = symlinkDestinationIssue(dest);
@@ -75602,7 +75837,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
75602
75837
  let removed = [];
75603
75838
  if (replace) removed = removeStaleSource2(restored, dest);
75604
75839
  else left = staleSourcePaths2(restored, dest);
75605
- const refused = deniedArchivePaths2(restored);
75840
+ const refused2 = deniedArchivePaths2(restored);
75606
75841
  const written = writeAppSource2(restored, dest);
75607
75842
  const agent = await seedAgentFilesFor(dest, flags, "restore");
75608
75843
  print({
@@ -75613,8 +75848,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
75613
75848
  ...agent,
75614
75849
  ...renamed ? { renamedTo: renamed } : {},
75615
75850
  ...removed.length ? { removed } : {},
75616
- ...refused.length ? {
75617
- refused,
75851
+ ...refused2.length ? {
75852
+ refused: refused2,
75618
75853
  refusedNote: "this archive carries paths a restore will not write (the deny-list has grown since it was published) \u2014 they were skipped, not written over"
75619
75854
  } : {},
75620
75855
  // EVERY path, not a count and not a sample: the whole failure was that a hybrid tree
@@ -75698,7 +75933,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
75698
75933
  collect: { lint: true, strict }
75699
75934
  });
75700
75935
  const { navIssues: navIssues2 } = await Promise.resolve().then(() => (init_nav_lint(), nav_lint_exports));
75701
- const { report: report2, hasErrors } = summarizeLint(declared, bres, outcome, strict, [
75936
+ const { report: report3, hasErrors } = summarizeLint(declared, bres, outcome, strict, [
75702
75937
  ...await cmsIssues(dir, declared, strict, { local: true }),
75703
75938
  ...surfaceIssues(dir, outcome.surfaceNav, strict),
75704
75939
  ...tokenColorIssues(dir),
@@ -75708,7 +75943,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
75708
75943
  ...await navIssues2(dir, strict)
75709
75944
  ]);
75710
75945
  if (hasErrors && !force) {
75711
- print({ ...report2, pushed: false, hint: "lint found errors \u2014 fix them, or re-run `himi push --force` to publish anyway" });
75946
+ print({ ...report3, pushed: false, hint: "lint found errors \u2014 fix them, or re-run `himi push --force` to publish anyway" });
75712
75947
  return 1;
75713
75948
  }
75714
75949
  const declaredData = await loadDataResourcesQuietly(dir);
@@ -75807,7 +76042,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
75807
76042
  // Reaches here ONLY on the forced path — the refusal above returned otherwise — so
75808
76043
  // this is the override's record, and the case it matters most for is a `failed` drive.
75809
76044
  ux: { evidence: patchUxEvidence, ctx: patchUxContext },
75810
- lint: report2.counts ?? null,
76045
+ lint: report3.counts ?? null,
75811
76046
  extra: { selector: parsed.selectors.map((s) => "pattern" in s ? `${s.kind}:${s.pattern}` : s.kind) }
75812
76047
  });
75813
76048
  }
@@ -76059,7 +76294,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76059
76294
  // print a `himi pull` command that answers app_source_not_found later — the worst
76060
76295
  // shape for a backup, which is one you are told you have.
76061
76296
  ...sourceSummary ? sourceStored === true ? { source: { ...sourceSummary, restore: `himi pull ${app} --release ${release}` } } : sourceStored === false ? { source: { ...sourceSummary, archived: false, note: "this serve target cannot store source archives, so this release cannot be restored with `himi pull`" } } : { source: { ...sourceSummary, archived: "unconfirmed", note: `this serve target did not report whether it stored the source (it may predate the field). Verify with \`himi pull ${app} --release ${release}\` before relying on it.` } } : { source: { archived: false, note: "pushed with --no-source \u2014 this release cannot be restored with `himi pull`" } },
76062
- lint: report2.counts,
76297
+ lint: report3.counts,
76063
76298
  // A push ships content, not backends. If the app declares CMS
76064
76299
  // collections, say so and point at the verbs — but never mutate the
76065
76300
  // site as a side effect of publishing a release.
@@ -76091,7 +76326,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76091
76326
  nondeterministicWorkers: drifting
76092
76327
  }),
76093
76328
  ...loopbackWarning ? { warning: loopbackWarning } : {},
76094
- ...report2.issues ? { issues: report2.issues } : {},
76329
+ ...report3.issues ? { issues: report3.issues } : {},
76095
76330
  previewWeb: base ? previewWebUrl(base, app, release, void 0, void 0, previewToken, previewHandover) : null,
76096
76331
  // A timestamp alone leaves the reader to work out both how long they have and how to
76097
76332
  // get another one. Print the duration and the re-mint command beside it (#2502 item 3).
@@ -76188,7 +76423,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76188
76423
  return 2;
76189
76424
  }
76190
76425
  try {
76191
- const res = writePack(resolve51(releaseDir), only, resolve51(str8(flags.out) ?? process.cwd()));
76426
+ const res = writePack(resolve52(releaseDir), only, resolve52(str8(flags.out) ?? process.cwd()));
76192
76427
  print({
76193
76428
  ok: true,
76194
76429
  app: res.app,
@@ -76244,7 +76479,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76244
76479
  collect: { lint: true, strict }
76245
76480
  });
76246
76481
  const { navIssues: navIssues2 } = await Promise.resolve().then(() => (init_nav_lint(), nav_lint_exports));
76247
- const { report: report2, hasErrors } = summarizeLint(app, bres, outcome, strict, [
76482
+ const { report: report3, hasErrors } = summarizeLint(app, bres, outcome, strict, [
76248
76483
  ...await cmsIssues(dir, app, strict, { local: true }),
76249
76484
  ...surfaceIssues(dir, outcome.surfaceNav, strict),
76250
76485
  ...tokenColorIssues(dir),
@@ -76255,11 +76490,11 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76255
76490
  ]);
76256
76491
  if (hasErrors && !force) {
76257
76492
  rmSync15(built, { recursive: true, force: true });
76258
- print({ ...report2, packed: false, hint: "lint found errors \u2014 fix them, or re-run `himi pack --force` to pack anyway" });
76493
+ print({ ...report3, packed: false, hint: "lint found errors \u2014 fix them, or re-run `himi pack --force` to pack anyway" });
76259
76494
  return 1;
76260
76495
  }
76261
76496
  try {
76262
- const res = writePack(built, app, resolve51(str8(flags.out) ?? dir), sourceArchive);
76497
+ const res = writePack(built, app, resolve52(str8(flags.out) ?? dir), sourceArchive);
76263
76498
  print({
76264
76499
  ok: true,
76265
76500
  app: res.app,
@@ -76269,12 +76504,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76269
76504
  entries: res.entryCount,
76270
76505
  format,
76271
76506
  launchMode,
76272
- lint: report2.counts,
76507
+ lint: report3.counts,
76273
76508
  contents: withSource ? "dev" : "release",
76274
76509
  ...sourceSummary ? { source: sourceSummary } : {},
76275
76510
  ...res.skipped.length ? { skipped: res.skipped } : {},
76276
76511
  ...hasErrors && force ? { forcedPastErrors: true } : {},
76277
- ...report2.issues ? { issues: report2.issues } : {},
76512
+ ...report3.issues ? { issues: report3.issues } : {},
76278
76513
  open: [
76279
76514
  ...withSource ? [`himi import ${res.out}`] : [],
76280
76515
  `himi run ${res.out}`,
@@ -76304,7 +76539,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76304
76539
  const { HIMI_PACKAGE_SOURCE_PATH: HIMI_PACKAGE_SOURCE_PATH2, isSafeAppId: isSafeAppId2, packageContents: packageContents2 } = await Promise.resolve().then(() => (init_himi_package(), himi_package_exports));
76305
76540
  let opened;
76306
76541
  try {
76307
- opened = openPackageFile2(resolve51(file));
76542
+ opened = openPackageFile2(resolve52(file));
76308
76543
  } catch (e) {
76309
76544
  io.error(JSON.stringify({ error: e.message }));
76310
76545
  return 1;
@@ -76317,7 +76552,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76317
76552
  io.error(JSON.stringify({
76318
76553
  ok: false,
76319
76554
  error: "app_source_not_in_package",
76320
- detail: `${resolve51(file)} is a release package: it carries built output (screens, bundles, tokens) and no source`,
76555
+ detail: `${resolve52(file)} is a release package: it carries built output (screens, bundles, tokens) and no source`,
76321
76556
  hint: "re-pack it from the content package with `himi pack --dev`, or restore from the serve plane with `himi pull <app>`"
76322
76557
  }));
76323
76558
  return 1;
@@ -76340,7 +76575,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76340
76575
  return 1;
76341
76576
  }
76342
76577
  }
76343
- const dest = resolve51(str8(flags.out) ?? process.cwd(), renamed ?? opened.header.app);
76578
+ const dest = resolve52(str8(flags.out) ?? process.cwd(), renamed ?? opened.header.app);
76344
76579
  const issue2 = restoreDestinationIssue(dest, flags.force === true);
76345
76580
  if (issue2) {
76346
76581
  io.error(JSON.stringify(issue2));
@@ -76379,7 +76614,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76379
76614
  return 1;
76380
76615
  }
76381
76616
  const left = staleSourcePaths2(restored, dest);
76382
- const refused = deniedArchivePaths2(restored);
76617
+ const refused2 = deniedArchivePaths2(restored);
76383
76618
  const written = writeAppSource2(restored, dest);
76384
76619
  const agent = await seedAgentFilesFor(dest, flags, "restore");
76385
76620
  print({
@@ -76390,8 +76625,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76390
76625
  files: written.length,
76391
76626
  ...agent,
76392
76627
  ...renamed ? { renamedTo: renamed } : {},
76393
- ...refused.length ? {
76394
- refused,
76628
+ ...refused2.length ? {
76629
+ refused: refused2,
76395
76630
  refusedNote: "this package carries paths a restore will not write (the deny-list has grown since it was packed) \u2014 they were skipped, not written over"
76396
76631
  } : {},
76397
76632
  ...left.length ? {
@@ -76427,7 +76662,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76427
76662
  }
76428
76663
  try {
76429
76664
  const { openPackageFile: openPackageFile2 } = await Promise.resolve().then(() => (init_pack(), pack_exports));
76430
- const opened = openPackageFile2(resolve51(file));
76665
+ const opened = openPackageFile2(resolve52(file));
76431
76666
  if (!opened.validation.ok || !opened.header) {
76432
76667
  io.error(JSON.stringify({ error: "refusing to share an invalid package", issues: opened.validation.errors }));
76433
76668
  return 1;
@@ -76437,12 +76672,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76437
76672
  io.error(JSON.stringify({
76438
76673
  ok: false,
76439
76674
  error: "refusing to share a package that carries the app's source",
76440
- detail: `${resolve51(file)} was packed with --dev, and a share link is public and unauthenticated \u2014 anyone with the URL could \`himi import\` your codebase`,
76675
+ detail: `${resolve52(file)} was packed with --dev, and a share link is public and unauthenticated \u2014 anyone with the URL could \`himi import\` your codebase`,
76441
76676
  hint: "share a release package instead (`himi pack` with no --dev), or hand the dev package over directly"
76442
76677
  }));
76443
76678
  return 1;
76444
76679
  }
76445
- const archive = readFileSync79(resolve51(file));
76680
+ const archive = readFileSync79(resolve52(file));
76446
76681
  const result = await client2().createPackageShare({
76447
76682
  app: opened.header.app,
76448
76683
  releaseId: opened.header.releaseId,
@@ -76581,9 +76816,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76581
76816
  });
76582
76817
  await announce(run2);
76583
76818
  print({ ok: true, app: run2.app, url: run2.url, port: run2.port, plane: "browser" });
76584
- await new Promise((resolve52) => {
76819
+ await new Promise((resolve53) => {
76585
76820
  const stop = () => {
76586
- void retract().catch((e) => io.error(JSON.stringify({ run: "stop_cleanup_failed", message: e.message }))).finally(() => run2.close().finally(() => resolve52()));
76821
+ void retract().catch((e) => io.error(JSON.stringify({ run: "stop_cleanup_failed", message: e.message }))).finally(() => run2.close().finally(() => resolve53()));
76587
76822
  };
76588
76823
  process.once("SIGINT", stop);
76589
76824
  process.once("SIGTERM", stop);
@@ -78623,13 +78858,13 @@ ${label2}`);
78623
78858
  // advertisable for the target this report is about.
78624
78859
  hasOwnerIssuer: (resolved2?.ownerIssue ?? "") !== ""
78625
78860
  });
78626
- const report2 = buildDoctorReport({ target, version: cliVersion(), data, serve, auth, loginModes, dpxStatus, versions });
78627
- if (targetError) report2.targetError = targetError;
78861
+ const report3 = buildDoctorReport({ target, version: cliVersion(), data, serve, auth, loginModes, dpxStatus, versions });
78862
+ if (targetError) report3.targetError = targetError;
78628
78863
  const { agentContextStatus: agentContextStatus2 } = await Promise.resolve().then(() => (init_agent_context(), agent_context_exports));
78629
78864
  const agentContext = agentContextStatus2(contentDir(flags), cliVersion());
78630
- if (agentContext) report2.agentContext = agentContext;
78865
+ if (agentContext) report3.agentContext = agentContext;
78631
78866
  if (flags.json === true) {
78632
- print(report2);
78867
+ print(report3);
78633
78868
  return 0;
78634
78869
  }
78635
78870
  const mark = (r) => r.reachable ? `reachable${r.status ? ` [${r.status}]` : ""}` : `UNREACHABLE${r.error ? ` (${r.error})` : ""}`;
@@ -78639,7 +78874,7 @@ ${label2}`);
78639
78874
  io.log(` ${mark(data)}`);
78640
78875
  io.log(` serve plane ${serveUrl || "(no serve url)"}`);
78641
78876
  io.log(` ${mark(serve)}`);
78642
- const serveCode = report2.servePlane.code;
78877
+ const serveCode = report3.servePlane.code;
78643
78878
  if (serveCode) io.log(` ${serveCode}: ${serveUnreachableHint(target)}`);
78644
78879
  io.log(` auth dpx session: ${auth.dpxSession ? "yes" : "no"} control token: ${auth.controlToken ? "yes" : controlHostRefused ? "REFUSED" : auth.controlTokenPresent ? "STALE" : "no"}`);
78645
78880
  if (auth.controlTokenHint) io.log(` ${auth.controlTokenHint}`);
@@ -78662,7 +78897,7 @@ ${label2}`);
78662
78897
  }
78663
78898
  io.log(
78664
78899
  `
78665
- ${report2.ok ? "OK \u2014 data + serve plane reachable." : typeof report2.hint === "string" && report2.hint ? report2.hint : serve.reachable ? "Data plane unreachable \u2014 check basic connectivity." : serveUnreachableHint(target)}`
78900
+ ${report3.ok ? "OK \u2014 data + serve plane reachable." : typeof report3.hint === "string" && report3.hint ? report3.hint : serve.reachable ? "Data plane unreachable \u2014 check basic connectivity." : serveUnreachableHint(target)}`
78666
78901
  );
78667
78902
  return 0;
78668
78903
  }
@@ -78775,9 +79010,9 @@ ${report2.ok ? "OK \u2014 data + serve plane reachable." : typeof report2.hint =
78775
79010
  }
78776
79011
  const scope = { app, siteId: site, environment: environment2 };
78777
79012
  try {
78778
- const report2 = sub === "plan" ? await planData({ scope, data, kv, call }) : sub === "create" ? await createData({ scope, data, kv, call, dryRun: flags["dry-run"] === true }) : await seedData({ scope, data, kv, call, dir, dryRun: flags["dry-run"] === true, force: flags.force === true });
78779
- print(report2);
78780
- return report2.ok ? 0 : 1;
79013
+ const report3 = sub === "plan" ? await planData({ scope, data, kv, call }) : sub === "create" ? await createData({ scope, data, kv, call, dryRun: flags["dry-run"] === true }) : await seedData({ scope, data, kv, call, dir, dryRun: flags["dry-run"] === true, force: flags.force === true });
79014
+ print(report3);
79015
+ return report3.ok ? 0 : 1;
78781
79016
  } catch (error) {
78782
79017
  io.error(JSON.stringify({ error: error.message, app, site, environment: environment2, hint: "run `himi data plan` to re-read actual state before retrying" }));
78783
79018
  return 1;
@@ -78792,6 +79027,14 @@ ${report2.ok ? "OK \u2014 data + serve plane reachable." : typeof report2.hint =
78792
79027
  const { runNotifySetup: runNotifySetup2 } = await Promise.resolve().then(() => (init_notify_setup(), notify_setup_exports));
78793
79028
  return runNotifySetup2(pos, flags, io);
78794
79029
  }
79030
+ if (pos[1] === "send" && flags.provider !== void 0) {
79031
+ if (flags.provider !== "ping") {
79032
+ io.error(JSON.stringify({ ok: false, error: "unknown_provider", hint: "The hosted sender is --provider ping." }));
79033
+ return 2;
79034
+ }
79035
+ const { runNotifyPing: runNotifyPing2 } = await Promise.resolve().then(() => (init_notify_ping(), notify_ping_exports));
79036
+ return runNotifyPing2(flags, io);
79037
+ }
78795
79038
  const { runNotify: runNotify2 } = await Promise.resolve().then(() => (init_notify(), notify_exports));
78796
79039
  return await runNotify2(pos, flags, io);
78797
79040
  case "cms": {
@@ -78850,9 +79093,9 @@ ${report2.ok ? "OK \u2014 data + serve plane reachable." : typeof report2.hint =
78850
79093
  return 2;
78851
79094
  }
78852
79095
  const common = { app, cms, call };
78853
- let report2;
79096
+ let report3;
78854
79097
  try {
78855
- report2 = sub === "query" ? await queryCms({ ...common, all: flags.all === true }) : sub === "create" ? await createCms({ ...common, dryRun: flags["dry-run"] === true, allowDestructive: flags["allow-destructive"] === true, applyPermissions: flags["apply-permissions"] === true }) : await seedCms({ ...common, dir, dryRun: flags["dry-run"] === true, force: flags.force === true, only: str8(flags.only) });
79098
+ report3 = sub === "query" ? await queryCms({ ...common, all: flags.all === true }) : sub === "create" ? await createCms({ ...common, dryRun: flags["dry-run"] === true, allowDestructive: flags["allow-destructive"] === true, applyPermissions: flags["apply-permissions"] === true }) : await seedCms({ ...common, dir, dryRun: flags["dry-run"] === true, force: flags.force === true, only: str8(flags.only) });
78856
79099
  } catch (e) {
78857
79100
  const partial = e.partial;
78858
79101
  io.error(JSON.stringify({
@@ -78864,8 +79107,8 @@ ${report2.ok ? "OK \u2014 data + serve plane reachable." : typeof report2.hint =
78864
79107
  }));
78865
79108
  return 1;
78866
79109
  }
78867
- print({ ...report2, site });
78868
- return report2.ok ? 0 : 1;
79110
+ print({ ...report3, site });
79111
+ return report3.ok ? 0 : 1;
78869
79112
  }
78870
79113
  case "site": {
78871
79114
  const sub = pos[1];