@wix/himalaya-cli 0.997.0 → 0.999.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
@@ -6607,8 +6607,10 @@ __export(validate_descriptor_core_exports, {
6607
6607
  isOpaqueAuthorJson: () => isOpaqueAuthorJson,
6608
6608
  loadBundleServicesLive: () => loadBundleServicesLive,
6609
6609
  nativeRequiredFindings: () => nativeRequiredFindings,
6610
+ nondeterministicServices: () => nondeterministicServices,
6610
6611
  pathCrossesOpaqueAuthorJson: () => pathCrossesOpaqueAuthorJson,
6611
6612
  pathValue: () => pathValue,
6613
+ pinnedIntrinsicsSource: () => pinnedIntrinsicsSource,
6612
6614
  resolveActionEvaluator: () => resolveActionEvaluator,
6613
6615
  resolveBootEvaluator: () => resolveBootEvaluator,
6614
6616
  resolveEvaluator: () => resolveEvaluator,
@@ -6704,12 +6706,17 @@ function runBundleSandbox(bundleJs, opts) {
6704
6706
  TextEncoder,
6705
6707
  TextDecoder,
6706
6708
  AbortController
6709
+ // NO `Date` / `Math` here, pinned or not: a pinned pair built on this side would be the host's
6710
+ // intrinsics wearing a sandbox name. The realm builds them from its own (`pinnedIntrinsicsSource`).
6707
6711
  };
6708
6712
  try {
6709
6713
  resolveBootEvaluator(opts.evaluator).run(bundleJs, sandbox, {
6710
6714
  timeoutMs: opts.timeoutMs ?? BOOT_EVAL_TIMEOUT_MS,
6711
6715
  filename: "himi-bundle.js",
6712
- captureConsole: Boolean(opts.captureConsole)
6716
+ captureConsole: Boolean(opts.captureConsole),
6717
+ ...opts.clock === void 0 ? {} : { clock: opts.clock },
6718
+ ...opts.seed === void 0 ? {} : { seed: opts.seed },
6719
+ ...opts.mirrorRandom ? { mirrorRandom: true } : {}
6713
6720
  });
6714
6721
  return { services, actions, console: consoleLines, threw: null };
6715
6722
  } catch (err) {
@@ -6735,6 +6742,59 @@ function dryRunBundle(bundleJs, opts = {}) {
6735
6742
  const r = runBundleSandbox(bundleJs, { rethrow: false, captureConsole: true, ...opts });
6736
6743
  return { services: Object.keys(r.services), console: r.console, threw: r.threw };
6737
6744
  }
6745
+ function pinnedIntrinsicsSource(pins) {
6746
+ const clock = pins.clock === void 0 ? void 0 : Number(pins.clock);
6747
+ const seed2 = pins.seed === void 0 ? void 0 : Math.trunc(Number(pins.seed)) >>> 0 || 1;
6748
+ if (clock === void 0 && seed2 === void 0) return null;
6749
+ const date = clock === void 0 ? "" : `
6750
+ var pinned = ${clock};
6751
+ // Captured NOW, before any bundle code runs: resolved per call, a worker that deletes or
6752
+ // overwrites \`globalThis.Reflect\` would make every pinned \`new Date()\` throw, both drift probes
6753
+ // would fail, and the drift check would stay silent about a worker the real build boots fine.
6754
+ var construct = Reflect.construct;
6755
+ // \`new Date()\` \u2192 the pinned instant; \`new Date(<args>)\` keeps its meaning; \`Date()\` called as a
6756
+ // function returns the pinned instant's string, as it would the current one.
6757
+ var PinnedDate = function Date() {
6758
+ if (new.target === undefined) return new RealDate(pinned).toString();
6759
+ return arguments.length ? construct(RealDate, arguments, new.target) : construct(RealDate, [pinned], new.target);
6760
+ };
6761
+ PinnedDate.prototype = Object.create(RealDate.prototype, { constructor: { value: PinnedDate, writable: true, configurable: true } });
6762
+ PinnedDate.now = function now() { return pinned; };
6763
+ PinnedDate.parse = RealDate.parse;
6764
+ PinnedDate.UTC = RealDate.UTC;
6765
+ out.Date = PinnedDate;`;
6766
+ const math = seed2 === void 0 ? "" : `
6767
+ var s = ${seed2};
6768
+ var imul = RealMath.imul;
6769
+ var M = Object.create(Object.getPrototypeOf(RealMath));
6770
+ Object.getOwnPropertyNames(RealMath).forEach(function (k) { Object.defineProperty(M, k, Object.getOwnPropertyDescriptor(RealMath, k)); });
6771
+ Object.getOwnPropertySymbols(RealMath).forEach(function (k) { Object.defineProperty(M, k, Object.getOwnPropertyDescriptor(RealMath, k)); });
6772
+ // Non-writable, so a bundle cannot put an unseeded PRNG back and make a seeded run vary.
6773
+ Object.defineProperty(M, "random", {
6774
+ value: function random() {
6775
+ s = (s + 0x6d2b79f5) >>> 0;
6776
+ var t = imul(s ^ (s >>> 15), 1 | s);
6777
+ t = (t + imul(t ^ (t >>> 7), 61 | t)) ^ t;
6778
+ var u = (t ^ (t >>> 14)) >>> 0;
6779
+ return ${pins.mirrorRandom ? "(~u >>> 0)" : "u"} / 4294967296;
6780
+ },
6781
+ writable: false, enumerable: false, configurable: false,
6782
+ });
6783
+ out.Math = M;`;
6784
+ return `(function (RealDate, RealMath) {
6785
+ var out = {};${date}${math}
6786
+ return out;
6787
+ })`;
6788
+ }
6789
+ function nondeterministicServices(bundleJs, opts = {}) {
6790
+ const boots = DRIFT_PROBES.map((probe) => runBundleSandbox(bundleJs, { rethrow: false, ...opts, ...probe }));
6791
+ const threw = boots.filter((b2) => b2.threw !== null).length;
6792
+ if (threw === boots.length) return [];
6793
+ const [a, b] = boots.map((boot) => boot.services);
6794
+ const names = [.../* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)])];
6795
+ if (threw > 0) return names.sort();
6796
+ return names.filter((name) => safeStringify(a[name]) !== safeStringify(b[name])).sort();
6797
+ }
6738
6798
  function setDefaultEvaluator(evaluator) {
6739
6799
  defaultEvaluator = evaluator;
6740
6800
  }
@@ -6875,26 +6935,10 @@ async function bootBundleWorker(bundleJs, opts) {
6875
6935
  timers.delete(t);
6876
6936
  }
6877
6937
  };
6878
- const frozenDate = opts.clock === void 0 ? void 0 : new Proxy(Date, {
6879
- get: (t, p) => p === "now" ? () => opts.clock : Reflect.get(t, p),
6880
- // `new Date()` → the pinned instant; `new Date(<args>)` keeps its normal meaning.
6881
- construct: (t, args) => args.length ? new t(...args) : new t(opts.clock),
6882
- apply: () => new Date(opts.clock).toString()
6883
- });
6884
- const seededMath = opts.seed === void 0 ? void 0 : (() => {
6885
- let s = opts.seed >>> 0 || 1;
6886
- const m = Object.create(Math);
6887
- Object.defineProperty(m, "random", {
6888
- value: () => {
6889
- s = s + 1831565813 >>> 0;
6890
- let t = Math.imul(s ^ s >>> 15, 1 | s);
6891
- t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
6892
- return ((t ^ t >>> 14) >>> 0) / 4294967296;
6893
- },
6894
- enumerable: true
6895
- });
6896
- return m;
6897
- })();
6938
+ const pins = {
6939
+ ...opts.clock === void 0 ? {} : { clock: opts.clock },
6940
+ ...opts.seed === void 0 ? {} : { seed: opts.seed }
6941
+ };
6898
6942
  const sandbox = {
6899
6943
  himalaya,
6900
6944
  globalThis: void 0,
@@ -6922,8 +6966,6 @@ async function bootBundleWorker(bundleJs, opts) {
6922
6966
  clearInterval: () => {
6923
6967
  }
6924
6968
  },
6925
- ...frozenDate ? { Date: frozenDate } : {},
6926
- ...seededMath ? { Math: seededMath } : {},
6927
6969
  // HOST globals, not ECMAScript built-ins: a bare vm context has Object/Array/Date/Intl/JSON
6928
6970
  // but NOT these. Injecting them unconditionally — INCLUDING under deviceParity — rested on
6929
6971
  // "every real worker runtime (JSC, Hermes, the web-host Worker) does" have them. **A bare
@@ -6974,7 +7016,7 @@ async function bootBundleWorker(bundleJs, opts) {
6974
7016
  errors.push({ service: "(boot)", message: ran.error });
6975
7017
  }
6976
7018
  } else {
6977
- realm.run(bundleJs, sandbox, { timeoutMs: 2e3, filename: "himi-bundle.js", hide });
7019
+ realm.run(bundleJs, sandbox, { timeoutMs: 2e3, filename: "himi-bundle.js", hide, ...pins });
6978
7020
  }
6979
7021
  } catch (err) {
6980
7022
  errors.push({ service: "(boot)", message: err?.message ?? String(err), ...err?.stack ? { stack: err.stack } : {} });
@@ -8376,7 +8418,7 @@ function validateScreenDescriptor(screenId, descriptor, opts = {}) {
8376
8418
  services: Object.keys(services)
8377
8419
  };
8378
8420
  }
8379
- var CRAWL_BLOCKING_PASSES, BOOT_EVAL_TIMEOUT_MS, DEVICE_PARITY_WITHHELD, defaultEvaluator, bootEvaluator, actionEvaluator, NATIVE_PROP_ENUMS, KNOWN_PROPS, IN_ARRAY_BINDING_PROPS, SERVICE_SIGIL, INTEGER_PROPS, NATIVE_REQUIRED_PROPS, bareNestedClass, NATIVE_NESTED_CLASSES, NATIVE_MODIFIERS_CLASS, NATIVE_DESCRIPTOR_CLASS, NATIVE_DESCRIPTOR_NESTED, NATIVE_NESTED_PROPS, MODIFIER_KEYS, INTEGER_MODIFIERS, MODIFIER_KINDS, SCHEMA_SCORED_NODES, CORE_PACKAGES, LEGACY_UNSCORED_KEYS, DYNAMIC_PLACEHOLDER, LITERAL_ONLY_PROPS, SERVICE_ONLY_BINDING_PROPS, WHOLE_VALUE_BINDING, EMBEDDED_BINDING, OPTIONS_BINDING_PROPS;
8421
+ var CRAWL_BLOCKING_PASSES, BOOT_EVAL_TIMEOUT_MS, DRIFT_PROBES, DEVICE_PARITY_WITHHELD, defaultEvaluator, bootEvaluator, actionEvaluator, NATIVE_PROP_ENUMS, KNOWN_PROPS, IN_ARRAY_BINDING_PROPS, SERVICE_SIGIL, INTEGER_PROPS, NATIVE_REQUIRED_PROPS, bareNestedClass, NATIVE_NESTED_CLASSES, NATIVE_MODIFIERS_CLASS, NATIVE_DESCRIPTOR_CLASS, NATIVE_DESCRIPTOR_NESTED, NATIVE_NESTED_PROPS, MODIFIER_KEYS, INTEGER_MODIFIERS, MODIFIER_KINDS, SCHEMA_SCORED_NODES, CORE_PACKAGES, LEGACY_UNSCORED_KEYS, DYNAMIC_PLACEHOLDER, LITERAL_ONLY_PROPS, SERVICE_ONLY_BINDING_PROPS, WHOLE_VALUE_BINDING, EMBEDDED_BINDING, OPTIONS_BINDING_PROPS;
8380
8422
  var init_validate_descriptor_core = __esm({
8381
8423
  "../../core/dev-server/src/validate-descriptor.core.ts"() {
8382
8424
  init_validator();
@@ -8395,6 +8437,12 @@ var init_validate_descriptor_core = __esm({
8395
8437
  "strict-enum"
8396
8438
  ]);
8397
8439
  BOOT_EVAL_TIMEOUT_MS = 2e3;
8440
+ DRIFT_PROBES = [
8441
+ { clock: Date.UTC(2020, 0, 1, 12, 0, 0, 0), seed: 1 },
8442
+ // a Wednesday, the 1st/2nd, everywhere in -11h…+14h
8443
+ { clock: Date.UTC(2021, 7, 28, 19, 35, 57, 789), seed: 1, mirrorRandom: true }
8444
+ // a Saturday or Sunday, the 28th/29th
8445
+ ];
8398
8446
  DEVICE_PARITY_WITHHELD = [
8399
8447
  "setTimeout",
8400
8448
  "clearTimeout",
@@ -9388,25 +9436,10 @@ function preludeFor(opts) {
9388
9436
  var consoleJson = "";
9389
9437
  var stringify = JSON.stringify;
9390
9438
  ${GUEST_NONFINITE_CODEC}${opts.seed === void 0 ? "" : `
9391
- // mulberry32, bit-identical to the host's seeded Math in validate-descriptor.core.ts. Math.imul
9392
- // and the >>> 0 coercions are what keep it identical: the algorithm is defined over 32-bit
9393
- // integers, and float arithmetic would drift apart after a handful of draws. Installed
9394
- // non-writable so a bundle cannot put the engine's PRNG back and make a seeded run vary.
9395
- (function () {
9396
- var s = (${Math.trunc(opts.seed) >>> 0}) || 1;
9397
- var $imul = Math.imul;
9398
- Object.defineProperty(Math, "random", {
9399
- value: function () {
9400
- s = (s + 0x6d2b79f5) >>> 0;
9401
- var t = $imul(s ^ (s >>> 15), 1 | s);
9402
- t = (t + $imul(t ^ (t >>> 7), 61 | t)) ^ t;
9403
- return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
9404
- },
9405
- enumerable: true,
9406
- configurable: false,
9407
- writable: false,
9408
- });
9409
- })();
9439
+ // A seeded Math \u2014 a copy of this realm's own, whose \`random\` is mulberry32, non-writable so a
9440
+ // bundle cannot put the engine's PRNG back and make a seeded run vary. The same source every
9441
+ // realm evaluates, so the stream is bit-identical to node:vm's by construction.
9442
+ globalThis.Math = (${pinnedIntrinsicsSource({ seed: opts.seed, ...opts.mirrorRandom ? { mirrorRandom: true } : {} })})(Date, Math).Math;
9410
9443
  `}
9411
9444
  var parse = JSON.parse;
9412
9445
  var stringValue = String;
@@ -9733,7 +9766,7 @@ ${opts.liveTransport ? ` var handle = { getState: function () { return def
9733
9766
  // GREEN on exactly the floor gate this realm exists to enforce. The URL family is never
9734
9767
  // installed here at all, which is why only these four need the guard.
9735
9768
  ${timerGlobals(opts.hide, opts.liveTransport === true)}
9736
- ${opts.clock !== void 0 ? ` globalThis.Date.now = function () { return ${opts.clock}; };` : ""}${opts.liveTransport ? `
9769
+ ${opts.clock === void 0 ? "" : opts.freezeDate ? ` globalThis.Date = (${pinnedIntrinsicsSource({ clock: opts.clock })})(globalThis.Date, Math).Date;` : ` globalThis.Date.now = function () { return ${opts.clock}; };`}${opts.liveTransport ? `
9737
9770
  // THE LOAD SWEEP, INSIDE THE GUEST. It has to live here: the service definitions are
9738
9771
  // closure-held and deliberately unnameable from guest code, so the host cannot reach the action
9739
9772
  // FUNCTIONS at all \u2014 which is precisely why the sync realm could not run them and silently
@@ -9877,7 +9910,17 @@ async function createQuickJsEvaluator(options = {}) {
9877
9910
  let readback = null;
9878
9911
  try {
9879
9912
  const pre = ctx.evalCode(
9880
- preludeFor({ input: himalaya?.input ?? {}, captureConsole, clock: options.clock, hide: opts.hide }),
9913
+ // A per-run clock/seed (#3049's drift probe) wins over the realm-wide pinned clock. Built
9914
+ // in the guest from the guest's own intrinsics, like every realm's (`pinnedIntrinsicsSource`).
9915
+ preludeFor({
9916
+ input: himalaya?.input ?? {},
9917
+ captureConsole,
9918
+ clock: opts.clock ?? options.clock,
9919
+ freezeDate: opts.clock !== void 0,
9920
+ hide: opts.hide,
9921
+ ...opts.seed === void 0 ? {} : { seed: opts.seed },
9922
+ ...opts.mirrorRandom ? { mirrorRandom: true } : {}
9923
+ }),
9881
9924
  "himi-sandbox.js"
9882
9925
  );
9883
9926
  if (pre.error) {
@@ -22901,7 +22944,7 @@ function ensureHListStyles() {
22901
22944
  if (hListStylesInjected || typeof document === "undefined") return;
22902
22945
  hListStylesInjected = true;
22903
22946
  const el = document.createElement("style");
22904
- el.textContent = "[data-himalaya-hlist]>*{flex:0 0 auto}";
22947
+ el.textContent = HLIST_CHILD_CSS;
22905
22948
  document.head.appendChild(el);
22906
22949
  }
22907
22950
  function ensureListAnimateRuntime() {
@@ -24134,10 +24177,16 @@ function renderNode(node, ctx) {
24134
24177
  function renderInner(node, ctx) {
24135
24178
  if (!node || typeof node !== "object") return null;
24136
24179
  const { type, props, modifiers } = normalize(node);
24180
+ const hListItem = ctx.hListItem === true;
24137
24181
  if (modifiers?.theme) ctx = withTheme(ctx, modifiers.theme);
24182
+ if (ctx.hListItem) ctx = { ...ctx, hListItem: false };
24138
24183
  const pkg = node.body?.package;
24139
24184
  const C = ctx.color;
24140
24185
  const wrap = ctx.modStyle(resolveModBindings(modifiers, ctx));
24186
+ const rowItemHold = hListItem && wrap.flex == null && wrap.flexShrink == null;
24187
+ if (rowItemHold) wrap.flexShrink = 0;
24188
+ const rowItem = rowItemHold ? { flexShrink: 0 } : {};
24189
+ const itemCtx = hListItem ? { ...ctx, hListItem: true } : ctx;
24141
24190
  {
24142
24191
  const m = modifiers;
24143
24192
  const hp = boundModNumber(m?.heightPath ?? m?.height_path, ctx);
@@ -24194,25 +24243,25 @@ function renderInner(node, ctx) {
24194
24243
  if (spec) {
24195
24244
  ensureTransitionKeyframes();
24196
24245
  ensureRevealRuntime();
24197
- const inner = renderNode({ ...node, modifiers: { ...modifiers, transition: void 0, revealOnScroll: void 0 } }, ctx);
24198
- const style = { opacity: 0 };
24246
+ const inner = renderNode({ ...node, modifiers: { ...modifiers, transition: void 0, revealOnScroll: void 0 } }, itemCtx);
24247
+ const style = { opacity: 0, ...rowItem };
24199
24248
  if (spec.distance != null) style["--hm-d"] = `${spec.distance}px`;
24200
24249
  return /* @__PURE__ */ jsx6("div", { "data-himalaya-reveal": spec.animation, style, children: inner });
24201
24250
  }
24202
24251
  }
24203
24252
  if (typeof modifiers?.parallax === "number" && modifiers.parallax !== 0 && !ctx.reduceMotion()) {
24204
24253
  ensureParallaxRuntime();
24205
- const inner = renderNode({ ...node, modifiers: { ...modifiers, parallax: void 0 } }, ctx);
24206
- return /* @__PURE__ */ jsx6("div", { "data-himalaya-parallax": String(modifiers.parallax), children: inner });
24254
+ const inner = renderNode({ ...node, modifiers: { ...modifiers, parallax: void 0 } }, itemCtx);
24255
+ return /* @__PURE__ */ jsx6("div", { "data-himalaya-parallax": String(modifiers.parallax), style: rowItemHold ? rowItem : void 0, children: inner });
24207
24256
  }
24208
24257
  if (modifiers?.scrollProgress) {
24209
24258
  ensureScrollProgressRuntime();
24210
24259
  const sticky = !!modifiers.sticky;
24211
24260
  const inner = renderNode(
24212
24261
  { ...node, modifiers: { ...modifiers, scrollProgress: void 0, sticky: void 0 } },
24213
- ctx
24262
+ itemCtx
24214
24263
  );
24215
- const barStyle = { transformOrigin: "left", transform: "scaleX(0)", alignSelf: "stretch" };
24264
+ const barStyle = { transformOrigin: "left", transform: "scaleX(0)", alignSelf: "stretch", ...rowItem };
24216
24265
  if (sticky) {
24217
24266
  barStyle.position = "sticky";
24218
24267
  barStyle.top = 0;
@@ -24224,16 +24273,16 @@ function renderInner(node, ctx) {
24224
24273
  ensureVectorAnimStyles();
24225
24274
  const name = modifiers.vectorAnim;
24226
24275
  const col = C(resolveScalarStatic(modifiers.color, ctx) ?? "accentPrimary", "#116DFF");
24227
- const inner = renderNode({ ...node, modifiers: { ...modifiers, vectorAnim: void 0 } }, ctx);
24228
- return /* @__PURE__ */ jsxs3("div", { "data-himalaya-vectoranim": name, style: { position: "relative", display: "inline-flex", alignItems: "center", justifyContent: "center" }, children: [
24276
+ const inner = renderNode({ ...node, modifiers: { ...modifiers, vectorAnim: void 0 } }, itemCtx);
24277
+ return /* @__PURE__ */ jsxs3("div", { "data-himalaya-vectoranim": name, style: { position: "relative", display: "inline-flex", alignItems: "center", justifyContent: "center", ...rowItem }, children: [
24229
24278
  inner,
24230
24279
  vectorAnimSvg(name, col, 36, !ctx.reduceMotion())
24231
24280
  ] });
24232
24281
  }
24233
24282
  if (modifiers?.confetti && !ctx.reduceMotion()) {
24234
24283
  ensureConfettiRuntime();
24235
- const inner = renderNode({ ...node, modifiers: { ...modifiers, confetti: void 0 } }, ctx);
24236
- return /* @__PURE__ */ jsxs3("div", { style: { position: "relative" }, children: [
24284
+ const inner = renderNode({ ...node, modifiers: { ...modifiers, confetti: void 0 } }, itemCtx);
24285
+ return /* @__PURE__ */ jsxs3("div", { style: { position: "relative", ...rowItem }, children: [
24237
24286
  inner,
24238
24287
  /* @__PURE__ */ jsx6("div", { "data-himalaya-confetti": true, style: { position: "absolute", inset: 0, pointerEvents: "none", overflow: "hidden" } })
24239
24288
  ] });
@@ -24255,7 +24304,8 @@ function renderInner(node, ctx) {
24255
24304
  const hasW = modifiers?.width != null || modifiers?.fillMaxWidth === true;
24256
24305
  const hasH = modifiers?.height != null;
24257
24306
  const justifyItems = zJustifyItems(props.alignment);
24258
- return /* @__PURE__ */ jsx6("div", { style: { position: "relative", display: "grid", justifyItems, alignItems: "center", ...hasW ? {} : { width: "100%" }, ...hasH ? {} : { minHeight: 40 }, ...wrap }, children: (props.children ?? []).map((c, i) => /* @__PURE__ */ jsx6("div", { style: { gridArea: "1 / 1", display: "grid", justifyItems, alignItems: "center", width: "100%" }, children: renderNode(c, ctx) }, c?.id ?? i)) });
24307
+ const fillsWidth = !hasW && !hListItem;
24308
+ return /* @__PURE__ */ jsx6("div", { style: { position: "relative", display: "grid", justifyItems, alignItems: "center", ...fillsWidth ? { width: "100%" } : {}, ...hasH ? {} : { minHeight: 40 }, ...wrap }, children: (props.children ?? []).map((c, i) => /* @__PURE__ */ jsx6("div", { style: { gridArea: "1 / 1", display: "grid", justifyItems, alignItems: "center", width: "100%" }, children: renderNode(c, ctx) }, c?.id ?? i)) });
24259
24309
  }
24260
24310
  case "LazyList": {
24261
24311
  const itemsPath = props.itemsPath ?? props.items_path;
@@ -24281,6 +24331,7 @@ function renderInner(node, ctx) {
24281
24331
  };
24282
24332
  if (props.horizontal) ensureHListStyles();
24283
24333
  const hListAttr = props.horizontal ? { "data-himalaya-hlist": "1" } : {};
24334
+ const asItem = (c) => props.horizontal ? { ...c, hListItem: true } : c;
24284
24335
  if (itemsPath && items[0] && ctx.provider) {
24285
24336
  const boundSwipe = props.rowSwipeActions ?? props.row_swipe_actions;
24286
24337
  const boundRefresh = props.onPullToRefresh ?? props.on_pull_to_refresh;
@@ -24293,7 +24344,7 @@ function renderInner(node, ctx) {
24293
24344
  itemsPath,
24294
24345
  template: items[0],
24295
24346
  renderRow: (t, ic) => {
24296
- let row = renderNode(t, ic);
24347
+ let row = renderNode(t, asItem(ic));
24297
24348
  if (boundStagger > 0 && React5.isValidElement(row)) {
24298
24349
  const i = Number(ic.itemScope?.__index ?? 0);
24299
24350
  const prev = row.props.style ?? {};
@@ -24350,7 +24401,7 @@ function renderInner(node, ctx) {
24350
24401
  if (animateItems) ensureListAnimateRuntime();
24351
24402
  const stickyHeader = props.stickyHeader ?? props.sticky_header;
24352
24403
  const stickyEl = stickyHeader && !props.horizontal ? /* @__PURE__ */ jsx6("div", { style: { position: "sticky", top: 0, zIndex: 2, background: C("surfacePrimary", "#fff") }, children: renderNode(stickyHeader, ctx) }) : null;
24353
- const rendered = staggerMs > 0 ? staggeredKids(items, ctx, staggerMs) : kids(items, ctx);
24404
+ const rendered = staggerMs > 0 ? staggeredKids(items, asItem(ctx), staggerMs) : kids(items, asItem(ctx));
24354
24405
  let body = rendered;
24355
24406
  if (swipe && ctx.onAction && !props.horizontal) {
24356
24407
  const leading = swipe.leading ?? [];
@@ -24422,7 +24473,7 @@ function renderInner(node, ctx) {
24422
24473
  return /* @__PURE__ */ jsxs3("div", { style: { textAlign: "center", width: "100%", padding: 12, boxSizing: "border-box", ...wrap }, children: [
24423
24474
  /* @__PURE__ */ jsx6("div", { style: { width: 46, height: 46, borderRadius: 13, background: C("surfaceTertiary", "#eee"), display: "grid", placeItems: "center", margin: "0 auto 12px", color: C("textSecondary", "#9aa2ad") }, children: iconSvg(props.icon, { size: 24 }) }),
24424
24475
  /* @__PURE__ */ jsx6("div", { style: { fontFamily: bodyFont(ctx), fontWeight: 600, fontSize: 16, color: C("textPrimary", "#111") }, children: asBoundText(props.title, ctx) || "Empty" }),
24425
- props.subtitle && /* @__PURE__ */ jsx6("div", { style: { fontSize: 13, color: C("textSecondary", "#888"), marginTop: 3 }, children: txt(props.subtitle, ctx) }),
24476
+ props.subtitle && /* @__PURE__ */ jsx6("div", { style: { fontFamily: bodyFont(ctx), fontSize: 13, color: C("textSecondary", "#888"), marginTop: 3 }, children: txt(props.subtitle, ctx) }),
24426
24477
  actionTextButton(ctx, props.action, asBoundText(props.actionLabel, ctx) || "Take action", C("accentPrimary", "#116DFF"), { margin: "12px auto 0", textAlign: "center" })
24427
24478
  ] });
24428
24479
  // ───────────── atoms ─────────────
@@ -24767,7 +24818,7 @@ function renderInner(node, ctx) {
24767
24818
  /* @__PURE__ */ jsx6("div", { style: { width: 3, borderRadius: 3, background: accent, flex: "none" } }),
24768
24819
  /* @__PURE__ */ jsxs3("div", { children: [
24769
24820
  /* @__PURE__ */ jsx6("div", { style: { fontFamily: bodyFont(ctx), fontWeight: 600, fontSize: 14, color: C("textPrimary", "#111") }, children: txt(props.title, ctx) }),
24770
- props.message && /* @__PURE__ */ jsx6("div", { style: { fontSize: 13, lineHeight: 1.4, color: C("textSecondary", "#666"), marginTop: 2 }, children: txt(props.message, ctx) }),
24821
+ props.message && /* @__PURE__ */ jsx6("div", { style: { fontFamily: bodyFont(ctx), fontSize: 13, lineHeight: 1.4, color: C("textSecondary", "#666"), marginTop: 2 }, children: txt(props.message, ctx) }),
24771
24822
  actionTextButton(ctx, props.action, asBoundText(props.actionLabel, ctx) || "Take action", C("textPrimary", "#111"), { marginTop: 7, textDecoration: "underline" })
24772
24823
  ] })
24773
24824
  ] });
@@ -24783,7 +24834,7 @@ function renderInner(node, ctx) {
24783
24834
  case "AlertDialog":
24784
24835
  return /* @__PURE__ */ jsxs3("div", { role: "alertdialog", "aria-modal": "true", "aria-label": props.title != null ? asBoundText(props.title, ctx) : "Alert", style: { background: C("surfacePrimary", "#fff"), borderRadius: ctx.radius("lg", 14), padding: 18, width: "100%", boxSizing: "border-box", border: `1px solid ${C("border", "#e3e3e3")}`, boxShadow: "0 12px 30px -12px rgba(0,0,0,.4)", ...wrap }, children: [
24785
24836
  /* @__PURE__ */ jsx6("div", { style: { fontFamily: bodyFont(ctx), fontWeight: 700, fontSize: 17, color: C("textPrimary", "#111") }, children: txt(props.title, ctx) }),
24786
- /* @__PURE__ */ jsx6("div", { style: { fontSize: 14, lineHeight: 1.45, color: C("textSecondary", "#666"), margin: "6px 0 16px" }, children: txt(props.message, ctx) }),
24837
+ /* @__PURE__ */ jsx6("div", { style: { fontFamily: bodyFont(ctx), fontSize: 14, lineHeight: 1.45, color: C("textSecondary", "#666"), margin: "6px 0 16px" }, children: txt(props.message, ctx) }),
24787
24838
  /* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: 10 }, children: [
24788
24839
  props.cancelAction != null && /* @__PURE__ */ jsx6("button", { type: "button", onClick: actionClick(ctx, props.cancelAction), style: { flex: 1, textAlign: "center", padding: 11, borderRadius: ctx.radius("md", 8), appearance: "none", WebkitAppearance: "none", border: "none", fontFamily: bodyFont(ctx), fontWeight: 600, fontSize: 15, background: C("surfaceTertiary", "#eee"), color: C("textPrimary", "#111"), cursor: ctx.onAction ? "pointer" : "default" }, children: asBoundText(props.cancelLabel, ctx) || "Cancel" }),
24789
24840
  props.confirmAction != null && /* @__PURE__ */ jsx6("button", { type: "button", onClick: actionClick(ctx, props.confirmAction), style: { flex: 1, textAlign: "center", padding: 11, borderRadius: ctx.radius("md", 8), appearance: "none", WebkitAppearance: "none", border: "none", fontFamily: bodyFont(ctx), fontWeight: 600, fontSize: 15, background: props.destructive ? C("danger", "#E62214") : C("accentPrimary", "#116DFF"), color: "#fff", cursor: ctx.onAction ? "pointer" : "default" }, children: asBoundText(props.confirmLabel, ctx) || (props.destructive ? "Delete" : "Confirm") })
@@ -24804,7 +24855,7 @@ function renderInner(node, ctx) {
24804
24855
  }
24805
24856
  }
24806
24857
  }
24807
- var useIsomorphicLayoutEffect, ResponsiveGrid, SPLIT_EXPANDED_MIN_WIDTH, SPLIT_COLUMN_GAP, ResponsiveSplitView, ABSOLUTE_URL_RE, appearKeyframesInjected, pressStylesInjected, FOCUS_RING_CSS, focusStylesInjected, hListStylesInjected, listAnimateRuntimeInstalled, transitionKeyframesInjected, countUpRuntimeInjected, MEASURE_PREFIX, measureRuntimeInjected, revealRuntimeInjected, vectorAnimStylesInjected, scrollProgressRuntimeInjected, confettiRuntimeInjected, lottieRuntimeInjected, riveRuntimeInjected, gradientKeyframesInjected, parallaxRuntimeInjected, spinKeyframesInjected, marqueeKeyframesInjected, alignItems, zJustifyItems, hAlignItems, bodyFont, kids, rowKids, staggeredKids, asTextL10n, asBoundText, useBoundString, InterpolatedTextView, txt, selectFragmentCase, fragmentValueHash, fragmentSlotContent, FragmentSlotNode, WorkerSubtreeNode, resolveItemDeep2, resolveSwipeActions, resolveModBindings, resolvedComponentId, directServiceBindings, ReactiveDirectScalars, HiddenGate, KEYBOARD_INPUT_MODES, AUTOCAPITALIZE_VALUES, ENTER_KEY_HINTS, AUTOGROW_CEILING, EditableField, MenuNode, LoadMoreSentinel, FieldErrorNode, FormView, MediaSlotProvider, MEDIA_ITEM_BINDABLE, MediaPlayerView, VideoNode, PdfViewNode, WebViewNode, InteractivePicker, InteractiveDatePicker, InteractiveSearchField, InteractiveStepper, INTERACTIVE_ROLES, ALWAYS_INTERACTIVE_COMPONENT_TYPES, controlNode, ToggleNode, SliderNode, SelectionControlNode, TabsNode, SegmentedControlNode, DisclosureGroupNode, GridNode, SplitViewNode, TextNode, ImageNode, AvatarNode, IconNode, ButtonNode, OtpInputNode, ProgressBarNode, ActivityIndicatorNode, BottomSheetNode, ChipsInputNode, ChipNode, TableNode, GaugeRing, GaugeNode, RatingNode, AvatarStripNode, CHART_STROKE_CYCLE, chartStrokeAt, chartBarCenter, ChartNode, donutSliceOpacity, DonutChartNode, LegendMarker, LegendNode, cellAlign, DataTableNode, voiceNoteState, voiceNoteDelivery, VOICE_NOTE_DEFAULT_BARS, clampBarCount, VoiceNoteNode, TimelineNode, WheelPickerNode, ColorPickerNode, FilterChipsNode, TILE_PX, MAX_MERCATOR_LAT, DEFAULT_TILE_MAX_ZOOM, CIRCLE_SEGMENTS, METRES_PER_DEG_LAT, MARKER_HIT_RADIUS, SHAPE_HIT_RADIUS, MapNode, CollapsingHeaderNode, UnsupportedOnSurface, CALENDAR_DATE_ONLY_RE, CAL_DEFAULT_MAX_DOTS, CAL_AGENDA_INITIAL_DAYS, CAL_AGENDA_PAGE_DAYS, CAL_DEFAULT_SNAP_MINUTES, CAL_UNASSIGNED_LANE_ID, MonthCalendarNode, TimeGridNode, AgendaNode, WebRenderer;
24858
+ var useIsomorphicLayoutEffect, ResponsiveGrid, SPLIT_EXPANDED_MIN_WIDTH, SPLIT_COLUMN_GAP, ResponsiveSplitView, ABSOLUTE_URL_RE, appearKeyframesInjected, pressStylesInjected, FOCUS_RING_CSS, focusStylesInjected, HLIST_CHILD_CSS, hListStylesInjected, listAnimateRuntimeInstalled, transitionKeyframesInjected, countUpRuntimeInjected, MEASURE_PREFIX, measureRuntimeInjected, revealRuntimeInjected, vectorAnimStylesInjected, scrollProgressRuntimeInjected, confettiRuntimeInjected, lottieRuntimeInjected, riveRuntimeInjected, gradientKeyframesInjected, parallaxRuntimeInjected, spinKeyframesInjected, marqueeKeyframesInjected, alignItems, zJustifyItems, hAlignItems, bodyFont, kids, rowKids, staggeredKids, asTextL10n, asBoundText, useBoundString, InterpolatedTextView, txt, selectFragmentCase, fragmentValueHash, fragmentSlotContent, FragmentSlotNode, WorkerSubtreeNode, resolveItemDeep2, resolveSwipeActions, resolveModBindings, resolvedComponentId, directServiceBindings, ReactiveDirectScalars, HiddenGate, KEYBOARD_INPUT_MODES, AUTOCAPITALIZE_VALUES, ENTER_KEY_HINTS, AUTOGROW_CEILING, EditableField, MenuNode, LoadMoreSentinel, FieldErrorNode, FormView, MediaSlotProvider, MEDIA_ITEM_BINDABLE, MediaPlayerView, VideoNode, PdfViewNode, WebViewNode, InteractivePicker, InteractiveDatePicker, InteractiveSearchField, InteractiveStepper, INTERACTIVE_ROLES, ALWAYS_INTERACTIVE_COMPONENT_TYPES, controlNode, ToggleNode, SliderNode, SelectionControlNode, TabsNode, SegmentedControlNode, DisclosureGroupNode, GridNode, SplitViewNode, TextNode, ImageNode, AvatarNode, IconNode, ButtonNode, OtpInputNode, ProgressBarNode, ActivityIndicatorNode, BottomSheetNode, ChipsInputNode, ChipNode, TableNode, GaugeRing, GaugeNode, RatingNode, AvatarStripNode, CHART_STROKE_CYCLE, chartStrokeAt, chartBarCenter, ChartNode, donutSliceOpacity, DonutChartNode, LegendMarker, LegendNode, cellAlign, DataTableNode, voiceNoteState, voiceNoteDelivery, VOICE_NOTE_DEFAULT_BARS, clampBarCount, VoiceNoteNode, TimelineNode, WheelPickerNode, ColorPickerNode, FilterChipsNode, TILE_PX, MAX_MERCATOR_LAT, DEFAULT_TILE_MAX_ZOOM, CIRCLE_SEGMENTS, METRES_PER_DEG_LAT, MARKER_HIT_RADIUS, SHAPE_HIT_RADIUS, MapNode, CollapsingHeaderNode, UnsupportedOnSurface, CALENDAR_DATE_ONLY_RE, CAL_DEFAULT_MAX_DOTS, CAL_AGENDA_INITIAL_DAYS, CAL_AGENDA_PAGE_DAYS, CAL_DEFAULT_SNAP_MINUTES, CAL_UNASSIGNED_LANE_ID, MonthCalendarNode, TimeGridNode, AgendaNode, WebRenderer;
24808
24859
  var init_renderNode = __esm({
24809
24860
  "../../core/web-renderer/src/renderNode.tsx"() {
24810
24861
  "use strict";
@@ -24890,6 +24941,7 @@ var init_renderNode = __esm({
24890
24941
  pressStylesInjected = false;
24891
24942
  FOCUS_RING_CSS = ':where(button,a,[href],input,select,textarea,[role="button"],[tabindex]):focus-visible{outline:2px solid var(--himi-accent,#116DFF);outline-offset:2px;border-radius:4px}';
24892
24943
  focusStylesInjected = false;
24944
+ HLIST_CHILD_CSS = "[data-himalaya-hlist]>*{flex:0 0 auto}";
24893
24945
  hListStylesInjected = false;
24894
24946
  listAnimateRuntimeInstalled = false;
24895
24947
  transitionKeyframesInjected = false;
@@ -28279,13 +28331,16 @@ var init_src3 = __esm({
28279
28331
  // ../../core/dev-server/src/render-descriptor.ts
28280
28332
  var render_descriptor_exports = {};
28281
28333
  __export(render_descriptor_exports, {
28334
+ HOST_PAGE_FONT: () => HOST_PAGE_FONT,
28282
28335
  buildRenderTree: () => buildRenderTree,
28283
28336
  clientEnvFor: () => clientEnvFor,
28284
28337
  collectNativeOnly: () => collectNativeOnly,
28285
28338
  isMissingPlaywrightExecutable: () => isMissingPlaywrightExecutable,
28286
28339
  pngAvailable: () => pngAvailable,
28340
+ pngPageHtml: () => pngPageHtml,
28287
28341
  renderDescriptorWeb: () => renderDescriptorWeb,
28288
28342
  renderPngBatch: () => renderPngBatch,
28343
+ setPngFontCss: () => setPngFontCss,
28289
28344
  stabilizePngPage: () => stabilizePngPage,
28290
28345
  withRetry: () => withRetry2
28291
28346
  });
@@ -28518,7 +28573,7 @@ async function renderDescriptorWeb(descriptor, tokens, scheme, wantPng, services
28518
28573
  const nativeOnly = collectNativeOnly(renderTree);
28519
28574
  if (nativeOnly.length) result.nativeOnly = nativeOnly;
28520
28575
  if (wantPng) {
28521
- const png = await renderPng(html, scheme, width, isRTL);
28576
+ const png = await renderPng(html, scheme, width, isRTL, tokens);
28522
28577
  if (png) result.pngBase64 = png;
28523
28578
  else result.pngUnavailable = true;
28524
28579
  }
@@ -28535,10 +28590,24 @@ async function withRetry2(op, attempts = 2) {
28535
28590
  }
28536
28591
  throw lastErr;
28537
28592
  }
28538
- async function renderPng(html, scheme, width, isRTL) {
28539
- const out = await renderPngBatch([{ html, scheme, width, isRTL }]);
28593
+ async function renderPng(html, scheme, width, isRTL, tokens) {
28594
+ const out = await renderPngBatch([{ html, scheme, width, isRTL, tokens }]);
28540
28595
  return out?.[0] ?? null;
28541
28596
  }
28597
+ function setPngFontCss(source) {
28598
+ const previous = pngFontCss;
28599
+ pngFontCss = source;
28600
+ return previous;
28601
+ }
28602
+ async function pngPageHtml(item) {
28603
+ let faces = "";
28604
+ try {
28605
+ faces = await pngFontCss?.(item.tokens ?? null) ?? "";
28606
+ } catch {
28607
+ faces = "";
28608
+ }
28609
+ return `<!doctype html><html${item.isRTL ? ' dir="rtl"' : ""}><head><meta charset="utf-8"><style>${faces}body{font-family:${HOST_PAGE_FONT}}</style></head><body style="margin:0">${item.html}</body></html>`;
28610
+ }
28542
28611
  function isMissingPlaywrightExecutable(error) {
28543
28612
  const message = error?.message ?? "";
28544
28613
  return /Executable doesn't exist at/.test(message) && /playwright install/.test(message);
@@ -28598,10 +28667,7 @@ async function renderPngBatch(items) {
28598
28667
  try {
28599
28668
  const page = await browser.newPage({ colorScheme: it.scheme, ...it.width && it.width > 0 ? { viewport: { width: Math.round(it.width), height: 900 } } : {} });
28600
28669
  try {
28601
- await page.setContent(
28602
- `<!doctype html><html${it.isRTL ? ' dir="rtl"' : ""}><head><meta charset="utf-8"></head><body style="margin:0">${it.html}</body></html>`,
28603
- { waitUntil: "load" }
28604
- );
28670
+ await page.setContent(await pngPageHtml(it), { waitUntil: "load" });
28605
28671
  await stabilizePngPage(page, it.scheme);
28606
28672
  const buf = await page.screenshot({ fullPage: true });
28607
28673
  out.push(Buffer.from(buf).toString("base64"));
@@ -28619,7 +28685,7 @@ async function renderPngBatch(items) {
28619
28685
  });
28620
28686
  }
28621
28687
  }
28622
- var TREE_TEXT_VALUE_PROPS, asStringOrNumber, asStringOnly, asOtpCode, VALUE_PATH_TEXT, MEDIA_PLAYER_QUEUE_PROPERTIES, NATIVE_ONLY_TYPES;
28688
+ var TREE_TEXT_VALUE_PROPS, asStringOrNumber, asStringOnly, asOtpCode, VALUE_PATH_TEXT, MEDIA_PLAYER_QUEUE_PROPERTIES, NATIVE_ONLY_TYPES, HOST_PAGE_FONT, pngFontCss;
28623
28689
  var init_render_descriptor = __esm({
28624
28690
  "../../core/dev-server/src/render-descriptor.ts"() {
28625
28691
  init_FakeServiceProvider();
@@ -28642,6 +28708,111 @@ var init_render_descriptor = __esm({
28642
28708
  ]);
28643
28709
  MEDIA_PLAYER_QUEUE_PROPERTIES = /* @__PURE__ */ new Set(["items", "itemsPath", "items_path"]);
28644
28710
  NATIVE_ONLY_TYPES = /* @__PURE__ */ new Set(["Map", "Video", "Lottie", "Rive", "WebView"]);
28711
+ HOST_PAGE_FONT = '"Wix Madefor Text", system-ui, sans-serif';
28712
+ }
28713
+ });
28714
+
28715
+ // ../../core/dev-server/src/render-fonts.ts
28716
+ import { existsSync as existsSync34, readFileSync as readFileSync34 } from "node:fs";
28717
+ import { extname, join as join31 } from "node:path";
28718
+ function servedFontFaces(appDir2, tokens) {
28719
+ try {
28720
+ const policyPath = join31(appDir2, "fonts.json");
28721
+ const policy = existsSync34(policyPath) ? JSON.parse(readFileSync34(policyPath, "utf8")) : {};
28722
+ let plan = planFonts(tokens, policy);
28723
+ if (!hasVendoredFloor()) plan = { ...plan, families: plan.families.filter((f) => !isHostProvided(f.name)) };
28724
+ if (plan.families.length === 0) return void 0;
28725
+ return servedProjection(plan);
28726
+ } catch {
28727
+ return void 0;
28728
+ }
28729
+ }
28730
+ function withServedFontFaces(tokens, appDir2) {
28731
+ const fontFaces = servedFontFaces(appDir2, tokens);
28732
+ return fontFaces ? { ...tokens, fontFaces } : tokens;
28733
+ }
28734
+ function declaredFamilies(tokens) {
28735
+ const decl = tokens?.fontFaces;
28736
+ return decl && typeof decl === "object" && !Array.isArray(decl) ? Object.keys(decl) : [];
28737
+ }
28738
+ async function faceBytes(face, catalog, opts) {
28739
+ try {
28740
+ if (opts.source) {
28741
+ const path = opts.source(face.file, face.sha256);
28742
+ return path ? readFileSync34(path) : null;
28743
+ }
28744
+ const bytes2 = await catalogFaceBytes(face.sha256, { catalog, ...opts.fetchFace ? { fetchFace: opts.fetchFace } : {} });
28745
+ return bytes2 ?? null;
28746
+ } catch {
28747
+ return null;
28748
+ }
28749
+ }
28750
+ async function pngFontFaceCss(tokens, opts = {}) {
28751
+ const cache = opts.source || opts.fetchFace ? void 0 : encoded;
28752
+ let catalog;
28753
+ try {
28754
+ catalog = opts.catalog ?? loadCatalog();
28755
+ } catch {
28756
+ return "";
28757
+ }
28758
+ const wanted = [];
28759
+ const seen = /* @__PURE__ */ new Set();
28760
+ const want = (family, face, variable) => {
28761
+ const key2 = `${family}\0${face.sha256}`;
28762
+ if (seen.has(key2)) return;
28763
+ seen.add(key2);
28764
+ wanted.push({ family, face, variable });
28765
+ };
28766
+ for (const [name, family] of Object.entries(catalog.bundled)) {
28767
+ for (const face of family.faces) want(name, face, family.variable);
28768
+ }
28769
+ let planned = [];
28770
+ try {
28771
+ planned = planFonts(tokens ?? {}, { families: declaredFamilies(tokens) }, catalog).families;
28772
+ } catch {
28773
+ planned = [];
28774
+ }
28775
+ for (const family of planned) {
28776
+ if (family.builtin) continue;
28777
+ for (const face of family.faces) want(family.name, face, family.variable);
28778
+ }
28779
+ const data = await Promise.all(
28780
+ wanted.map(async ({ face }) => {
28781
+ const hit = cache?.get(face.sha256);
28782
+ if (hit !== void 0) return hit;
28783
+ const bytes2 = await faceBytes(face, catalog, opts);
28784
+ if (!bytes2) return null;
28785
+ const b64 = bytes2.toString("base64");
28786
+ cache?.set(face.sha256, b64);
28787
+ return b64;
28788
+ })
28789
+ );
28790
+ const rules = [];
28791
+ wanted.forEach(({ family, face, variable }, i) => {
28792
+ const b64 = data[i];
28793
+ if (b64 == null) return;
28794
+ const [mime, format] = FORMATS[extname(face.file).toLowerCase()] ?? ["font/ttf", "truetype"];
28795
+ const wght = variable?.axes?.["wght"];
28796
+ const weight = wght ? `${wght.min} ${wght.max}` : String(face.weight);
28797
+ rules.push(
28798
+ `@font-face{font-family:${cssString(family)};font-weight:${weight};font-style:${face.style ?? "normal"};font-display:block;src:url(data:${mime};base64,${b64}) format("${format}")}`
28799
+ );
28800
+ });
28801
+ return rules.join("");
28802
+ }
28803
+ var encoded, cssString, FORMATS;
28804
+ var init_render_fonts = __esm({
28805
+ "../../core/dev-server/src/render-fonts.ts"() {
28806
+ init_catalog();
28807
+ init_plan_fonts();
28808
+ init_face_source();
28809
+ encoded = /* @__PURE__ */ new Map();
28810
+ cssString = (s) => `"${s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/</g, "\\3c ").replace(/\n/g, "\\a ")}"`;
28811
+ FORMATS = {
28812
+ ".woff2": ["font/woff2", "woff2"],
28813
+ ".woff": ["font/woff", "woff"],
28814
+ ".otf": ["font/otf", "opentype"]
28815
+ };
28645
28816
  }
28646
28817
  });
28647
28818
 
@@ -29518,7 +29689,7 @@ var init_src5 = __esm({
29518
29689
  });
29519
29690
 
29520
29691
  // ../../core/dev-server/src/flags/index.ts
29521
- import { readFileSync as readFileSync34 } from "node:fs";
29692
+ import { readFileSync as readFileSync35 } from "node:fs";
29522
29693
  import { resolve as resolve26 } from "node:path";
29523
29694
  function selectProvider(config, store) {
29524
29695
  const local = new LocalFlagProvider(store, () => config?.overrides);
@@ -29614,7 +29785,7 @@ var init_flags2 = __esm({
29614
29785
  if (now - this.lastFetch < this.ttlMs) return;
29615
29786
  this.lastFetch = now;
29616
29787
  try {
29617
- const defs = JSON.parse(readFileSync34(resolve26(appDir2, "flags.json"), "utf8"));
29788
+ const defs = JSON.parse(readFileSync35(resolve26(appDir2, "flags.json"), "utf8"));
29618
29789
  if (Array.isArray(defs) && defs.length > 0) store.replaceAll(defs);
29619
29790
  } catch {
29620
29791
  }
@@ -29664,19 +29835,19 @@ var init_motion_flags = __esm({
29664
29835
  });
29665
29836
 
29666
29837
  // ../../core/dev-server/src/kits.ts
29667
- import { readdirSync as readdirSync17, readFileSync as readFileSync35 } from "node:fs";
29668
- import { resolve as resolve27, join as join31 } from "node:path";
29838
+ import { readdirSync as readdirSync17, readFileSync as readFileSync36 } from "node:fs";
29839
+ import { resolve as resolve27, join as join32 } from "node:path";
29669
29840
  import { fileURLToPath as fileURLToPath16 } from "node:url";
29670
29841
  function listKits() {
29671
29842
  return readdirSync17(CATALOG).filter((f) => f.endsWith(".json")).map((f) => {
29672
- const { tokens, ...meta } = JSON.parse(readFileSync35(join31(CATALOG, f), "utf8"));
29843
+ const { tokens, ...meta } = JSON.parse(readFileSync36(join32(CATALOG, f), "utf8"));
29673
29844
  return meta;
29674
29845
  });
29675
29846
  }
29676
29847
  function readKit(id) {
29677
29848
  if (!/^[a-z0-9-]+$/.test(id)) return null;
29678
29849
  try {
29679
- return JSON.parse(readFileSync35(join31(CATALOG, `${id}.json`), "utf8"));
29850
+ return JSON.parse(readFileSync36(join32(CATALOG, `${id}.json`), "utf8"));
29680
29851
  } catch {
29681
29852
  return null;
29682
29853
  }
@@ -29685,7 +29856,7 @@ var ROOT5, CATALOG;
29685
29856
  var init_kits = __esm({
29686
29857
  "../../core/dev-server/src/kits.ts"() {
29687
29858
  ROOT5 = resolve27(fileURLToPath16(new URL("../../..", import.meta.url)));
29688
- CATALOG = join31(ROOT5, "stdlib/design-kits");
29859
+ CATALOG = join32(ROOT5, "stdlib/design-kits");
29689
29860
  }
29690
29861
  });
29691
29862
 
@@ -30414,8 +30585,10 @@ __export(validate_descriptor_exports, {
30414
30585
  nativeRequiredFindings: () => nativeRequiredFindings,
30415
30586
  navLogicBundleUrl: () => navLogicBundleUrl,
30416
30587
  nodeVmEvaluator: () => nodeVmEvaluator,
30588
+ nondeterministicServices: () => nondeterministicServices,
30417
30589
  pathCrossesOpaqueAuthorJson: () => pathCrossesOpaqueAuthorJson,
30418
30590
  pathValue: () => pathValue,
30591
+ pinnedIntrinsicsSource: () => pinnedIntrinsicsSource,
30419
30592
  readBuiltBundle: () => readBuiltBundle,
30420
30593
  readBuiltBundleMap: () => readBuiltBundleMap,
30421
30594
  resolveActionEvaluator: () => resolveActionEvaluator,
@@ -30428,12 +30601,12 @@ __export(validate_descriptor_exports, {
30428
30601
  validateScreenDescriptor: () => validateScreenDescriptor,
30429
30602
  workerSubtreeAllowed: () => workerSubtreeAllowed
30430
30603
  });
30431
- import { readFileSync as readFileSync36, existsSync as existsSync34, readdirSync as readdirSync18 } from "node:fs";
30604
+ import { readFileSync as readFileSync37, existsSync as existsSync35, readdirSync as readdirSync18 } from "node:fs";
30432
30605
  import { resolve as resolve28 } from "node:path";
30433
- import { runInNewContext } from "node:vm";
30606
+ import { createContext, runInContext } from "node:vm";
30434
30607
  async function loadAllowedComponents(appDir2) {
30435
30608
  const modPath = resolve28(appDir2, "components.ts");
30436
- if (!existsSync34(modPath)) return void 0;
30609
+ if (!existsSync35(modPath)) return void 0;
30437
30610
  try {
30438
30611
  const { pathToFileURL: pathToFileURL8 } = await import("node:url");
30439
30612
  const mod = await import(pathToFileURL8(modPath).href);
@@ -30446,7 +30619,7 @@ async function loadAllowedComponents(appDir2) {
30446
30619
  }
30447
30620
  function readBuiltBundle(tier5Root, bundleName) {
30448
30621
  const p = resolve28(tier5Root, `${bundleName}.bundle.js`);
30449
- return existsSync34(p) ? readFileSync36(p, "utf8") : void 0;
30622
+ return existsSync35(p) ? readFileSync37(p, "utf8") : void 0;
30450
30623
  }
30451
30624
  function bundleNameFromUrl(url) {
30452
30625
  if (typeof url !== "string") return null;
@@ -30474,10 +30647,10 @@ function appWorkerActionsFor(config, tier5Root) {
30474
30647
  }
30475
30648
  function readBuiltBundleMap(tier5Root, bundleName) {
30476
30649
  const p = resolve28(tier5Root, `${bundleName}.bundle.js.map`);
30477
- return existsSync34(p) ? readFileSync36(p, "utf8") : void 0;
30650
+ return existsSync35(p) ? readFileSync37(p, "utf8") : void 0;
30478
30651
  }
30479
30652
  function nativeSourceFiles(directory, extension, buildDirMaxDepth, depth = 1) {
30480
- if (!existsSync34(directory)) return [];
30653
+ if (!existsSync35(directory)) return [];
30481
30654
  let entries;
30482
30655
  try {
30483
30656
  entries = readdirSync18(directory, { withFileTypes: true });
@@ -30497,12 +30670,12 @@ function registeredActions(source) {
30497
30670
  return [...source.matchAll(/ActionDispatcher(?:\.shared)?\s*\.\s*register\s*\(\s*"([A-Za-z0-9_.]+)"/g)].map((match) => match[1]);
30498
30671
  }
30499
30672
  function discoverNativeActions(appDir2) {
30500
- const roots = NATIVE_SOURCE_ROOTS.filter(({ directory }) => existsSync34(resolve28(appDir2, directory)));
30673
+ const roots = NATIVE_SOURCE_ROOTS.filter(({ directory }) => existsSync35(resolve28(appDir2, directory)));
30501
30674
  const sources = roots.flatMap(({ directory, extension, buildDirMaxDepth }) => nativeSourceFiles(resolve28(appDir2, directory), extension, buildDirMaxDepth));
30502
30675
  const registered = sources.flatMap((source) => {
30503
30676
  let text4;
30504
30677
  try {
30505
- text4 = readFileSync36(source, "utf8");
30678
+ text4 = readFileSync37(source, "utf8");
30506
30679
  } catch (err) {
30507
30680
  if (!vanished(err)) throw err;
30508
30681
  return [];
@@ -30521,7 +30694,14 @@ var init_validate_descriptor = __esm({
30521
30694
  init_validate_descriptor_core();
30522
30695
  nodeVmEvaluator = {
30523
30696
  run(code, sandbox, opts) {
30524
- runInNewContext(code, sandbox, { timeout: opts.timeoutMs, filename: opts.filename });
30697
+ const context = createContext(sandbox);
30698
+ const pins = pinnedIntrinsicsSource(opts);
30699
+ if (pins) {
30700
+ const pinned = runInContext(`(${pins})(Date, Math)`, context, { timeout: opts.timeoutMs, filename: "himi-pins.js" });
30701
+ if (pinned.Date) sandbox.Date = pinned.Date;
30702
+ if (pinned.Math) sandbox.Math = pinned.Math;
30703
+ }
30704
+ runInContext(code, context, { timeout: opts.timeoutMs, filename: opts.filename });
30525
30705
  }
30526
30706
  };
30527
30707
  setDefaultEvaluator(nodeVmEvaluator);
@@ -30619,8 +30799,8 @@ __export(config_exports2, {
30619
30799
  serializeRolloutYaml: () => serializeRolloutYaml,
30620
30800
  validateOverlayPatch: () => validateOverlayPatch
30621
30801
  });
30622
- import { mkdirSync as mkdirSync15, readFileSync as readFileSync37, writeFileSync as writeFileSync12 } from "node:fs";
30623
- import { dirname as dirname20, join as join32, resolve as resolve29 } from "node:path";
30802
+ import { mkdirSync as mkdirSync15, readFileSync as readFileSync38, writeFileSync as writeFileSync12 } from "node:fs";
30803
+ import { dirname as dirname20, join as join33, resolve as resolve29 } from "node:path";
30624
30804
  import { fileURLToPath as fileURLToPath17 } from "node:url";
30625
30805
  function strip(line) {
30626
30806
  const h = line.indexOf("#");
@@ -30685,14 +30865,14 @@ function parseRevocationsYaml(text4) {
30685
30865
  function appConfigPath(app, file, root = REPO_ROOT6) {
30686
30866
  assertAppId(app, "appConfigPath");
30687
30867
  for (const base of ["apps", "test-apps"]) {
30688
- const p = join32(root, base, app, file);
30868
+ const p = join33(root, base, app, file);
30689
30869
  try {
30690
- readFileSync37(p);
30870
+ readFileSync38(p);
30691
30871
  return p;
30692
30872
  } catch {
30693
30873
  }
30694
30874
  }
30695
- return join32(root, "apps", app, file);
30875
+ return join33(root, "apps", app, file);
30696
30876
  }
30697
30877
  function serializeRolloutYaml(cfg) {
30698
30878
  const lines = [`app: ${cfg.app}`, "rings:"];
@@ -30740,7 +30920,7 @@ function validateOverlayPatch(patch) {
30740
30920
  }
30741
30921
  function readJsonAt(app, file, root) {
30742
30922
  try {
30743
- return JSON.parse(readFileSync37(appConfigPath(app, file, root), "utf8"));
30923
+ return JSON.parse(readFileSync38(appConfigPath(app, file, root), "utf8"));
30744
30924
  } catch {
30745
30925
  return null;
30746
30926
  }
@@ -30778,14 +30958,14 @@ function saveLocalFlags(app, defs, root = REPO_ROOT6) {
30778
30958
  }
30779
30959
  function loadRollout(app) {
30780
30960
  try {
30781
- return parseRolloutYaml(readFileSync37(appConfigPath(app, "rollout.yaml"), "utf8"));
30961
+ return parseRolloutYaml(readFileSync38(appConfigPath(app, "rollout.yaml"), "utf8"));
30782
30962
  } catch {
30783
30963
  return null;
30784
30964
  }
30785
30965
  }
30786
30966
  function loadRevocations(app) {
30787
30967
  try {
30788
- return parseRevocationsYaml(readFileSync37(appConfigPath(app, "revocations.yaml"), "utf8")).revoked;
30968
+ return parseRevocationsYaml(readFileSync38(appConfigPath(app, "revocations.yaml"), "utf8")).revoked;
30789
30969
  } catch {
30790
30970
  return [];
30791
30971
  }
@@ -30863,8 +31043,8 @@ var init_config2 = __esm({
30863
31043
  // ../../core/dev-server/src/index.ts
30864
31044
  import { createServer as createServer2 } from "node:http";
30865
31045
  import { readFile, stat } from "node:fs/promises";
30866
- import { readFileSync as readFileSync38, existsSync as existsSync35, watch, mkdirSync as mkdirSync16, rmSync as rmSync5 } from "node:fs";
30867
- import { extname, resolve as resolve30, normalize as normalize3, sep as sep7, join as join33 } from "node:path";
31046
+ import { readFileSync as readFileSync39, existsSync as existsSync36, watch, mkdirSync as mkdirSync16, rmSync as rmSync5 } from "node:fs";
31047
+ import { extname as extname2, resolve as resolve30, normalize as normalize3, sep as sep7 } from "node:path";
30868
31048
  import { createHash as createHash15, randomUUID } from "node:crypto";
30869
31049
  import { fileURLToPath as fileURLToPath18, pathToFileURL as pathToFileURL6 } from "node:url";
30870
31050
  function deepMerge3(base, patch) {
@@ -30914,7 +31094,7 @@ function readAppTokens(state) {
30914
31094
  if (!state.app) return null;
30915
31095
  try {
30916
31096
  const tokenPath = state.app.module.designTokensPath ?? resolve30(state.app.dir, state.app.module.config.designTokensPath ?? "tokens.json");
30917
- const parsed = JSON.parse(readFileSync38(tokenPath, "utf8"));
31097
+ const parsed = JSON.parse(readFileSync39(tokenPath, "utf8"));
30918
31098
  delete parsed._meta;
30919
31099
  return parsed;
30920
31100
  } catch {
@@ -30926,7 +31106,7 @@ function effectiveAppConfigOverride(state) {
30926
31106
  if (state.app) {
30927
31107
  try {
30928
31108
  gitOverlay = JSON.parse(
30929
- readFileSync38(resolve30(state.app.dir, "app-config.overlay.json"), "utf8")
31109
+ readFileSync39(resolve30(state.app.dir, "app-config.overlay.json"), "utf8")
30930
31110
  );
30931
31111
  } catch {
30932
31112
  }
@@ -30986,7 +31166,7 @@ function handleL10nRequest(req, res, state) {
30986
31166
  return sendJson(res, 404, { error: "unknown_app", app }, cors);
30987
31167
  }
30988
31168
  const path = resolve30(state.app.dir, "l10n", `${tag}.json`);
30989
- if (!existsSync35(path)) {
31169
+ if (!existsSync36(path)) {
30990
31170
  res.writeHead(204, cors);
30991
31171
  res.end();
30992
31172
  return;
@@ -30995,7 +31175,7 @@ function handleL10nRequest(req, res, state) {
30995
31175
  let messages;
30996
31176
  try {
30997
31177
  messages = Object.fromEntries(
30998
- keyMap(parseCatalog(readFileSync38(path, "utf8")), { sourceFallback: tag === sourceLocale })
31178
+ keyMap(parseCatalog(readFileSync39(path, "utf8")), { sourceFallback: tag === sourceLocale })
30999
31179
  );
31000
31180
  } catch {
31001
31181
  return sendJson(res, 500, { error: "catalog_unreadable", app, tag }, cors);
@@ -31040,18 +31220,6 @@ async function runScreenDiagnostics(state, screenId, descriptor) {
31040
31220
  evidence: { runId: `dev:${state.startedAt}:${screenId}`, ts: (/* @__PURE__ */ new Date()).toISOString() }
31041
31221
  });
31042
31222
  }
31043
- function servedFontFaces(appDir2, tokens) {
31044
- try {
31045
- const policyPath = join33(appDir2, "fonts.json");
31046
- const policy = existsSync35(policyPath) ? JSON.parse(readFileSync38(policyPath, "utf8")) : {};
31047
- let plan = planFonts(tokens, policy);
31048
- if (!hasVendoredFloor()) plan = { ...plan, families: plan.families.filter((f) => !isHostProvided(f.name)) };
31049
- if (plan.families.length === 0) return void 0;
31050
- return servedProjection(plan);
31051
- } catch {
31052
- return void 0;
31053
- }
31054
- }
31055
31223
  async function fontFaceBytesBySha(_appDir, sha) {
31056
31224
  try {
31057
31225
  return await catalogFaceBytes(sha);
@@ -31399,7 +31567,7 @@ async function buildDescriptorForScreenId(state, screenId, query = new URLSearch
31399
31567
  function bundleIntegritySync(name, dir) {
31400
31568
  for (const root of dir ? [dir, TIER5_ROOT2] : [TIER5_ROOT2]) {
31401
31569
  try {
31402
- const bytes2 = readFileSync38(resolve30(root, `${name}.bundle.js`));
31570
+ const bytes2 = readFileSync39(resolve30(root, `${name}.bundle.js`));
31403
31571
  return "sha256-" + createHash15("sha256").update(bytes2).digest("base64");
31404
31572
  } catch {
31405
31573
  }
@@ -32174,9 +32342,10 @@ async function handleDev(req, res, state) {
32174
32342
  }
32175
32343
  const screenId = descriptor.screenId ?? body.screenId ?? "render";
32176
32344
  const diagnostics = await runScreenDiagnostics(state, screenId, descriptor);
32345
+ const appTokens = readAppTokens(state);
32177
32346
  const render = await renderDescriptorWeb(
32178
32347
  descriptor,
32179
- readAppTokens(state),
32348
+ appTokens && state.app ? withServedFontFaces(appTokens, state.app.dir) : appTokens,
32180
32349
  scheme,
32181
32350
  body.png === true,
32182
32351
  body.services ?? null,
@@ -32980,8 +33149,8 @@ function readActionHandlerManifest(app) {
32980
33149
  let decls;
32981
33150
  let bytes2;
32982
33151
  try {
32983
- decls = JSON.parse(readFileSync38(manifestPath, "utf8"));
32984
- bytes2 = readFileSync38(bundlePath);
33152
+ decls = JSON.parse(readFileSync39(manifestPath, "utf8"));
33153
+ bytes2 = readFileSync39(bundlePath);
32985
33154
  } catch {
32986
33155
  return { handlers: [] };
32987
33156
  }
@@ -33021,7 +33190,7 @@ async function serveStatic(req, res, root, prefix) {
33021
33190
  const s = await stat(fullPath);
33022
33191
  if (s.isDirectory()) return send(res, 404, "directory");
33023
33192
  const data = await readFile(fullPath);
33024
- const ext = extname(fullPath).toLowerCase();
33193
+ const ext = extname2(fullPath).toLowerCase();
33025
33194
  res.setHeader("content-type", MIME[ext] ?? "application/octet-stream");
33026
33195
  res.setHeader("cache-control", "max-age=60");
33027
33196
  if (req.url?.startsWith("/tier4/")) {
@@ -33284,7 +33453,7 @@ function createDevServer(opts = {}) {
33284
33453
  const q = new URLSearchParams(url.split("?")[1] ?? "");
33285
33454
  const assetApp = q.get("app") ?? state.appName;
33286
33455
  const assetDir = state.app && assetApp === state.app.name ? state.app.dir : resolveAppDir(assetApp);
33287
- const hit = assetDir ? collectAssets(assetDir).find((a) => assetSha256(readFileSync38(a.path)) === sha) : void 0;
33456
+ const hit = assetDir ? collectAssets(assetDir).find((a) => assetSha256(readFileSync39(a.path)) === sha) : void 0;
33288
33457
  if (!hit && assetDir) {
33289
33458
  const fontBytes = await fontFaceBytesBySha(assetDir, sha);
33290
33459
  if (fontBytes) {
@@ -33307,7 +33476,7 @@ function createDevServer(opts = {}) {
33307
33476
  res.end(JSON.stringify({ error: "asset_not_found", app: assetApp, sha }));
33308
33477
  return;
33309
33478
  }
33310
- const bytes2 = readFileSync38(hit.path);
33479
+ const bytes2 = readFileSync39(hit.path);
33311
33480
  res.writeHead(200, {
33312
33481
  "content-type": hit.contentType,
33313
33482
  "content-length": String(bytes2.length),
@@ -33394,7 +33563,7 @@ function createDevServer(opts = {}) {
33394
33563
  if (url === "/v1/schema/screen-descriptor.json" && req.method === "GET") {
33395
33564
  try {
33396
33565
  const schemaPath = resolve30(ROOT6, "core/schema/generated/screen-descriptor.schema.json");
33397
- const body = readFileSync38(schemaPath, "utf8");
33566
+ const body = readFileSync39(schemaPath, "utf8");
33398
33567
  return send(res, 200, body, {
33399
33568
  "content-type": "application/schema+json; charset=utf-8",
33400
33569
  "cache-control": "no-store",
@@ -33428,7 +33597,7 @@ function createDevServer(opts = {}) {
33428
33597
  try {
33429
33598
  const { parseRevocationsYaml: parseRevocationsYaml2 } = await Promise.resolve().then(() => (init_config2(), config_exports2));
33430
33599
  revoked = parseRevocationsYaml2(
33431
- readFileSync38(resolve30(state.app.dir, "revocations.yaml"), "utf8")
33600
+ readFileSync39(resolve30(state.app.dir, "revocations.yaml"), "utf8")
33432
33601
  ).revoked;
33433
33602
  } catch {
33434
33603
  }
@@ -33636,7 +33805,6 @@ var ROOT6, TIER3_ROOT, TIER4_ROOT, tier4Verifier, TIER5_ROOT2, ACTION_HANDLERS_R
33636
33805
  var init_src6 = __esm({
33637
33806
  "../../core/dev-server/src/index.ts"() {
33638
33807
  init_inject();
33639
- init_plan_fonts();
33640
33808
  init_face_source();
33641
33809
  init_himi_report();
33642
33810
  init_store2();
@@ -33662,6 +33830,7 @@ var init_src6 = __esm({
33662
33830
  init_check();
33663
33831
  init_openapi();
33664
33832
  init_render_descriptor();
33833
+ init_render_fonts();
33665
33834
  init_app_config();
33666
33835
  init_tier();
33667
33836
  init_flags2();
@@ -33670,6 +33839,7 @@ var init_src6 = __esm({
33670
33839
  init_kits();
33671
33840
  init_widgets();
33672
33841
  ROOT6 = resolve30(fileURLToPath18(new URL("../../..", import.meta.url)));
33842
+ setPngFontCss((tokens) => pngFontFaceCss(tokens));
33673
33843
  TIER3_ROOT = resolve30(ROOT6, "core/dev-server/web");
33674
33844
  TIER4_ROOT = resolve30(ROOT6, "core/dev-server/tier4-bundles");
33675
33845
  tier4Verifier = new TierFourVerifier(TIER4_ROOT);
@@ -36353,7 +36523,7 @@ __export(build_exports2, {
36353
36523
  withStoreNavBundle: () => withStoreNavBundle
36354
36524
  });
36355
36525
  import { createHash as createHash18 } from "node:crypto";
36356
- import { readFileSync as readFileSync39, readdirSync as readdirSync19, existsSync as existsSync36 } from "node:fs";
36526
+ import { readFileSync as readFileSync40, readdirSync as readdirSync19, existsSync as existsSync37 } from "node:fs";
36357
36527
  import { dirname as dirname21, join as join34, resolve as resolve31 } from "node:path";
36358
36528
  import { fileURLToPath as fileURLToPath19 } from "node:url";
36359
36529
  import { createRequire as createRequire2 } from "node:module";
@@ -36393,9 +36563,9 @@ function l10nLintOptions(locale, appDir2) {
36393
36563
  const catalog = /* @__PURE__ */ new Set();
36394
36564
  for (const tag of tags) {
36395
36565
  const path = join34(appDir2, "l10n", `${tag}.json`);
36396
- if (!existsSync36(path)) continue;
36566
+ if (!existsSync37(path)) continue;
36397
36567
  try {
36398
- const parsed = JSON.parse(readFileSync39(path, "utf8"));
36568
+ const parsed = JSON.parse(readFileSync40(path, "utf8"));
36399
36569
  for (const m of Object.values(parsed.messages ?? {})) {
36400
36570
  if (typeof m?.source === "string" && typeof m.translation === "string" && m.translation.length > 0) {
36401
36571
  catalog.add(m.source);
@@ -36560,7 +36730,7 @@ function shellSha(root = REPO_ROOT7) {
36560
36730
  function isMonorepoCheckout(dir) {
36561
36731
  try {
36562
36732
  const top = execFileSync4("git", ["rev-parse", "--show-toplevel"], { cwd: dir, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
36563
- return top.length > 0 && existsSync36(join34(top, "core", "schema", "core.proto"));
36733
+ return top.length > 0 && existsSync37(join34(top, "core", "schema", "core.proto"));
36564
36734
  } catch {
36565
36735
  return false;
36566
36736
  }
@@ -36697,7 +36867,7 @@ async function buildReleaseFromContent(contentDir2, dest, opts = {}) {
36697
36867
  function readTokensForLint(preloaded) {
36698
36868
  try {
36699
36869
  const tokenPath = preloaded.module.designTokensPath ?? resolve31(preloaded.dir, preloaded.module.config.designTokensPath ?? "tokens.json");
36700
- const parsed = JSON.parse(readFileSync39(tokenPath, "utf8"));
36870
+ const parsed = JSON.parse(readFileSync40(tokenPath, "utf8"));
36701
36871
  delete parsed._meta;
36702
36872
  return parsed;
36703
36873
  } catch {
@@ -36721,6 +36891,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
36721
36891
  const baked = [];
36722
36892
  const linkable = /* @__PURE__ */ new Set();
36723
36893
  const lintTokens = collect2?.lint || collect2?.render ? readTokensForLint(preloaded) : void 0;
36894
+ const renderTokens = lintTokens && withServedFontFaces(lintTokens, preloaded.dir);
36724
36895
  const allowedComponents = await loadAllowedComponents(preloaded.dir);
36725
36896
  const nativeActions = discoverNativeActions(preloaded.dir);
36726
36897
  const appWorkerActions = appWorkerActionsFor(preloaded.module.config, tier5Dir);
@@ -36728,7 +36899,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
36728
36899
  const compareScheme = collect2?.render?.compareScheme;
36729
36900
  const renderCompare = async (descriptor, services) => {
36730
36901
  if (!compareScheme || compareScheme === renderScheme) return {};
36731
- const rr = await renderDescriptorWeb(descriptor, lintTokens, compareScheme, false, services, collect2?.render?.width, collect2?.render?.rtl === true);
36902
+ const rr = await renderDescriptorWeb(descriptor, renderTokens, compareScheme, false, services, collect2?.render?.width, collect2?.render?.rtl === true);
36732
36903
  return { compare: { scheme: compareScheme, renderable: rr.renderable, ...rr.html ? { html: rr.html } : {}, ...rr.reason ? { reason: rr.reason } : {} } };
36733
36904
  };
36734
36905
  const LIVE_LOAD_BUDGET_MS = 3e4;
@@ -36834,7 +37005,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
36834
37005
  if (addrCache.has(name)) return addrCache.get(name);
36835
37006
  let bytes2;
36836
37007
  try {
36837
- bytes2 = readFileSync39(join34(tier5Dir, `${name}.bundle.js`));
37008
+ bytes2 = readFileSync40(join34(tier5Dir, `${name}.bundle.js`));
36838
37009
  } catch {
36839
37010
  return null;
36840
37011
  }
@@ -36856,8 +37027,8 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
36856
37027
  if (store.putDoc) {
36857
37028
  for (const [name, file] of [["spec", "SPEC.md"], ["mobile-ux", "MOBILE-UX.md"]]) {
36858
37029
  const path = join34(preloaded.dir, file);
36859
- if (!existsSync36(path)) continue;
36860
- const bytes2 = readFileSync39(path);
37030
+ if (!existsSync37(path)) continue;
37031
+ const bytes2 = readFileSync40(path);
36861
37032
  if (bytes2.length === 0 || bytes2.length > MAX_AUTHORING_DOC_BYTES) {
36862
37033
  throw new Error(`${file} must be non-empty and at most ${MAX_AUTHORING_DOC_BYTES} bytes to ship with a release.`);
36863
37034
  }
@@ -36872,7 +37043,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
36872
37043
  const iconPath = resolveAppDirIcon(preloaded.dir);
36873
37044
  if (iconPath) {
36874
37045
  try {
36875
- const bytes2 = readFileSync39(iconPath);
37046
+ const bytes2 = readFileSync40(iconPath);
36876
37047
  await store.putIcon(app, bytes2);
36877
37048
  iconHash = sha2564(bytes2);
36878
37049
  } catch {
@@ -36894,7 +37065,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
36894
37065
  }
36895
37066
  const seenAssetSha = /* @__PURE__ */ new Set();
36896
37067
  for (const a of collected) {
36897
- const bytes2 = readFileSync39(a.path);
37068
+ const bytes2 = readFileSync40(a.path);
36898
37069
  const hash = sha2564(bytes2);
36899
37070
  if (!seenAssetSha.has(hash)) {
36900
37071
  await store.putAsset(app, hash, bytes2, a.contentType);
@@ -36916,7 +37087,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
36916
37087
  const fontWarnings = [];
36917
37088
  try {
36918
37089
  const appTokens = readTokensForLint(preloaded) ?? {};
36919
- const policy = existsSync36(join34(preloaded.dir, "fonts.json")) ? JSON.parse(readFileSync39(join34(preloaded.dir, "fonts.json"), "utf8")) : {};
37090
+ const policy = existsSync37(join34(preloaded.dir, "fonts.json")) ? JSON.parse(readFileSync40(join34(preloaded.dir, "fonts.json"), "utf8")) : {};
36920
37091
  fontPlan = planFonts(appTokens, policy);
36921
37092
  } catch (err) {
36922
37093
  throw new Error(
@@ -36932,7 +37103,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
36932
37103
  `[release-build] ${family.name} face ${face.postScriptName} has no local bytes (sha ${face.sha256.slice(0, 12)}\u2026), so the release would declare a face the asset route cannot serve. Run \`npm run fonts:catalog\` to warm the cache before publishing.`
36933
37104
  );
36934
37105
  }
36935
- const bytes2 = readFileSync39(src);
37106
+ const bytes2 = readFileSync40(src);
36936
37107
  const hash = sha2564(bytes2);
36937
37108
  if (hash !== face.sha256) {
36938
37109
  throw new Error(
@@ -36982,7 +37153,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
36982
37153
  if (store.putAsset) {
36983
37154
  for (const face of collectBrandFonts(preloaded.dir)) {
36984
37155
  try {
36985
- const bytes2 = readFileSync39(face.path);
37156
+ const bytes2 = readFileSync40(face.path);
36986
37157
  if (bytes2.length === 0) continue;
36987
37158
  const hash = sha2564(bytes2);
36988
37159
  await store.putAsset(app, hash, bytes2, "font/ttf");
@@ -37078,7 +37249,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
37078
37249
  }
37079
37250
  if (collect2?.render && (!collect2.render.screenId || collect2.render.screenId === screenId)) {
37080
37251
  const { services, liveCalls, liveReturned, liveErrors } = await renderServicesFor(bundleName, descriptor);
37081
- const rr = await renderDescriptorWeb(descriptor, lintTokens, renderScheme, collect2.render.png === true, services, collect2.render.width, collect2.render.rtl === true);
37252
+ const rr = await renderDescriptorWeb(descriptor, renderTokens, renderScheme, collect2.render.png === true, services, collect2.render.width, collect2.render.rtl === true);
37082
37253
  renders.push({ screenId, scheme: renderScheme, ...rr, ...await renderCompare(descriptor, services), ...collect2.render.dumpState && services ? { serviceState: services } : {}, ...liveCalls ? { liveCalls } : {}, ...liveReturned !== void 0 ? { liveReturned } : {}, ...liveErrors ? { liveErrors } : {} });
37083
37254
  }
37084
37255
  }
@@ -37105,7 +37276,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
37105
37276
  lint.push({ screenId: wantedRender, ok: report2.ok, issues: report2.issues });
37106
37277
  }
37107
37278
  const { services, liveCalls, liveReturned, liveErrors } = await renderServicesFor(bundleName, descriptor);
37108
- const rr = await renderDescriptorWeb(descriptor, lintTokens, renderScheme, collect2.render.png === true, services, collect2.render.width, collect2.render.rtl === true);
37279
+ const rr = await renderDescriptorWeb(descriptor, renderTokens, renderScheme, collect2.render.png === true, services, collect2.render.width, collect2.render.rtl === true);
37109
37280
  renders.push({ screenId: wantedRender, scheme: renderScheme, ...rr, ...await renderCompare(descriptor, services), ...collect2.render.dumpState && services ? { serviceState: services } : {}, ...liveCalls ? { liveCalls } : {}, ...liveReturned !== void 0 ? { liveReturned } : {}, ...liveErrors ? { liveErrors } : {} });
37110
37281
  }
37111
37282
  }
@@ -37365,7 +37536,12 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
37365
37536
  const js = readBuiltBundle(tier5Dir, name);
37366
37537
  if (!js) continue;
37367
37538
  const input = bundleInputs.get(name);
37368
- workers.push({ bundle: name, ...dryRunBundle(js, input ? { input } : {}) });
37539
+ const drifting = bundles[name]?.servicesHash ? nondeterministicServices(js, input ? { input } : {}) : [];
37540
+ workers.push({
37541
+ bundle: name,
37542
+ ...dryRunBundle(js, input ? { input } : {}),
37543
+ ...drifting.length ? { nondeterministicServices: drifting } : {}
37544
+ });
37369
37545
  }
37370
37546
  }
37371
37547
  return {
@@ -37387,7 +37563,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
37387
37563
  ...collect2?.lint ? { lint, workers } : {},
37388
37564
  ...collect2?.render ? { renders } : {},
37389
37565
  ...collect2?.descriptors ? { descriptors: baked, linkableScreenIds: [...linkable] } : {},
37390
- ...lintTokens !== void 0 ? { tokens: lintTokens } : {},
37566
+ ...renderTokens !== void 0 ? { tokens: renderTokens } : {},
37391
37567
  ...preloaded.meta.surfaces ? { surfaceNav: preloaded.meta.surfaces } : {},
37392
37568
  auth: (() => {
37393
37569
  const a = preloaded.module.config.auth;
@@ -37407,9 +37583,9 @@ async function buildFunctionsOnlyRelease(preloaded, dest) {
37407
37583
  const sources = {};
37408
37584
  for (const definition of config.functions.functions) {
37409
37585
  const candidates = [".ts", ".js", ".mts", ".mjs"].map((extension) => join34(preloaded.dir, "functions", `${definition.name}${extension}`));
37410
- const source = candidates.find((candidate) => existsSync36(candidate));
37586
+ const source = candidates.find((candidate) => existsSync37(candidate));
37411
37587
  if (!source) throw new Error(`missing source for function ${definition.name}; expected functions/${definition.name}.ts`);
37412
- sources[definition.name] = readFileSync39(source, "utf8");
37588
+ sources[definition.name] = readFileSync40(source, "utf8");
37413
37589
  }
37414
37590
  const built = await buildFunctions(config.functions.functions, sources);
37415
37591
  const bundles = {};
@@ -37459,6 +37635,7 @@ var init_build3 = __esm({
37459
37635
  init_wix_member_login();
37460
37636
  init_wix_placeholders();
37461
37637
  init_render_descriptor();
37638
+ init_render_fonts();
37462
37639
  init_screen_crawl();
37463
37640
  init_icons();
37464
37641
  init_build2();
@@ -38089,11 +38266,11 @@ __export(captcha_exports, {
38089
38266
  captchaContentInput: () => captchaContentInput,
38090
38267
  runCaptcha: () => runCaptcha
38091
38268
  });
38092
- import { readFileSync as readFileSync40 } from "node:fs";
38269
+ import { readFileSync as readFileSync41 } from "node:fs";
38093
38270
  import { resolve as resolve32 } from "node:path";
38094
38271
  function readObject(path) {
38095
38272
  try {
38096
- return JSON.parse(readFileSync40(path, "utf8"));
38273
+ return JSON.parse(readFileSync41(path, "utf8"));
38097
38274
  } catch {
38098
38275
  return {};
38099
38276
  }
@@ -38237,11 +38414,11 @@ var init_push_setup_apple_credentials = __esm({
38237
38414
  });
38238
38415
 
38239
38416
  // src/push-onboarding.ts
38240
- import { existsSync as existsSync37, mkdirSync as mkdirSync17, readFileSync as readFileSync41, statSync as statSync7, writeFileSync as writeFileSync13, chmodSync as chmodSync2 } from "node:fs";
38417
+ import { existsSync as existsSync38, mkdirSync as mkdirSync17, readFileSync as readFileSync42, statSync as statSync7, writeFileSync as writeFileSync13, chmodSync as chmodSync2 } from "node:fs";
38241
38418
  import { basename as basename9, dirname as dirname22, join as join35, resolve as resolve33 } from "node:path";
38242
38419
  function readJson2(path) {
38243
38420
  try {
38244
- const parsed = JSON.parse(readFileSync41(path, "utf8"));
38421
+ const parsed = JSON.parse(readFileSync42(path, "utf8"));
38245
38422
  return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
38246
38423
  } catch {
38247
38424
  return {};
@@ -38249,7 +38426,7 @@ function readJson2(path) {
38249
38426
  }
38250
38427
  function pushInputsFromContent(dir) {
38251
38428
  const root = resolve33(dir);
38252
- if (!existsSync37(join35(root, "himalaya.content.json"))) return { initialized: false };
38429
+ if (!existsSync38(join35(root, "himalaya.content.json"))) return { initialized: false };
38253
38430
  const content = readJson2(join35(root, "himalaya.content.json"));
38254
38431
  const provisioning = readJson2(join35(root, "provisioning.json"));
38255
38432
  const native = provisioning.native ?? {};
@@ -38326,7 +38503,7 @@ function readKeyFile(path) {
38326
38503
  }
38327
38504
  let body;
38328
38505
  try {
38329
- body = readFileSync41(path, "utf8");
38506
+ body = readFileSync42(path, "utf8");
38330
38507
  } catch {
38331
38508
  return { ok: false, code: "key_file_unreadable", reason: "cannot read the selected key file; check its path and file permissions" };
38332
38509
  }
@@ -38381,7 +38558,7 @@ function buildPushSetupBody(i, keys) {
38381
38558
  }
38382
38559
  function readPushOnboarding(dir) {
38383
38560
  const path = join35(resolve33(dir), PUSH_ONBOARDING_PATH);
38384
- if (!existsSync37(path)) return { version: 1 };
38561
+ if (!existsSync38(path)) return { version: 1 };
38385
38562
  const parsed = readJson2(path);
38386
38563
  return { version: 1, ...parsed };
38387
38564
  }
@@ -38416,7 +38593,7 @@ function recordPushDeferral(dir, d) {
38416
38593
  }
38417
38594
  function clearPushDeferral(dir) {
38418
38595
  const path = join35(resolve33(dir), PUSH_ONBOARDING_PATH);
38419
- if (!existsSync37(path)) return;
38596
+ if (!existsSync38(path)) return;
38420
38597
  const { push: _dropped, ...rest } = readPushOnboarding(dir);
38421
38598
  writeFile(dir, { ...rest, version: 1 });
38422
38599
  }
@@ -39376,7 +39553,7 @@ __export(pack_exports, {
39376
39553
  });
39377
39554
  import { createHash as createHash19 } from "node:crypto";
39378
39555
  import { deflateRawSync, inflateRawSync } from "node:zlib";
39379
- import { existsSync as existsSync38, mkdirSync as mkdirSync18, readFileSync as readFileSync42, readdirSync as readdirSync20, rmSync as rmSync6, statSync as statSync8, writeFileSync as writeFileSync14 } from "node:fs";
39556
+ import { existsSync as existsSync39, mkdirSync as mkdirSync18, readFileSync as readFileSync43, readdirSync as readdirSync20, rmSync as rmSync6, statSync as statSync8, writeFileSync as writeFileSync14 } from "node:fs";
39380
39557
  import { dirname as dirname23, join as join36, resolve as resolve35 } from "node:path";
39381
39558
  function writeZip(entries) {
39382
39559
  const sorted = entries.slice().sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
@@ -39471,10 +39648,10 @@ function inflateEntry(buf, entry) {
39471
39648
  return bytes2;
39472
39649
  }
39473
39650
  function readIf(path) {
39474
- return existsSync38(path) && statSync8(path).isFile() ? readFileSync42(path) : null;
39651
+ return existsSync39(path) && statSync8(path).isFile() ? readFileSync43(path) : null;
39475
39652
  }
39476
39653
  function listDir(dir) {
39477
- return existsSync38(dir) ? readdirSync20(dir).filter((f) => statSync8(join36(dir, f)).isFile()) : [];
39654
+ return existsSync39(dir) ? readdirSync20(dir).filter((f) => statSync8(join36(dir, f)).isFile()) : [];
39478
39655
  }
39479
39656
  function gatherReleaseEntries(appDir2) {
39480
39657
  const manifestPath = join36(appDir2, HIMI_PACKAGE_MANIFEST_PATH);
@@ -39553,7 +39730,7 @@ function packRelease(releaseRoot, app, out, opts = {}) {
39553
39730
  const appDir2 = join36(resolve35(releaseRoot), app);
39554
39731
  const { all, header, skipped } = buildEntries(appDir2, app, opts);
39555
39732
  const buf = writeZip(all);
39556
- const isDir = existsSync38(out) && statSync8(out).isDirectory();
39733
+ const isDir = existsSync39(out) && statSync8(out).isDirectory();
39557
39734
  const outFile = isDir ? join36(resolve35(out), packageFileName(app, header.releaseId)) : resolve35(out);
39558
39735
  mkdirSync18(dirname23(outFile), { recursive: true });
39559
39736
  writeFileSync14(outFile, buf);
@@ -39570,11 +39747,11 @@ function resolvePackageDirDest(outDir, app, releaseId) {
39570
39747
  }
39571
39748
  };
39572
39749
  const replaceable = (dir) => {
39573
- if (!existsSync38(dir)) return true;
39750
+ if (!existsSync39(dir)) return true;
39574
39751
  if (!statSync8(dir).isDirectory()) return false;
39575
39752
  return readdirSync20(dir).length === 0 || packagedApp(dir) === app;
39576
39753
  };
39577
- if (existsSync38(outDir) && !statSync8(outDir).isDirectory()) {
39754
+ if (existsSync39(outDir) && !statSync8(outDir).isDirectory()) {
39578
39755
  throw new Error(`refusing to write a package tree over ${outDir} \u2014 it is a file, not a directory`);
39579
39756
  }
39580
39757
  if (replaceable(outDir)) return outDir;
@@ -39621,7 +39798,7 @@ function openPackageBuffer(buf) {
39621
39798
  return openFromEntries(readZip(buf), { requireHeader: true });
39622
39799
  }
39623
39800
  function openPackageFile(file) {
39624
- return openPackageBuffer(readFileSync42(file));
39801
+ return openPackageBuffer(readFileSync43(file));
39625
39802
  }
39626
39803
  function openPackageDir(dir) {
39627
39804
  const root = resolve35(dir);
@@ -39632,10 +39809,10 @@ function openPackageDir(dir) {
39632
39809
  const childRel = rel ? `${rel}/${name}` : name;
39633
39810
  const childAbs = join36(abs, name);
39634
39811
  if (statSync8(childAbs).isDirectory()) walk2(childRel);
39635
- else if (isSafeEntryName(childRel)) entries.set(childRel, readFileSync42(childAbs));
39812
+ else if (isSafeEntryName(childRel)) entries.set(childRel, readFileSync43(childAbs));
39636
39813
  }
39637
39814
  };
39638
- if (!existsSync38(root)) throw new Error(`no such package directory: ${root}`);
39815
+ if (!existsSync39(root)) throw new Error(`no such package directory: ${root}`);
39639
39816
  walk2("");
39640
39817
  const manifestBytes = entries.get(HIMI_PACKAGE_MANIFEST_PATH);
39641
39818
  if (manifestBytes) {
@@ -39716,7 +39893,7 @@ __export(app_source_exports, {
39716
39893
  writeConflicts: () => writeConflicts,
39717
39894
  zipAppSource: () => zipAppSource
39718
39895
  });
39719
- import { readdirSync as readdirSync21, lstatSync as lstatSync5, readFileSync as readFileSync43, mkdirSync as mkdirSync19, writeFileSync as writeFileSync15, existsSync as existsSync39, rmSync as rmSync7, rmdirSync, unlinkSync as unlinkSync3 } from "node:fs";
39896
+ import { readdirSync as readdirSync21, lstatSync as lstatSync5, readFileSync as readFileSync44, mkdirSync as mkdirSync19, writeFileSync as writeFileSync15, existsSync as existsSync40, rmSync as rmSync7, rmdirSync, unlinkSync as unlinkSync3 } from "node:fs";
39720
39897
  import { join as join37, resolve as resolve36, sep as sep8 } from "node:path";
39721
39898
  import { deflateRawSync as deflateRawSync2 } from "node:zlib";
39722
39899
  function walkSourceTree(dir, file, skip) {
@@ -39729,7 +39906,7 @@ function walkSourceTree(dir, file, skip) {
39729
39906
  continue;
39730
39907
  }
39731
39908
  if (st.isDirectory()) {
39732
- if (isDeniedSourceDir(name, relDir) || existsSync39(join37(dir, rel, PACKAGE_DIR_MARKER))) skip(rel);
39909
+ if (isDeniedSourceDir(name, relDir) || existsSync40(join37(dir, rel, PACKAGE_DIR_MARKER))) skip(rel);
39733
39910
  else walk2(rel);
39734
39911
  continue;
39735
39912
  }
@@ -39747,7 +39924,7 @@ function collectAppSource(dir) {
39747
39924
  const skipped = [];
39748
39925
  walkSourceTree(
39749
39926
  dir,
39750
- (archivePath, hostRel) => entries.push({ path: archivePath, bytes: readFileSync43(join37(dir, hostRel)) }),
39927
+ (archivePath, hostRel) => entries.push({ path: archivePath, bytes: readFileSync44(join37(dir, hostRel)) }),
39751
39928
  (hostRel) => skipped.push(hostRel)
39752
39929
  );
39753
39930
  entries.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
@@ -39815,7 +39992,7 @@ function writeAppSource(entries, destDir) {
39815
39992
  return written;
39816
39993
  }
39817
39994
  function staleSourcePaths(entries, destDir) {
39818
- if (!existsSync39(destDir)) return [];
39995
+ if (!existsSync40(destDir)) return [];
39819
39996
  const archived = new Set(entries.map((e) => e.path));
39820
39997
  const stale = [];
39821
39998
  walkSourceTree(destDir, (archivePath) => {
@@ -39871,7 +40048,7 @@ function removeStaleSource(entries, destDir) {
39871
40048
  const segments = entry.path.split("/");
39872
40049
  for (let i = 1; i < segments.length; i++) needed.add(segments.slice(0, i).join("/"));
39873
40050
  }
39874
- if (existsSync39(root)) pruneEmptyDirs(root, "", needed, removed);
40051
+ if (existsSync40(root)) pruneEmptyDirs(root, "", needed, removed);
39875
40052
  return removed.sort();
39876
40053
  }
39877
40054
  function pruneEmptyDirs(root, rel, needed, removed) {
@@ -39944,13 +40121,13 @@ __export(eject_exports, {
39944
40121
  EJECTABLE: () => EJECTABLE,
39945
40122
  ejectModule: () => ejectModule
39946
40123
  });
39947
- import { existsSync as existsSync40, mkdirSync as mkdirSync20, readFileSync as readFileSync44, writeFileSync as writeFileSync16 } from "node:fs";
40124
+ import { existsSync as existsSync41, mkdirSync as mkdirSync20, readFileSync as readFileSync45, writeFileSync as writeFileSync16 } from "node:fs";
39948
40125
  import { dirname as dirname24, join as join38, relative as relative5, resolve as resolve37, sep as sep9 } from "node:path";
39949
40126
  function locate(repoRootOrCwd, mod) {
39950
40127
  const inRepo = resolve37(repoRootOrCwd, `stdlib/flows/${mod}/src/index.ts`);
39951
- if (existsSync40(inRepo)) return { path: inRepo, form: "source" };
40128
+ if (existsSync41(inRepo)) return { path: inRepo, form: "source" };
39952
40129
  const dist = resolve37(repoRootOrCwd, `node_modules/@wix/himalaya/dist/${mod}.mjs`);
39953
- if (existsSync40(dist)) return { path: dist, form: "bundle" };
40130
+ if (existsSync41(dist)) return { path: dist, form: "bundle" };
39954
40131
  return null;
39955
40132
  }
39956
40133
  function specifiersFor(mod) {
@@ -39988,15 +40165,15 @@ function ejectModule(opts) {
39988
40165
  // gate still applies. Ejecting buys layout and flow, never the floor.
39989
40166
 
39990
40167
  `;
39991
- const normalized = readFileSync44(found.path, "utf8").replace(
40168
+ const normalized = readFileSync45(found.path, "utf8").replace(
39992
40169
  /(["'])@himalaya\/([a-z0-9-]+(?:\/[a-z0-9-]+)?)\1/g,
39993
40170
  (_m, q, sub) => `${q}@wix/himalaya/${sub}${q}`
39994
40171
  );
39995
40172
  writeFileSync16(target, banner + normalized);
39996
40173
  const rewired = [];
39997
40174
  for (const f of files) {
39998
- if (!existsSync40(f)) continue;
39999
- const before = readFileSync44(f, "utf8");
40175
+ if (!existsSync41(f)) continue;
40176
+ const before = readFileSync45(f, "utf8");
40000
40177
  let after = before;
40001
40178
  let rel = relative5(dirname24(f), target).split(sep9).join("/").replace(/\.tsx?$/, ".js");
40002
40179
  if (!rel.startsWith(".")) rel = `./${rel}`;
@@ -40044,14 +40221,14 @@ __export(test_exports, {
40044
40221
  scopeDescriptors: () => scopeDescriptors,
40045
40222
  writeRecordedMocks: () => writeRecordedMocks
40046
40223
  });
40047
- import { existsSync as existsSync41, mkdirSync as mkdirSync21, readFileSync as readFileSync45, writeFileSync as writeFileSync17 } from "node:fs";
40224
+ import { existsSync as existsSync42, mkdirSync as mkdirSync21, readFileSync as readFileSync46, writeFileSync as writeFileSync17 } from "node:fs";
40048
40225
  import { join as join39, resolve as resolve38 } from "node:path";
40049
40226
  function readTestConfig(dir) {
40050
40227
  const p = resolve38(dir, TEST_CONFIG_FILE);
40051
- if (!existsSync41(p)) return {};
40228
+ if (!existsSync42(p)) return {};
40052
40229
  let parsed;
40053
40230
  try {
40054
- parsed = JSON.parse(readFileSync45(p, "utf8"));
40231
+ parsed = JSON.parse(readFileSync46(p, "utf8"));
40055
40232
  } catch (e) {
40056
40233
  throw new Error(`${TEST_CONFIG_FILE} is not valid JSON \u2014 ${e.message}`);
40057
40234
  }
@@ -40094,7 +40271,7 @@ function readTestConfig(dir) {
40094
40271
  function readNetRules(path) {
40095
40272
  let parsed;
40096
40273
  try {
40097
- parsed = JSON.parse(readFileSync45(path, "utf8"));
40274
+ parsed = JSON.parse(readFileSync46(path, "utf8"));
40098
40275
  } catch (e) {
40099
40276
  throw new Error(`--net ${path} could not be read as JSON \u2014 ${e.message}`);
40100
40277
  }
@@ -40115,7 +40292,7 @@ function readNetRules(path) {
40115
40292
  function defaultNetRules(dir) {
40116
40293
  for (const rel of ["dev/net-mocks.json", "tests/net-mocks.json"]) {
40117
40294
  const p = resolve38(dir, rel);
40118
- if (existsSync41(p)) {
40295
+ if (existsSync42(p)) {
40119
40296
  const rules = readNetRules(p);
40120
40297
  if (rules.length) return { rules, from: rel };
40121
40298
  }
@@ -40131,7 +40308,7 @@ function readCannedResponses() {
40131
40308
  ];
40132
40309
  for (const url of candidates) {
40133
40310
  try {
40134
- const parsed = JSON.parse(readFileSync45(url, "utf8"));
40311
+ const parsed = JSON.parse(readFileSync46(url, "utf8"));
40135
40312
  const byKey = {};
40136
40313
  for (const [k, v] of Object.entries(parsed)) {
40137
40314
  if (!k.startsWith("//")) byKey[k] = v;
@@ -40248,7 +40425,7 @@ async function runShotsPass(opts) {
40248
40425
  const rr = await opts.deps.renderDescriptorWeb(baked.descriptor, opts.tokens, scheme, false, state, opts.width);
40249
40426
  if (rr.renderable && rr.html) shots.push({ screenId: baked.screenId, html: rr.html });
40250
40427
  }
40251
- const pngs = await opts.deps.renderPngBatch(shots.map((x) => ({ html: x.html, scheme, ...opts.width ? { width: opts.width } : {} })));
40428
+ const pngs = await opts.deps.renderPngBatch(shots.map((x) => ({ html: x.html, scheme, tokens: opts.tokens, ...opts.width ? { width: opts.width } : {} })));
40252
40429
  if (pngs === null) return { dir: opts.outDir, written: [], unavailable: true };
40253
40430
  if (opts.clearDir) opts.deps.clearDir?.(opts.outDir);
40254
40431
  const written = [];
@@ -40681,14 +40858,14 @@ var mobile_ux_lint_exports = {};
40681
40858
  __export(mobile_ux_lint_exports, {
40682
40859
  mobileUxIssues: () => mobileUxIssues
40683
40860
  });
40684
- import { existsSync as existsSync42, readFileSync as readFileSync46 } from "node:fs";
40861
+ import { existsSync as existsSync43, readFileSync as readFileSync47 } from "node:fs";
40685
40862
  import { join as join40 } from "node:path";
40686
40863
  function mobileUxIssues(dir, strict) {
40687
40864
  const file = join40(dir, "MOBILE-UX.md");
40688
- if (!existsSync42(file)) return [];
40865
+ if (!existsSync43(file)) return [];
40689
40866
  let text4;
40690
40867
  try {
40691
- text4 = readFileSync46(file, "utf8");
40868
+ text4 = readFileSync47(file, "utf8");
40692
40869
  } catch {
40693
40870
  return [];
40694
40871
  }
@@ -41949,18 +42126,18 @@ function createFunctionDataCapability(options) {
41949
42126
  }));
41950
42127
  };
41951
42128
  const encodeQuery = (query) => {
41952
- const encoded = { ...query };
41953
- if (query.filter !== void 0) encoded.filter = mapFilter(query.filter);
41954
- if (Array.isArray(query.sort)) encoded.sort = query.sort.map((sort) => {
42129
+ const encoded2 = { ...query };
42130
+ if (query.filter !== void 0) encoded2.filter = mapFilter(query.filter);
42131
+ if (Array.isArray(query.sort)) encoded2.sort = query.sort.map((sort) => {
41955
42132
  if (!sort || typeof sort !== "object") return sort;
41956
42133
  const record2 = sort;
41957
42134
  const logical = typeof record2.fieldName === "string" ? record2.fieldName : "";
41958
42135
  return { ...record2, fieldName: queryField(logical) };
41959
42136
  });
41960
- if (Array.isArray(query.fields)) encoded.fields = query.fields.map((logical) => {
42137
+ if (Array.isArray(query.fields)) encoded2.fields = query.fields.map((logical) => {
41961
42138
  return queryField(String(logical));
41962
42139
  });
41963
- return encoded;
42140
+ return encoded2;
41964
42141
  };
41965
42142
  const decode = (result) => {
41966
42143
  if (!result || typeof result !== "object") return result;
@@ -42352,7 +42529,7 @@ __export(functions_exports, {
42352
42529
  resolveFunctionsTarget: () => resolveFunctionsTarget,
42353
42530
  runRemoteFunctionOperation: () => runRemoteFunctionOperation
42354
42531
  });
42355
- import { readFileSync as readFileSync47, existsSync as existsSync43 } from "node:fs";
42532
+ import { readFileSync as readFileSync48, existsSync as existsSync44 } from "node:fs";
42356
42533
  import { join as join41, resolve as resolve39 } from "node:path";
42357
42534
  function resolveFunctionsTarget(input) {
42358
42535
  const explicitUrl = input.functionsUrl?.trim();
@@ -42372,9 +42549,9 @@ async function loadFunctionsApp(dir) {
42372
42549
  }
42373
42550
  const sources = {};
42374
42551
  for (const definition of config.functions.functions) {
42375
- const source = [".ts", ".js", ".mts", ".mjs"].map((extension) => join41(loaded.dir, "functions", `${definition.name}${extension}`)).find(existsSync43);
42552
+ const source = [".ts", ".js", ".mts", ".mjs"].map((extension) => join41(loaded.dir, "functions", `${definition.name}${extension}`)).find(existsSync44);
42376
42553
  if (!source) throw new Error(`missing source for function ${definition.name}; expected functions/${definition.name}.ts`);
42377
- sources[definition.name] = readFileSync47(source, "utf8");
42554
+ sources[definition.name] = readFileSync48(source, "utf8");
42378
42555
  }
42379
42556
  const data = config.cms || config.data ? mergeDataResources(config) : void 0;
42380
42557
  const dataErrors = validateDataResources(data, loaded.name).filter((issue2) => issue2.severity === "error");
@@ -42529,7 +42706,7 @@ __export(native_decode_exports, {
42529
42706
  runNativeDecode: () => runNativeDecode
42530
42707
  });
42531
42708
  import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
42532
- import { existsSync as existsSync44, mkdtempSync as mkdtempSync2, readFileSync as readFileSync48, rmSync as rmSync8, writeFileSync as writeFileSync18 } from "node:fs";
42709
+ import { existsSync as existsSync45, mkdtempSync as mkdtempSync2, readFileSync as readFileSync49, rmSync as rmSync8, writeFileSync as writeFileSync18 } from "node:fs";
42533
42710
  import { tmpdir as tmpdir3 } from "node:os";
42534
42711
  import { join as join42 } from "node:path";
42535
42712
  import { fileURLToPath as fileURLToPath20 } from "node:url";
@@ -42541,8 +42718,8 @@ function nativeDecodeAndroidHarnessDir() {
42541
42718
  }
42542
42719
  function nativeOracleShipped() {
42543
42720
  return {
42544
- ios: existsSync44(join42(nativeDecodePackageDir(), "Package.swift")),
42545
- android: existsSync44(join42(nativeDecodeAndroidHarnessDir(), "gradlew"))
42721
+ ios: existsSync45(join42(nativeDecodePackageDir(), "Package.swift")),
42722
+ android: existsSync45(join42(nativeDecodeAndroidHarnessDir(), "gradlew"))
42546
42723
  };
42547
42724
  }
42548
42725
  function detectNativeDecode(options = {}) {
@@ -42553,7 +42730,7 @@ function detectNativeDecode(options = {}) {
42553
42730
  return { platform: "ios", available: false, reason: `the iOS decoder oracle requires macOS (darwin); this host is ${hostPlatform}` };
42554
42731
  }
42555
42732
  if (!swiftAvailable) return { platform: "ios", available: false, reason: "swift is not on PATH" };
42556
- const packageAvailable = options.packageAvailable ?? existsSync44(join42(packageDir, "Package.swift"));
42733
+ const packageAvailable = options.packageAvailable ?? existsSync45(join42(packageDir, "Package.swift"));
42557
42734
  if (!packageAvailable) {
42558
42735
  return {
42559
42736
  platform: "ios",
@@ -42565,7 +42742,7 @@ function detectNativeDecode(options = {}) {
42565
42742
  }
42566
42743
  function localPropertiesSdk(harnessDir) {
42567
42744
  try {
42568
- const match = readFileSync48(join42(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
42745
+ const match = readFileSync49(join42(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
42569
42746
  return match?.[1]?.trim().replace(/\\([ :\\])/g, "$1") ?? null;
42570
42747
  } catch {
42571
42748
  return null;
@@ -42574,7 +42751,7 @@ function localPropertiesSdk(harnessDir) {
42574
42751
  function detectAndroidNativeDecode(options = {}) {
42575
42752
  const harnessDir = options.harnessDir ?? nativeDecodeAndroidHarnessDir();
42576
42753
  const gradlew = join42(harnessDir, "gradlew");
42577
- const gradlewAvailable = options.gradlewAvailable ?? existsSync44(gradlew);
42754
+ const gradlewAvailable = options.gradlewAvailable ?? existsSync45(gradlew);
42578
42755
  if (!gradlewAvailable) {
42579
42756
  return {
42580
42757
  platform: "android",
@@ -42584,7 +42761,7 @@ function detectAndroidNativeDecode(options = {}) {
42584
42761
  }
42585
42762
  const androidHome = options.androidHome ?? process.env.ANDROID_HOME ?? "";
42586
42763
  const sdk = androidHome.trim() || (options.localPropertiesSdk !== void 0 ? options.localPropertiesSdk : localPropertiesSdk(harnessDir));
42587
- const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync44(sdk));
42764
+ const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync45(sdk));
42588
42765
  if (!sdkAvailable) {
42589
42766
  return {
42590
42767
  platform: "android",
@@ -42716,7 +42893,7 @@ function runAndroidNativeDecode(options) {
42716
42893
  stdio: ["ignore", "ignore", "pipe"],
42717
42894
  encoding: "utf8"
42718
42895
  });
42719
- const stdout = readFileSync48(outputPath, "utf8");
42896
+ const stdout = readFileSync49(outputPath, "utf8");
42720
42897
  return {
42721
42898
  platform: "android",
42722
42899
  verdicts: parseNativeDecodeOutput(stdout, options.descriptors.map((descriptor) => descriptor.screenId), "android"),
@@ -42787,7 +42964,7 @@ __export(browser_authoring_exports, {
42787
42964
  import { createServer as createServer3 } from "node:http";
42788
42965
  import { createHash as createHash22, randomBytes as randomBytes4 } from "node:crypto";
42789
42966
  import { execFile as execFile2 } from "node:child_process";
42790
- import { existsSync as existsSync45, readdirSync as readdirSync22, readFileSync as readFileSync49, realpathSync as realpathSync4, statSync as statSync9 } from "node:fs";
42967
+ import { existsSync as existsSync46, readdirSync as readdirSync22, readFileSync as readFileSync50, realpathSync as realpathSync4, statSync as statSync9 } from "node:fs";
42791
42968
  import { join as join43, posix, relative as relative6, sep as sep10 } from "node:path";
42792
42969
  function humanMs(ms) {
42793
42970
  return ms < 1e3 ? `${ms}ms` : `${Math.round(ms / 1e3)}s`;
@@ -42806,11 +42983,11 @@ function collectWorkerSources(tier5SrcDir, bundleName) {
42806
42983
  if (statSync9(childAbs).isDirectory()) {
42807
42984
  walk2(childAbs, childRel);
42808
42985
  } else if (/\.(ts|tsx|js|mjs|json)$/.test(name)) {
42809
- files[childRel] = readFileSync49(childAbs, "utf8");
42986
+ files[childRel] = readFileSync50(childAbs, "utf8");
42810
42987
  }
42811
42988
  }
42812
42989
  };
42813
- if (!existsSync45(root)) return null;
42990
+ if (!existsSync46(root)) return null;
42814
42991
  walk2(root, `/tier5-src/${bundleName}`);
42815
42992
  const entry = [`/tier5-src/${bundleName}/index.ts`, `/tier5-src/${bundleName}/index.js`].find((p) => p in files);
42816
42993
  if (!entry) return null;
@@ -42837,10 +43014,10 @@ function collectRelativeSiblings(files, tier5SrcDir) {
42837
43014
  join43(onDisk, "index.js")
42838
43015
  ];
42839
43016
  for (const abs of candidates) {
42840
- if (!existsSync45(abs) || statSync9(abs).isDirectory()) continue;
43017
+ if (!existsSync46(abs) || statSync9(abs).isDirectory()) continue;
42841
43018
  const key2 = `/tier5-src/${relative6(tier5SrcDir, abs).split(sep10).join(posix.sep)}`;
42842
43019
  if (key2 in files) break;
42843
- files[key2] = readFileSync49(abs, "utf8");
43020
+ files[key2] = readFileSync50(abs, "utf8");
42844
43021
  queue.push(key2);
42845
43022
  break;
42846
43023
  }
@@ -42875,7 +43052,7 @@ function collectSdkModules(files, resolveSubpath) {
42875
43052
  function sdkSubpathReader(resolve45) {
42876
43053
  return (sub) => {
42877
43054
  try {
42878
- return readFileSync49(resolve45(`@wix/himalaya/${sub}`), "utf8");
43055
+ return readFileSync50(resolve45(`@wix/himalaya/${sub}`), "utf8");
42879
43056
  } catch {
42880
43057
  return null;
42881
43058
  }
@@ -43049,7 +43226,7 @@ __export(coverage_exports, {
43049
43226
  suppressedNativeKeys: () => suppressedNativeKeys,
43050
43227
  trendAndStore: () => trendAndStore
43051
43228
  });
43052
- import { existsSync as existsSync46, mkdirSync as mkdirSync22, readFileSync as readFileSync50, writeFileSync as writeFileSync19 } from "node:fs";
43229
+ import { existsSync as existsSync47, mkdirSync as mkdirSync22, readFileSync as readFileSync51, writeFileSync as writeFileSync19 } from "node:fs";
43053
43230
  import { dirname as dirname25, join as join44 } from "node:path";
43054
43231
  function suppressedNativeKeys(oracle) {
43055
43232
  return [...oracle.ios ? [] : ["native-decode|ios"], ...oracle.android ? [] : ["native-decode|android"]];
@@ -43223,8 +43400,8 @@ function trendAndStore(dir, entries, suppressed) {
43223
43400
  const p = join44(dir, LEDGER_FILE);
43224
43401
  let previous = null;
43225
43402
  try {
43226
- if (existsSync46(p)) {
43227
- const parsed = JSON.parse(readFileSync50(p, "utf8"));
43403
+ if (existsSync47(p)) {
43404
+ const parsed = JSON.parse(readFileSync51(p, "utf8"));
43228
43405
  if (Array.isArray(parsed.keys)) previous = parsed.keys.filter((k) => typeof k === "string");
43229
43406
  }
43230
43407
  } catch {
@@ -43266,8 +43443,8 @@ function diffAndStoreObservations(dir, current) {
43266
43443
  const p = join44(dir, OBS_FILE);
43267
43444
  let previous = null;
43268
43445
  try {
43269
- if (existsSync46(p)) {
43270
- const parsed = JSON.parse(readFileSync50(p, "utf8"));
43446
+ if (existsSync47(p)) {
43447
+ const parsed = JSON.parse(readFileSync51(p, "utf8"));
43271
43448
  if (parsed.screens && typeof parsed.screens === "object" && !Array.isArray(parsed.screens) && Object.values(parsed.screens).every(
43272
43449
  (v) => Array.isArray(v) && v.every((l) => typeof l === "string")
43273
43450
  )) {
@@ -43328,11 +43505,11 @@ __export(design_kits_exports, {
43328
43505
  kitsDir: () => kitsDir,
43329
43506
  listKits: () => listKits2
43330
43507
  });
43331
- import { existsSync as existsSync47, readFileSync as readFileSync51, readdirSync as readdirSync23 } from "node:fs";
43508
+ import { existsSync as existsSync48, readFileSync as readFileSync52, readdirSync as readdirSync23 } from "node:fs";
43332
43509
  import { join as join45, basename as basename10 } from "node:path";
43333
43510
  import { fileURLToPath as fileURLToPath21 } from "node:url";
43334
43511
  function kitsDir() {
43335
- return KIT_DIR_CANDIDATES.find((p) => existsSync47(p));
43512
+ return KIT_DIR_CANDIDATES.find((p) => existsSync48(p));
43336
43513
  }
43337
43514
  function listKits2() {
43338
43515
  const dir = kitsDir();
@@ -43356,7 +43533,7 @@ In a published @wix/himalaya-cli this is a packaging bug \u2014 the kits should
43356
43533
  if (!kits.includes(name)) {
43357
43534
  return { ok: false, kit: name, kits, problems: [`no design kit named "${name}". Available: ${kits.join(", ")}`] };
43358
43535
  }
43359
- const raw = readFileSync51(join45(dir, `${name}.json`), "utf8");
43536
+ const raw = readFileSync52(join45(dir, `${name}.json`), "utf8");
43360
43537
  let parsed;
43361
43538
  try {
43362
43539
  parsed = JSON.parse(raw);
@@ -43396,11 +43573,11 @@ __export(assets_exports, {
43396
43573
  removeAssetPayload: () => removeAssetPayload,
43397
43574
  verifyReport: () => verifyReport
43398
43575
  });
43399
- import { readFileSync as readFileSync52 } from "node:fs";
43576
+ import { readFileSync as readFileSync53 } from "node:fs";
43400
43577
  import { basename as basename11 } from "node:path";
43401
43578
  function declaredAssets(dir) {
43402
43579
  return collectAssets(dir).map((a) => {
43403
- const bytes2 = readFileSync52(a.path);
43580
+ const bytes2 = readFileSync53(a.path);
43404
43581
  return {
43405
43582
  name: a.name,
43406
43583
  sha256: assetSha256(bytes2),
@@ -43477,7 +43654,7 @@ function verifyReport(dir, app, manifest) {
43477
43654
  };
43478
43655
  }
43479
43656
  function addAssetPayload(manifest, filePath, opts) {
43480
- const bytes2 = readFileSync52(filePath);
43657
+ const bytes2 = readFileSync53(filePath);
43481
43658
  const name = opts.name ?? basename11(filePath);
43482
43659
  const sha2565 = assetSha256(bytes2);
43483
43660
  const record2 = {
@@ -44944,19 +45121,19 @@ var init_preview_assets_generated = __esm({
44944
45121
  "../../packages/serve/src/preview-assets.generated.ts"() {
44945
45122
  init_preview_assets_format();
44946
45123
  PREVIEW_ASSET_MANIFEST = [
44947
- { key: "assets/index-BvDcgJGH.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 1005923, sha256: "f307e430cd004dc19c3cc48fbf15111dfa31bd22686304bd5437bb59c9baf486" },
44948
- { key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 1005931, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
44949
- { key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 1096855, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
44950
- { key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 1187839, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
44951
- { key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 1278819, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
44952
- { key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 1369691, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
44953
- { key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 1460671, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
44954
- { key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 1569307, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
44955
- { key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 1678391, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
44956
- { key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 1787439, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
44957
- { key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 1895139, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
44958
- { key: "index.html", contentType: "text/html; charset=utf-8", offset: 1983247, length: 4448, sha256: "6e6842152bdef028d3a52da1cfa23a400fc90c6af9dedf3dc9c65ad0698386ee" },
44959
- { key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 1987695, length: 17209, sha256: "dffc9718e2faa63ae2cc919e0a842f585ed565aaaa7c53778e90379442c731b6" }
45124
+ { key: "assets/index-CD7rJtUy.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 1006255, sha256: "1f775ada818f0f8d26665e3fb4eeff5ef99a4eb2d8dd493a0bf76e64569eef4a" },
45125
+ { key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 1006263, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
45126
+ { key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 1097187, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
45127
+ { key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 1188171, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
45128
+ { key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 1279151, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
45129
+ { key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 1370023, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
45130
+ { key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 1461003, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
45131
+ { key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 1569639, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
45132
+ { key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 1678723, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
45133
+ { key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 1787771, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
45134
+ { key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 1895471, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
45135
+ { key: "index.html", contentType: "text/html; charset=utf-8", offset: 1983579, length: 4448, sha256: "c1e9a6eea6af68bc7e7ae1044a9f46f5938c69b8a5998ea02c3fed7c7db5523a" },
45136
+ { key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 1988027, length: 17209, sha256: "dffc9718e2faa63ae2cc919e0a842f585ed565aaaa7c53778e90379442c731b6" }
44960
45137
  ];
44961
45138
  }
44962
45139
  });
@@ -44972,7 +45149,7 @@ __export(run_exports, {
44972
45149
  runPackage: () => runPackage,
44973
45150
  withoutProdServe: () => withoutProdServe
44974
45151
  });
44975
- import { cpSync, existsSync as existsSync48, mkdirSync as mkdirSync23, mkdtempSync as mkdtempSync3, readFileSync as readFileSync53, rmSync as rmSync9, statSync as statSync10 } from "node:fs";
45152
+ import { cpSync, existsSync as existsSync49, mkdirSync as mkdirSync23, mkdtempSync as mkdtempSync3, readFileSync as readFileSync54, rmSync as rmSync9, statSync as statSync10 } from "node:fs";
44976
45153
  import { tmpdir as tmpdir4 } from "node:os";
44977
45154
  import { dirname as dirname26, join as join46 } from "node:path";
44978
45155
  import { fileURLToPath as fileURLToPath22 } from "node:url";
@@ -44993,9 +45170,9 @@ async function fetchBytes(url) {
44993
45170
  }
44994
45171
  async function resolvePackage(source, workDir) {
44995
45172
  const isUrl2 = /^https?:\/\//i.test(source);
44996
- if (!isUrl2 && existsSync48(source) && statSync10(source).isDirectory()) {
45173
+ if (!isUrl2 && existsSync49(source) && statSync10(source).isDirectory()) {
44997
45174
  const appDirManifest = join46(source, "release-manifest.json");
44998
- if (existsSync48(appDirManifest)) {
45175
+ if (existsSync49(appDirManifest)) {
44999
45176
  const opened2 = openPackageDir(source);
45000
45177
  if (!opened2.validation.ok) {
45001
45178
  throw new Error(`package is not valid:
@@ -45023,7 +45200,7 @@ async function resolvePackage(source, workDir) {
45023
45200
  }
45024
45201
  throw new Error(`${source} is a directory but has no release-manifest.json \u2014 is it a package?`);
45025
45202
  }
45026
- const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync53(source);
45203
+ const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync54(source);
45027
45204
  const root = workDir ?? mkdtempSync3(join46(tmpdir4(), "himi-run-"));
45028
45205
  const { app, appDir: appDir2 } = unpackTo(bytes2, root);
45029
45206
  const opened = openPackageDir(appDir2);
@@ -45053,8 +45230,8 @@ async function loadPreviewAssets() {
45053
45230
  // in-repo checkout
45054
45231
  ];
45055
45232
  for (const path of candidates) {
45056
- if (!existsSync48(path)) continue;
45057
- const blob = readFileSync53(path);
45233
+ if (!existsSync49(path)) continue;
45234
+ const blob = readFileSync54(path);
45058
45235
  return mod.assemblePreviewAssetsFromBlob(new Uint8Array(blob.buffer, blob.byteOffset, blob.byteLength));
45059
45236
  }
45060
45237
  return /* @__PURE__ */ new Map();
@@ -45136,7 +45313,7 @@ __export(run_browser_exports, {
45136
45313
  runInBrowser: () => runInBrowser
45137
45314
  });
45138
45315
  import { createServer as createServer5 } from "node:http";
45139
- import { existsSync as existsSync49, readFileSync as readFileSync54 } from "node:fs";
45316
+ import { existsSync as existsSync50, readFileSync as readFileSync55 } from "node:fs";
45140
45317
  import { spawnSync as spawnSync3, execFile as execFile3 } from "node:child_process";
45141
45318
  import { dirname as dirname27, resolve as resolve40 } from "node:path";
45142
45319
  import { fileURLToPath as fileURLToPath23 } from "node:url";
@@ -45144,7 +45321,7 @@ function stagedDir() {
45144
45321
  return process.env.HIMI_BROWSER_PLANE_OUT ? resolve40(process.env.HIMI_BROWSER_PLANE_OUT) : resolve40(REPO, "packages", "serve", "dist", "browser-plane");
45145
45322
  }
45146
45323
  function missingStaged() {
45147
- return [...SERVED].filter((f) => !existsSync49(resolve40(stagedDir(), f))).sort();
45324
+ return [...SERVED].filter((f) => !existsSync50(resolve40(stagedDir(), f))).sort();
45148
45325
  }
45149
45326
  function ensureBrowserPlaneStaged() {
45150
45327
  if (missingStaged().length === 0) return { ok: true, detail: "already staged" };
@@ -45234,7 +45411,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
45234
45411
  }
45235
45412
  const name = path === "/" || path === "/index.html" ? "host.html" : path.slice(1);
45236
45413
  if (SERVED.has(name)) {
45237
- if (!existsSync49(resolve40(stagedDir(), name))) {
45414
+ if (!existsSync50(resolve40(stagedDir(), name))) {
45238
45415
  const restaged = ensureBrowserPlaneStaged();
45239
45416
  if (!restaged.ok) {
45240
45417
  res.writeHead(503, { "content-type": "application/json" });
@@ -45244,7 +45421,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
45244
45421
  }
45245
45422
  let bytes2;
45246
45423
  try {
45247
- bytes2 = readFileSync54(resolve40(stagedDir(), name));
45424
+ bytes2 = readFileSync55(resolve40(stagedDir(), name));
45248
45425
  } catch (e) {
45249
45426
  res.writeHead(503, { "content-type": "application/json" });
45250
45427
  res.end(JSON.stringify({ error: "browser_plane_unstaged", file: name, detail: String(e) }));
@@ -45707,7 +45884,7 @@ __export(preflight_exports, {
45707
45884
  parseStoreConfig: () => parseStoreConfig,
45708
45885
  requireEnv: () => requireEnv
45709
45886
  });
45710
- import { existsSync as existsSync50, readFileSync as readFileSync55 } from "node:fs";
45887
+ import { existsSync as existsSync51, readFileSync as readFileSync56 } from "node:fs";
45711
45888
  import { isAbsolute as isAbsolute3, relative as relative7, resolve as resolve41 } from "node:path";
45712
45889
  function isInsideRepo(p) {
45713
45890
  const rel = relative7(REPO_ROOT3, resolve41(p));
@@ -45764,10 +45941,10 @@ function parseStoreConfig(text4) {
45764
45941
  }
45765
45942
  function loadStoreConfig(app) {
45766
45943
  const p = storeConfigPath(app);
45767
- if (!existsSync50(p)) {
45944
+ if (!existsSync51(p)) {
45768
45945
  throw new Error(`No store config at ${p}. Create apps/${app}/store/store.config.yaml first (see /setup-store-signing).`);
45769
45946
  }
45770
- return parseStoreConfig(readFileSync55(p, "utf8"));
45947
+ return parseStoreConfig(readFileSync56(p, "utf8"));
45771
45948
  }
45772
45949
  var init_preflight = __esm({
45773
45950
  "../store-release/preflight.ts"() {
@@ -45786,7 +45963,7 @@ __export(credential_profile_exports, {
45786
45963
  profilePath: () => profilePath,
45787
45964
  resolveStoreCredentials: () => resolveStoreCredentials
45788
45965
  });
45789
- import { existsSync as existsSync51, readFileSync as readFileSync56 } from "node:fs";
45966
+ import { existsSync as existsSync52, readFileSync as readFileSync57 } from "node:fs";
45790
45967
  import { homedir as homedir5 } from "node:os";
45791
45968
  import { join as join47 } from "node:path";
45792
45969
  function credentialsDir(home = homedir5()) {
@@ -45829,8 +46006,8 @@ function resolveStoreCredentials(opts) {
45829
46006
  const { app, cfg } = opts;
45830
46007
  const env = opts.env ?? process.env;
45831
46008
  const home = opts.home ?? homedir5();
45832
- const read = opts.readProfile ?? ((p) => readFileSync56(p, "utf8"));
45833
- const exists = opts.profileExists ?? existsSync51;
46009
+ const read = opts.readProfile ?? ((p) => readFileSync57(p, "utf8"));
46010
+ const exists = opts.profileExists ?? existsSync52;
45834
46011
  const ios = cfg.ios ?? {};
45835
46012
  const flagName = opts.profileFlag?.trim();
45836
46013
  const named = namedProfile(cfg, opts.profileFlag);
@@ -45910,7 +46087,7 @@ __export(preflight_app_exports, {
45910
46087
  preflightApp: () => preflightApp,
45911
46088
  profileAccount: () => profileAccount
45912
46089
  });
45913
- import { readFileSync as readFileSync57, existsSync as existsSync52, readdirSync as readdirSync24, statSync as statSync11 } from "node:fs";
46090
+ import { readFileSync as readFileSync58, existsSync as existsSync53, readdirSync as readdirSync24, statSync as statSync11 } from "node:fs";
45914
46091
  import { createHash as createHash23 } from "node:crypto";
45915
46092
  import { join as join48 } from "node:path";
45916
46093
  function analyze(projectYml, storeConfig, icon, account) {
@@ -45976,8 +46153,8 @@ function profileAccount(app, storeConfig, opts = {}) {
45976
46153
  }
45977
46154
  }
45978
46155
  async function preflightApp(app, opts = {}) {
45979
- const projectYml = existsSync52(iosProjectYml(app)) ? readFileSync57(iosProjectYml(app), "utf8") : "";
45980
- const storeConfig = existsSync52(storeConfigPath(app)) ? readFileSync57(storeConfigPath(app), "utf8") : "";
46156
+ const projectYml = existsSync53(iosProjectYml(app)) ? readFileSync58(iosProjectYml(app), "utf8") : "";
46157
+ const storeConfig = existsSync53(storeConfigPath(app)) ? readFileSync58(storeConfigPath(app), "utf8") : "";
45981
46158
  if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }];
45982
46159
  const findings = analyze(
45983
46160
  projectYml,
@@ -46013,15 +46190,15 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
46013
46190
  function appLevelMetadataFiles(app, locale = "en-US") {
46014
46191
  const root = join48(storeDir(app), "metadata");
46015
46192
  const out = /* @__PURE__ */ new Set();
46016
- if (existsSync52(root)) {
46193
+ if (existsSync53(root)) {
46017
46194
  for (const n of readdirSync24(root)) if (n.endsWith(".txt")) out.add(n);
46018
46195
  }
46019
- if (existsSync52(join48(root, locale, "privacy_url.txt"))) out.add("privacy_url.txt");
46196
+ if (existsSync53(join48(root, locale, "privacy_url.txt"))) out.add("privacy_url.txt");
46020
46197
  return out;
46021
46198
  }
46022
46199
  function reviewInfoFiles(app) {
46023
46200
  const dir = join48(storeDir(app), "review_information");
46024
- if (!existsSync52(dir)) return /* @__PURE__ */ new Set();
46201
+ if (!existsSync53(dir)) return /* @__PURE__ */ new Set();
46025
46202
  return new Set(readdirSync24(dir).filter((n) => n.endsWith(".txt")));
46026
46203
  }
46027
46204
  function isValidAppStoreSize(w, h) {
@@ -46136,7 +46313,7 @@ function playListingAssets(app, locale = "en-US") {
46136
46313
  for (const name of names) {
46137
46314
  const p = join48(dir, name);
46138
46315
  try {
46139
- if (statSync11(p).isFile()) return { name, bytes: readFileSync57(p) };
46316
+ if (statSync11(p).isFile()) return { name, bytes: readFileSync58(p) };
46140
46317
  } catch {
46141
46318
  }
46142
46319
  }
@@ -46168,25 +46345,25 @@ function analyzeListing(metaFiles, shots) {
46168
46345
  }
46169
46346
  function metadataFilesPresent(app, locale = "en-US") {
46170
46347
  const dir = join48(storeDir(app), "metadata", locale);
46171
- if (!existsSync52(dir)) return /* @__PURE__ */ new Set();
46348
+ if (!existsSync53(dir)) return /* @__PURE__ */ new Set();
46172
46349
  return new Set(readdirSync24(dir).filter((n) => n.endsWith(".txt")));
46173
46350
  }
46174
46351
  function listScreenshots(app, locale = "en-US") {
46175
46352
  const out = [];
46176
46353
  const flat = join48(storeDir(app), "screenshots", locale);
46177
- if (existsSync52(flat)) {
46354
+ if (existsSync53(flat)) {
46178
46355
  for (const png of readdirSync24(flat).filter((n) => n.endsWith(".png"))) {
46179
- const sz = pngSize(readFileSync57(join48(flat, png)));
46356
+ const sz = pngSize(readFileSync58(join48(flat, png)));
46180
46357
  if (sz) out.push({ name: png, w: sz.w, h: sz.h });
46181
46358
  }
46182
46359
  }
46183
46360
  const legacy = join48(storeDir(app), "metadata", locale, "screenshots");
46184
- if (existsSync52(legacy)) {
46361
+ if (existsSync53(legacy)) {
46185
46362
  for (const deviceDir of readdirSync24(legacy)) {
46186
46363
  const d = join48(legacy, deviceDir);
46187
46364
  if (!statSync11(d).isDirectory()) continue;
46188
46365
  for (const png of readdirSync24(d).filter((n) => n.endsWith(".png"))) {
46189
- const sz = pngSize(readFileSync57(join48(d, png)));
46366
+ const sz = pngSize(readFileSync58(join48(d, png)));
46190
46367
  if (sz) out.push({ name: `${deviceDir}/${png}`, w: sz.w, h: sz.h });
46191
46368
  }
46192
46369
  }
@@ -46195,12 +46372,12 @@ function listScreenshots(app, locale = "en-US") {
46195
46372
  }
46196
46373
  function placeholderHashes2() {
46197
46374
  const templateIos = join48(appDir("_template"), "ios");
46198
- if (!existsSync52(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
46375
+ if (!existsSync53(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
46199
46376
  for (const target of readdirSync24(templateIos)) {
46200
46377
  const p = join48(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
46201
46378
  try {
46202
46379
  if (!statSync11(p).isFile()) continue;
46203
- return [LEGACY_PLACEHOLDER_SHA2562, createHash23("sha256").update(readFileSync57(p)).digest("hex")];
46380
+ return [LEGACY_PLACEHOLDER_SHA2562, createHash23("sha256").update(readFileSync58(p)).digest("hex")];
46204
46381
  } catch {
46205
46382
  }
46206
46383
  }
@@ -46231,12 +46408,12 @@ async function pixelIssues(bytes2) {
46231
46408
  }
46232
46409
  }
46233
46410
  async function appIconState(iosDir) {
46234
- if (!existsSync52(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
46411
+ if (!existsSync53(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
46235
46412
  for (const target of readdirSync24(iosDir)) {
46236
46413
  const p = join48(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
46237
46414
  try {
46238
46415
  if (!statSync11(p).isFile()) continue;
46239
- const bytes2 = readFileSync57(p);
46416
+ const bytes2 = readFileSync58(p);
46240
46417
  const hash = createHash23("sha256").update(bytes2).digest("hex");
46241
46418
  const pixels = await pixelIssues(bytes2);
46242
46419
  return {
@@ -46308,7 +46485,7 @@ __export(version_exports, {
46308
46485
  setAndroidVersion: () => setAndroidVersion,
46309
46486
  setIosVersion: () => setIosVersion
46310
46487
  });
46311
- import { readFileSync as readFileSync58, writeFileSync as writeFileSync20 } from "node:fs";
46488
+ import { readFileSync as readFileSync59, writeFileSync as writeFileSync20 } from "node:fs";
46312
46489
  function readIosVersion(projectYml) {
46313
46490
  const marketing = matchScalar(projectYml, "CFBundleShortVersionString");
46314
46491
  const build2 = matchScalar(projectYml, "CFBundleVersion");
@@ -46366,8 +46543,8 @@ function setAndroidVersion(gradle, v) {
46366
46543
  function bumpVersion(app, opts) {
46367
46544
  const iosPath = iosProjectYml(app);
46368
46545
  const gradlePath = androidGradle(app);
46369
- const iosYml = readFileSync58(iosPath, "utf8");
46370
- const gradle = readFileSync58(gradlePath, "utf8");
46546
+ const iosYml = readFileSync59(iosPath, "utf8");
46547
+ const gradle = readFileSync59(gradlePath, "utf8");
46371
46548
  const current = readIosVersion(iosYml);
46372
46549
  const next = {
46373
46550
  marketing: opts.marketing ?? current.marketing,
@@ -46384,7 +46561,7 @@ var init_version = __esm({
46384
46561
  });
46385
46562
 
46386
46563
  // ../store-release/register-bundle.ts
46387
- import { readFileSync as readFileSync59 } from "node:fs";
46564
+ import { readFileSync as readFileSync60 } from "node:fs";
46388
46565
  import { createPrivateKey as createPrivateKey2, sign } from "node:crypto";
46389
46566
  function b64url2(b) {
46390
46567
  return Buffer.from(b).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
@@ -46402,7 +46579,7 @@ function bundleIdBody(identifier, name, platform = "IOS") {
46402
46579
  async function registerBundleId(opts) {
46403
46580
  const env = requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
46404
46581
  assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
46405
- const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync59(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
46582
+ const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync60(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
46406
46583
  const res = await fetch(`${ASC_API}/v1/bundleIds`, {
46407
46584
  method: "POST",
46408
46585
  headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json" },
@@ -46456,7 +46633,7 @@ __export(asc_status_exports, {
46456
46633
  ascStatus: () => ascStatus,
46457
46634
  buildVerdict: () => buildVerdict
46458
46635
  });
46459
- import { readFileSync as readFileSync60 } from "node:fs";
46636
+ import { readFileSync as readFileSync61 } from "node:fs";
46460
46637
  function buildVerdict(builds) {
46461
46638
  if (!builds.length) {
46462
46639
  return "NO builds registered \u2014 if you uploaded recently and it's been >15 min, the binary was REJECTED IN PROCESSING (reason is email-only; run validate-binary.ts / scan-purpose-strings.ts to reproduce it).";
@@ -46470,7 +46647,7 @@ function buildVerdict(builds) {
46470
46647
  function client(creds) {
46471
46648
  const env = creds ?? requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
46472
46649
  assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
46473
- const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync60(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
46650
+ const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync61(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
46474
46651
  return async (path) => {
46475
46652
  const r = await fetch(`${ASC}${path}`, { headers: { Authorization: `Bearer ${jwt}` } });
46476
46653
  return { status: r.status, json: await r.json().catch(() => ({})) };
@@ -46630,7 +46807,7 @@ __export(secrets_exports, {
46630
46807
  runRemoteSecretsCommand: () => runRemoteSecretsCommand,
46631
46808
  runSecretsCommand: () => runSecretsCommand
46632
46809
  });
46633
- import { readFileSync as readFileSync61 } from "node:fs";
46810
+ import { readFileSync as readFileSync62 } from "node:fs";
46634
46811
  function environment(value) {
46635
46812
  if (value === "preview" || value === "production") return value;
46636
46813
  throw new Error("--environment must be preview or production");
@@ -46640,9 +46817,9 @@ function required(value, flag) {
46640
46817
  return value;
46641
46818
  }
46642
46819
  function masterKey() {
46643
- const encoded = process.env.HIMI_SECRET_MASTER_KEY;
46644
- if (!encoded) throw new Error("HIMI_SECRET_MASTER_KEY is required (base64url-encoded 32-byte key)");
46645
- const key2 = Buffer.from(encoded, "base64url");
46820
+ const encoded2 = process.env.HIMI_SECRET_MASTER_KEY;
46821
+ if (!encoded2) throw new Error("HIMI_SECRET_MASTER_KEY is required (base64url-encoded 32-byte key)");
46822
+ const key2 = Buffer.from(encoded2, "base64url");
46646
46823
  if (key2.byteLength !== 32) throw new Error("HIMI_SECRET_MASTER_KEY must decode to exactly 32 bytes");
46647
46824
  return key2;
46648
46825
  }
@@ -46661,7 +46838,7 @@ async function runSecretsCommand(operation, flags, io, options = {}) {
46661
46838
  io.log(JSON.stringify(await vault.list({ app, environment: env })));
46662
46839
  return 0;
46663
46840
  }
46664
- const value = options.readValue ? options.readValue() : readFileSync61(0, "utf8").replace(/\r?\n$/, "");
46841
+ const value = options.readValue ? options.readValue() : readFileSync62(0, "utf8").replace(/\r?\n$/, "");
46665
46842
  if (operation === "set") await vault.set({ app, environment: env, name, value });
46666
46843
  else if (operation === "rotate") await vault.rotate({ app, environment: env, name, value });
46667
46844
  else throw new Error(`unknown secrets operation ${operation}`);
@@ -46690,7 +46867,7 @@ async function runRemoteSecretsCommand(operation, flags, io, options) {
46690
46867
  }
46691
46868
  let body;
46692
46869
  if (operation !== "list") {
46693
- const value = options.readValue ? options.readValue() : readFileSync61(0, "utf8").replace(/\r?\n$/, "");
46870
+ const value = options.readValue ? options.readValue() : readFileSync62(0, "utf8").replace(/\r?\n$/, "");
46694
46871
  body = JSON.stringify({ value });
46695
46872
  }
46696
46873
  const response = await (options.fetchImpl ?? fetch)(url, { method: operation === "list" ? "GET" : operation === "set" ? "PUT" : "POST", headers: headers2, body });
@@ -46726,7 +46903,7 @@ __export(notify_exports, {
46726
46903
  runNotify: () => runNotify,
46727
46904
  saveAdminSession: () => saveAdminSession
46728
46905
  });
46729
- import { chmodSync as chmodSync3, mkdirSync as mkdirSync24, readFileSync as readFileSync62, writeFileSync as writeFileSync21 } from "node:fs";
46906
+ import { chmodSync as chmodSync3, mkdirSync as mkdirSync24, readFileSync as readFileSync63, writeFileSync as writeFileSync21 } from "node:fs";
46730
46907
  import { homedir as homedir6 } from "node:os";
46731
46908
  import { dirname as dirname29, join as join49 } from "node:path";
46732
46909
  function defaultSessionsPath() {
@@ -46734,7 +46911,7 @@ function defaultSessionsPath() {
46734
46911
  }
46735
46912
  function loadSessionsFile(path = defaultSessionsPath()) {
46736
46913
  try {
46737
- return JSON.parse(readFileSync62(path, "utf8"));
46914
+ return JSON.parse(readFileSync63(path, "utf8"));
46738
46915
  } catch {
46739
46916
  return {};
46740
46917
  }
@@ -50710,10 +50887,10 @@ function patchGrids(src, installed, patch) {
50710
50887
  return out + src.slice(cursor);
50711
50888
  }
50712
50889
  function patchModules(src, installed, patch) {
50713
- return src.replace(/"homeModules": "((?:[^"\\]|\\.)*)"/g, (whole, encoded) => {
50890
+ return src.replace(/"homeModules": "((?:[^"\\]|\\.)*)"/g, (whole, encoded2) => {
50714
50891
  let modules;
50715
50892
  try {
50716
- const parsed = JSON.parse(JSON.parse(`"${encoded}"`));
50893
+ const parsed = JSON.parse(JSON.parse(`"${encoded2}"`));
50717
50894
  if (!Array.isArray(parsed)) return whole;
50718
50895
  modules = parsed;
50719
50896
  } catch {
@@ -50901,7 +51078,7 @@ var init_home_descriptor = __esm({
50901
51078
  });
50902
51079
 
50903
51080
  // src/site-analyze/apply.ts
50904
- import { existsSync as existsSync53, readFileSync as readFileSync63, writeFileSync as writeFileSync23, copyFileSync as copyFileSync3, mkdirSync as mkdirSync26, realpathSync as realpathSync5, statSync as statSync12 } from "node:fs";
51081
+ import { existsSync as existsSync54, readFileSync as readFileSync64, writeFileSync as writeFileSync23, copyFileSync as copyFileSync3, mkdirSync as mkdirSync26, realpathSync as realpathSync5, statSync as statSync12 } from "node:fs";
50905
51082
  import { dirname as dirname30, isAbsolute as isAbsolute4, join as join51, resolve as resolve42, sep as sep11 } from "node:path";
50906
51083
  import { spawnSync as spawnSync4 } from "node:child_process";
50907
51084
  function unpairedRedirectNote(overlay) {
@@ -50917,7 +51094,7 @@ function committedShellProvisioning(path) {
50917
51094
  function findRepoRoot(cwd) {
50918
51095
  let dir = cwd;
50919
51096
  for (let i = 0; i < 8; i++) {
50920
- if (SHELL_NAMES2.some((name) => existsSync53(join51(dir, shellAppDir(name), "package.json")))) return dir;
51097
+ if (SHELL_NAMES2.some((name) => existsSync54(join51(dir, shellAppDir(name), "package.json")))) return dir;
50921
51098
  const next = dirname30(dir);
50922
51099
  if (next === dir) break;
50923
51100
  dir = next;
@@ -50986,10 +51163,10 @@ function mergeCustomerOwned(committed, overlay) {
50986
51163
  function buildMergedContract(options) {
50987
51164
  const { appDir: appDir2, packageDir, overlay } = options;
50988
51165
  const committedPath = join51(appDir2, "provisioning.json");
50989
- if (!existsSync53(committedPath)) {
51166
+ if (!existsSync54(committedPath)) {
50990
51167
  throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
50991
51168
  }
50992
- const committed = JSON.parse(readFileSync63(committedPath, "utf8"));
51169
+ const committed = JSON.parse(readFileSync64(committedPath, "utf8"));
50993
51170
  const merged = mergeCustomerOwned(committed, overlay);
50994
51171
  const overlayFontFamily = (overlay.branding ?? {}).fontFamily;
50995
51172
  const branding = merged.branding ?? {};
@@ -51002,7 +51179,7 @@ function buildMergedContract(options) {
51002
51179
  const stage = (fromRel, toRel) => {
51003
51180
  const from = contained(packageDir, fromRel);
51004
51181
  const to = contained(join51(appDir2, STAGED), toRel.slice(STAGED.length + 1));
51005
- if (!from || !to || !existsSync53(from)) return void 0;
51182
+ if (!from || !to || !existsSync54(from)) return void 0;
51006
51183
  let real;
51007
51184
  let realRoot;
51008
51185
  try {
@@ -51025,10 +51202,10 @@ function buildMergedContract(options) {
51025
51202
  const icon = stage("media/icon.png", `${STAGED}/icon.png`);
51026
51203
  if (icon) branding.appIconPath = icon;
51027
51204
  const facesPath = join51(packageDir, "media/fonts/faces.json");
51028
- if (existsSync53(facesPath)) {
51205
+ if (existsSync54(facesPath)) {
51029
51206
  let faces = [];
51030
51207
  try {
51031
- const parsed = JSON.parse(readFileSync63(facesPath, "utf8"));
51208
+ const parsed = JSON.parse(readFileSync64(facesPath, "utf8"));
51032
51209
  faces = Array.isArray(parsed) ? parsed : [];
51033
51210
  } catch {
51034
51211
  faces = [];
@@ -51061,8 +51238,8 @@ async function applyOverlays(input) {
51061
51238
  const cwd = resolve42(input.cwd);
51062
51239
  const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
51063
51240
  assertKnownShell(shell);
51064
- const overlay = JSON.parse(readFileSync63(input.overlayPath, "utf8"));
51065
- const tokens = JSON.parse(readFileSync63(input.tokensPath, "utf8"));
51241
+ const overlay = JSON.parse(readFileSync64(input.overlayPath, "utf8"));
51242
+ const tokens = JSON.parse(readFileSync64(input.tokensPath, "utf8"));
51066
51243
  const wrote = [];
51067
51244
  const notes = [];
51068
51245
  const repoRoot2 = findRepoRoot(cwd);
@@ -51096,8 +51273,8 @@ async function applyOverlays(input) {
51096
51273
  }
51097
51274
  const pkgProv = join51(cwd, "provisioning.json");
51098
51275
  assertNotCommitted(pkgProv, input.forbiddenProvisioning);
51099
- if (existsSync53(pkgProv)) {
51100
- const cur = JSON.parse(readFileSync63(pkgProv, "utf8"));
51276
+ if (existsSync54(pkgProv)) {
51277
+ const cur = JSON.parse(readFileSync64(pkgProv, "utf8"));
51101
51278
  const merged = deepMerge4(cur, overlay);
51102
51279
  writeFileSync23(pkgProv, JSON.stringify(merged, null, 2) + "\n");
51103
51280
  wrote.push(pkgProv);
@@ -51106,8 +51283,8 @@ async function applyOverlays(input) {
51106
51283
  wrote.push(pkgProv);
51107
51284
  }
51108
51285
  const pkgTokens = join51(cwd, "tokens.json");
51109
- if (existsSync53(pkgTokens) && (tokens.colors || tokens.typography)) {
51110
- const cur = JSON.parse(readFileSync63(pkgTokens, "utf8"));
51286
+ if (existsSync54(pkgTokens) && (tokens.colors || tokens.typography)) {
51287
+ const cur = JSON.parse(readFileSync64(pkgTokens, "utf8"));
51111
51288
  const merged = deepMerge4(cur, tokens);
51112
51289
  const mergedColors = merged.colors;
51113
51290
  if (mergedColors && typeof mergedColors === "object" && !Array.isArray(mergedColors)) {
@@ -51118,8 +51295,8 @@ async function applyOverlays(input) {
51118
51295
  }
51119
51296
  const homeAction = homeRefreshActionId(shell);
51120
51297
  const homeSrc = join51(cwd, "dev/index.ts");
51121
- if (homeAction && existsSync53(homeSrc)) {
51122
- const prev = readFileSync63(homeSrc, "utf8");
51298
+ if (homeAction && existsSync54(homeSrc)) {
51299
+ const prev = readFileSync64(homeSrc, "utf8");
51123
51300
  const patched = patchBrandParams(prev, overlay, homeAction);
51124
51301
  let next = patched.src;
51125
51302
  if (!patched.foreign && overlay.installedVerticals?.length) {
@@ -51142,13 +51319,13 @@ async function applyOverlays(input) {
51142
51319
  notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
51143
51320
  }
51144
51321
  }
51145
- if (!input.iconPath || !existsSync53(input.iconPath)) {
51322
+ if (!input.iconPath || !existsSync54(input.iconPath)) {
51146
51323
  const book = input.iconPath ? dirname30(dirname30(resolve42(input.iconPath))) : void 0;
51147
51324
  notes.push(
51148
51325
  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"
51149
51326
  );
51150
51327
  }
51151
- if (input.iconPath && existsSync53(input.iconPath)) {
51328
+ if (input.iconPath && existsSync54(input.iconPath)) {
51152
51329
  try {
51153
51330
  const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
51154
51331
  wrote.push(...installed.wrote);
@@ -55302,7 +55479,7 @@ __export(cli_exports, {
55302
55479
  runSiteAnalyze: () => runSiteAnalyze,
55303
55480
  runSiteFunctionCli: () => runSiteFunctionCli
55304
55481
  });
55305
- import { readFileSync as readFileSync64 } from "node:fs";
55482
+ import { readFileSync as readFileSync65 } from "node:fs";
55306
55483
  import { resolve as resolve43 } from "node:path";
55307
55484
  function assetFetchFor(_opts) {
55308
55485
  return pinnedFetch2;
@@ -55389,7 +55566,7 @@ async function runSiteFunctionCli(opts) {
55389
55566
  let source;
55390
55567
  if (opts.sourcePath) {
55391
55568
  const p = resolve43(opts.cwd ?? process.cwd(), opts.sourcePath);
55392
- source = readFileSync64(p, "utf8");
55569
+ source = readFileSync65(p, "utf8");
55393
55570
  }
55394
55571
  let body;
55395
55572
  if (opts.bodyRaw != null) {
@@ -55646,7 +55823,7 @@ __export(site_create_exports, {
55646
55823
  runSiteList: () => runSiteList,
55647
55824
  writeProvisioningBinding: () => writeProvisioningBinding
55648
55825
  });
55649
- import { existsSync as existsSync54, readFileSync as readFileSync65, writeFileSync as writeFileSync24 } from "node:fs";
55826
+ import { existsSync as existsSync55, readFileSync as readFileSync66, writeFileSync as writeFileSync24 } from "node:fs";
55650
55827
  import { resolve as resolvePath2 } from "node:path";
55651
55828
  function oauthClientName(projectName) {
55652
55829
  return `${projectName} client`;
@@ -55795,7 +55972,7 @@ async function runSiteCreate(opts) {
55795
55972
  if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
55796
55973
  return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
55797
55974
  }
55798
- function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync54, readFileSync: readFileSync65, writeFileSync: writeFileSync24 }) {
55975
+ function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync55, readFileSync: readFileSync66, writeFileSync: writeFileSync24 }) {
55799
55976
  const msid = binding2.siteId;
55800
55977
  const path = resolvePath2(target);
55801
55978
  const committed = committedShellProvisioning(path);
@@ -56127,7 +56304,7 @@ var init_site_oauth_client = __esm({
56127
56304
  });
56128
56305
 
56129
56306
  // src/cli.ts
56130
- import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync66, mkdirSync as mkdirSync27, writeFileSync as writeFileSync25, existsSync as existsSync55, rmSync as rmSync10, readdirSync as readdirSync25, statSync as statSync13, lstatSync as lstatSync6, accessSync, constants } from "node:fs";
56307
+ import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync67, mkdirSync as mkdirSync27, writeFileSync as writeFileSync25, existsSync as existsSync56, rmSync as rmSync10, readdirSync as readdirSync25, statSync as statSync13, lstatSync as lstatSync6, accessSync, constants } from "node:fs";
56131
56308
  import { execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn5 } from "node:child_process";
56132
56309
  import { createHash as createHash24, randomUUID as randomUUID3 } from "node:crypto";
56133
56310
  import { tmpdir as tmpdir5, homedir as homedir7, hostname } from "node:os";
@@ -58574,6 +58751,14 @@ init_splash();
58574
58751
 
58575
58752
  // src/lint-report.ts
58576
58753
  init_himi_report();
58754
+ function nondeterministicWorkers(workers) {
58755
+ return (workers ?? []).filter((w) => w.nondeterministicServices?.length).map((w) => ({ bundle: w.bundle ?? "(unnamed)", services: [...w.nondeterministicServices] }));
58756
+ }
58757
+ function describeNondeterministicWorkers(workers) {
58758
+ const one = (w) => `worker "${w.bundle}" (${w.services.length === 1 ? "service" : "services"} ${w.services.join(", ")})`;
58759
+ return workers.length <= 1 ? workers.map(one).join("") : `${workers.slice(0, -1).map(one).join(", ")} and ${one(workers[workers.length - 1])}`;
58760
+ }
58761
+ var NONDETERMINISTIC_FIX = "move those clock or random values out of the service's initial state and compute them in an action instead (for example one the screen's onAppear dispatches)";
58577
58762
  function summarizeLint(app, bres, outcome, strict, extraIssues = []) {
58578
58763
  const issues = (outcome.lint ?? []).flatMap((s) => s.issues.map((i) => ({ screen: s.screenId, ...i })));
58579
58764
  issues.push(...extraIssues);
@@ -58622,8 +58807,20 @@ function summarizeLint(app, bres, outcome, strict, extraIssues = []) {
58622
58807
  message: failure.message
58623
58808
  });
58624
58809
  }
58810
+ for (const w of nondeterministicWorkers(outcome.workers)) {
58811
+ issues.push({
58812
+ screen: null,
58813
+ pass: "initial-state",
58814
+ severity: "warning",
58815
+ ruleCode: "nondeterministic-initial-state",
58816
+ bundle: w.bundle,
58817
+ path: w.bundle,
58818
+ services: w.services,
58819
+ message: `${describeNondeterministicWorkers([w])} builds a different initial state depending on when it is built \u2014 it reads the clock or Math.random() while it boots, and that state is hashed into the release. So builds of this unchanged source produce different releases (a new releaseId off-repo; new content under the same id in-repo), and a mobile-UX drive or attestation recorded against one build will not match the release a later push builds. To fix it, ${NONDETERMINISTIC_FIX}.`
58820
+ });
58821
+ }
58625
58822
  const errorIssues = issues.filter((i) => i.severity === "error");
58626
- const workers = (outcome.workers ?? []).filter((w) => w.threw || w.console.length);
58823
+ const workers = (outcome.workers ?? []).filter((w) => w.threw || w.console.length || w.nondeterministicServices?.length);
58627
58824
  const workerThrows = workers.filter((w) => w.threw);
58628
58825
  const hasErrors = bres.compileErrors.length > 0 || outcome.failedToBuild.length > 0 || outcome.missingBundles.length > 0 || errorIssues.length > 0 || workerThrows.length > 0;
58629
58826
  const legacy = {
@@ -59389,7 +59586,7 @@ var num = (v) => typeof v === "string" && v !== "" && Number.isFinite(Number(v))
59389
59586
  function embeddedTemplateCatalog() {
59390
59587
  return availableTemplates().map((name) => {
59391
59588
  const path = join52(templateSourceDir(name), TEMPLATE_META_FILE);
59392
- const meta = JSON.parse(readFileSync66(path, "utf8"));
59589
+ const meta = JSON.parse(readFileSync67(path, "utf8"));
59393
59590
  if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
59394
59591
  throw new Error(`${path} must be { title: string, description: string, tags: string[], category?: string }`);
59395
59592
  }
@@ -60031,7 +60228,7 @@ var COMMANDS = [
60031
60228
  ];
60032
60229
  function cliVersion() {
60033
60230
  try {
60034
- return JSON.parse(readFileSync66(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
60231
+ return JSON.parse(readFileSync67(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
60035
60232
  } catch {
60036
60233
  return "unknown";
60037
60234
  }
@@ -60126,7 +60323,7 @@ function ageInDays(publishedAt, now = Date.now()) {
60126
60323
  }
60127
60324
  function packageVersion(path) {
60128
60325
  try {
60129
- const version2 = JSON.parse(readFileSync66(path, "utf8")).version;
60326
+ const version2 = JSON.parse(readFileSync67(path, "utf8")).version;
60130
60327
  return typeof version2 === "string" && version2 ? version2 : void 0;
60131
60328
  } catch {
60132
60329
  return void 0;
@@ -60196,7 +60393,7 @@ function updateCachePath(env = process.env) {
60196
60393
  }
60197
60394
  function readUpdateCache(path) {
60198
60395
  try {
60199
- const parsed = JSON.parse(readFileSync66(path, "utf8"));
60396
+ const parsed = JSON.parse(readFileSync67(path, "utf8"));
60200
60397
  return parsed && typeof parsed === "object" ? parsed : {};
60201
60398
  } catch {
60202
60399
  return {};
@@ -60269,7 +60466,7 @@ function createUpdateRunner(spawn6 = spawnSync5) {
60269
60466
  reexec: (argv) => {
60270
60467
  const root = globalNodeModulesRoot();
60271
60468
  const entry = root ? join52(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
60272
- if (!entry || !existsSync55(entry)) return void 0;
60469
+ if (!entry || !existsSync56(entry)) return void 0;
60273
60470
  const result = spawnSync5(process.execPath, [entry, ...argv], {
60274
60471
  // inherit keeps PIPED STDIN working — commands that read stdin must survive a re-exec.
60275
60472
  stdio: "inherit",
@@ -60316,7 +60513,7 @@ function staleUpdateLockFile(cachePath, now) {
60316
60513
  for (const path of [`${cachePath}.lock.break`, `${cachePath}.lock`]) {
60317
60514
  let content;
60318
60515
  try {
60319
- content = readFileSync66(path, "utf8");
60516
+ content = readFileSync67(path, "utf8");
60320
60517
  } catch {
60321
60518
  continue;
60322
60519
  }
@@ -60339,7 +60536,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
60339
60536
  const mine = lockStamp(now);
60340
60537
  const readLock = (path) => {
60341
60538
  try {
60342
- return readFileSync66(path, "utf8");
60539
+ return readFileSync67(path, "utf8");
60343
60540
  } catch {
60344
60541
  return void 0;
60345
60542
  }
@@ -60979,7 +61176,7 @@ async function nativeConfigAdvisories(app, configSource) {
60979
61176
  const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
60980
61177
  const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
60981
61178
  const iosYmlPath = iosProjectYml2(app);
60982
- const iosYml = existsSync55(iosYmlPath) ? readFileSync66(iosYmlPath, "utf8") : "";
61179
+ const iosYml = existsSync56(iosYmlPath) ? readFileSync67(iosYmlPath, "utf8") : "";
60983
61180
  let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
60984
61181
  if (!optedIn) {
60985
61182
  const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
@@ -60993,7 +61190,7 @@ async function nativeConfigAdvisories(app, configSource) {
60993
61190
  }
60994
61191
  function readConfigSource(dir) {
60995
61192
  try {
60996
- return readFileSync66(join52(dir, "config.ts"), "utf8");
61193
+ return readFileSync67(join52(dir, "config.ts"), "utf8");
60997
61194
  } catch {
60998
61195
  return null;
60999
61196
  }
@@ -61005,7 +61202,7 @@ function writePngFile(path, base64) {
61005
61202
  }
61006
61203
  async function initFromRemoteTemplate(name, parentDir, template, c) {
61007
61204
  const dir = resolve44(parentDir, name);
61008
- if (existsSync55(join52(dir, "himalaya.content.json"))) {
61205
+ if (existsSync56(join52(dir, "himalaya.content.json"))) {
61009
61206
  throw new Error(`content package already exists at ${dir}`);
61010
61207
  }
61011
61208
  const r = await c.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
@@ -61048,7 +61245,7 @@ function symlinkDestinationIssue(dest) {
61048
61245
  function restoreDestinationIssue(dest, force) {
61049
61246
  const link = symlinkDestinationIssue(dest);
61050
61247
  if (link) return link;
61051
- if (!existsSync55(dest)) return null;
61248
+ if (!existsSync56(dest)) return null;
61052
61249
  if (!statSync13(dest).isDirectory()) {
61053
61250
  return { error: `${dest} exists and is not a directory`, hint: "pass --out/--name to land somewhere else, or remove the file" };
61054
61251
  }
@@ -61063,7 +61260,7 @@ function restoreDestinationIssue(dest, force) {
61063
61260
  function isHimalayaMonorepoCheckout(start) {
61064
61261
  let dir = resolve44(start);
61065
61262
  for (; ; ) {
61066
- if (existsSync55(join52(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync55(join52(dir, "core", "serve", "src", "server.ts"))) return true;
61263
+ if (existsSync56(join52(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync56(join52(dir, "core", "serve", "src", "server.ts"))) return true;
61067
61264
  const parent = dirname31(dir);
61068
61265
  if (parent === dir) return false;
61069
61266
  dir = parent;
@@ -61133,8 +61330,8 @@ function materializeForPreview(appDir2, slug, displayName) {
61133
61330
  }
61134
61331
  async function appId(dir) {
61135
61332
  try {
61136
- const { readFileSync: readFileSync67 } = await import("node:fs");
61137
- const m = JSON.parse(readFileSync67(join52(dir, "himalaya.content.json"), "utf8"));
61333
+ const { readFileSync: readFileSync68 } = await import("node:fs");
61334
+ const m = JSON.parse(readFileSync68(join52(dir, "himalaya.content.json"), "utf8"));
61138
61335
  if (m.name) return m.name;
61139
61336
  } catch {
61140
61337
  }
@@ -61142,8 +61339,8 @@ async function appId(dir) {
61142
61339
  }
61143
61340
  async function contentVisibility(dir) {
61144
61341
  try {
61145
- const { readFileSync: readFileSync67 } = await import("node:fs");
61146
- const m = JSON.parse(readFileSync67(join52(dir, "himalaya.content.json"), "utf8"));
61342
+ const { readFileSync: readFileSync68 } = await import("node:fs");
61343
+ const m = JSON.parse(readFileSync68(join52(dir, "himalaya.content.json"), "utf8"));
61147
61344
  if (m.visibility === "public" || m.visibility === "unlisted") return m.visibility;
61148
61345
  } catch {
61149
61346
  }
@@ -61362,16 +61559,18 @@ function resolutionFlag(flags) {
61362
61559
  if (flags.source === true) return "source";
61363
61560
  return void 0;
61364
61561
  }
61365
- async function recordedReleaseForContentQuietly(dir, resolution) {
61562
+ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
61366
61563
  let out;
61367
61564
  try {
61368
61565
  const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
61369
61566
  const bres = await buildContentForValidation2(dir, { resolution });
61370
61567
  out = mkdtempSync4(join52(tmpdir5(), "himi-ux-record-"));
61371
61568
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
61372
- const outcome = await buildReleaseFromContent2(dir, out, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {} });
61569
+ const outcome = await buildReleaseFromContent2(dir, out, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {}, collect: { lint: true } });
61373
61570
  const releaseId = outcome.manifest.releaseId;
61374
61571
  if (!releaseId) return null;
61572
+ const drifting = nondeterministicWorkers(outcome.workers);
61573
+ if (drifting.length) onDrift?.(drifting);
61375
61574
  const payload = await loadReleaseFromDir(await appId(dir), out);
61376
61575
  return { releaseId, releaseHash: releasePayloadHash(payload) };
61377
61576
  } catch {
@@ -61400,6 +61599,10 @@ function handoverUxEvidence(dir, release) {
61400
61599
  }
61401
61600
  return evidence;
61402
61601
  }
61602
+ function releaseDriftCause(workers, redo, evidence) {
61603
+ const one = workers.length === 1;
61604
+ return `${redo} alone cannot reliably clear this: ${describeNondeterministicWorkers(workers)} ${one ? "builds" : "build"} a different initial state depending on when ${one ? "it is" : "they are"} built \u2014 ${one ? "it reads" : "they read"} the clock or Math.random() while booting, and that state is hashed into the release \u2014 so this unchanged package builds a different release from one run to the next, and ${evidence} recorded now cannot be relied on to match the release the next push builds. First ${NONDETERMINISTIC_FIX}`;
61605
+ }
61403
61606
  function uxRecordCommands(contentPath) {
61404
61607
  return `\`himi ux audit --content ${contentPath} --strict\`, then \`himi ux record --content ${contentPath} --platform ios --status unavailable --reason "<why you could not drive it>"\``;
61405
61608
  }
@@ -61421,7 +61624,11 @@ function uxHandoverHint(uxEvidence, ctx) {
61421
61624
  if (uxEvidence.state === "failed") {
61422
61625
  return `a mobile-UX drive for ${releaseId} IS recorded, and it FAILED on ${uxEvidence.failedPlatforms.join(", ")} (see ${uxEvidence.path}). A published draft is the owner-private preview a customer is handed, so fix what the drive found and re-record it \u2014 re-running \`himi ux record\` over a failure without changing the app just writes the same failure down again. Only if you intend to hand a customer a preview whose UX you already know is broken, \`${door} --force\`.`;
61423
61626
  }
61424
- const why = uxEvidence.state === "absent" ? `nothing has recorded a mobile-UX drive for this package \u2014 ${uxEvidence.path} does not exist` : uxEvidence.state === "unrecorded" ? uxEvidence.malformed.length ? `${uxEvidence.path} has no iOS or Android drive this gate can read \u2014 ${uxEvidence.malformed.join("; ")}` : `${uxEvidence.path} exists but carries no iOS or Android drive (\`himi render\` writes its rendered widths there too, so the file alone proves nothing)` : uxEvidence.state === "unreadable" ? `${ctx.quote(`${ctx.contentDir}/${uxEvidence.path}`)} ${uxEvidence.error} \u2014 delete it and record again, because re-recording over a malformed store does not repair it` : uxEvidence.state === "outdated" ? `a mobile-UX drive for ${releaseId} is recorded, but the package has CHANGED since \u2014 in-repo a release id is the git HEAD sha, so editing a screen, a token or a worker without committing keeps the id while replacing everything it identifies (a record written before this check also lands here, carrying no content hash)` : `the recorded mobile-UX drive is about ${uxEvidence.otherReleases.length ? `release ${uxEvidence.otherReleases.join(", ")}` : "no release at all"}, not ${releaseId}${uxEvidence.unstamped ? ` (${uxEvidence.unstamped} drive(s) name no release)` : ""}`;
61627
+ const why = uxEvidence.state === "absent" ? `nothing has recorded a mobile-UX drive for this package \u2014 ${uxEvidence.path} does not exist` : uxEvidence.state === "unrecorded" ? uxEvidence.malformed.length ? `${uxEvidence.path} has no iOS or Android drive this gate can read \u2014 ${uxEvidence.malformed.join("; ")}` : `${uxEvidence.path} exists but carries no iOS or Android drive (\`himi render\` writes its rendered widths there too, so the file alone proves nothing)` : uxEvidence.state === "unreadable" ? `${ctx.quote(`${ctx.contentDir}/${uxEvidence.path}`)} ${uxEvidence.error} \u2014 delete it and record again, because re-recording over a malformed store does not repair it` : uxEvidence.state === "outdated" && ctx.nondeterministicWorkers?.length ? `a mobile-UX drive for ${releaseId} is recorded, but it describes different content from the release this push just built \u2014 an uncommitted edit since the record would do that, and so does the worker named below` : uxEvidence.state === "outdated" ? `a mobile-UX drive for ${releaseId} is recorded, but the package has CHANGED since \u2014 in-repo a release id is the git HEAD sha, so editing a screen, a token or a worker without committing keeps the id while replacing everything it identifies (a record written before this check also lands here, carrying no content hash)` : `the recorded mobile-UX drive is about ${uxEvidence.otherReleases.length ? `release ${uxEvidence.otherReleases.join(", ")}` : "no release at all"}, not ${releaseId}${uxEvidence.unstamped ? ` (${uxEvidence.unstamped} drive(s) name no release)` : ""}`;
61628
+ const drifting = ctx.nondeterministicWorkers ?? [];
61629
+ if (drifting.length > 0) {
61630
+ return `${why}. ${releaseDriftCause(drifting, "Re-recording", "a drive")}; then record the drive: ${uxRemedy}, and re-run \`${door}\`. Only if you intend to hand over a preview WITHOUT that evidence, \`${door} --force\`.`;
61631
+ }
61425
61632
  return `${why}. A published draft is the owner-private preview a customer is handed, so record the drive first: ${uxRemedy}, then re-run \`${door}\`. Only if you intend to hand over a preview WITHOUT that evidence, \`${door} --force\`.`;
61426
61633
  }
61427
61634
  var SECRET_FLAG_NAME = /token|secret|password|cookie|auth/i;
@@ -61448,10 +61655,18 @@ function uxHandoverNote(uxEvidence, ctx) {
61448
61655
  if (uxEvidence.state === "failed") {
61449
61656
  return `published over a FAILED mobile-UX drive for ${ctx.releaseId} on ${uxEvidence.failedPlatforms.join(", ")}. The preview link below is the owner-private handover \u2014 fix what the drive found and publish again before a customer reviews it.`;
61450
61657
  }
61658
+ const drifting = ctx.nondeterministicWorkers ?? [];
61659
+ const driftCause = drifting.length > 0 ? releaseDriftCause(drifting, "Re-recording", "a drive") : null;
61451
61660
  if (uxEvidence.state === "unreadable") {
61452
61661
  const why = uxEvidence.error ? ` \u2014 ${uxEvidence.path} ${uxEvidence.error}` : ` \u2014 ${uxEvidence.path} could not be read`;
61662
+ if (driftCause) {
61663
+ return `published with no mobile-UX drive this gate accepts for ${ctx.releaseId} (unreadable)${why}. The preview link below is the owner-private handover \u2014 DELETE ${ctx.quote(`${ctx.contentDir}/${uxEvidence.path}`)}, because re-recording over a malformed store does not repair it. ${driftCause}; then record the drive again with \`himi ux record --content ${ctx.contentArg} \u2026\`, and publish again before a customer reviews it.`;
61664
+ }
61453
61665
  return `published with no mobile-UX drive this gate accepts for ${ctx.releaseId} (unreadable)${why}. The preview link below is the owner-private handover \u2014 DELETE ${ctx.quote(`${ctx.contentDir}/${uxEvidence.path}`)} and record the drive again with \`himi ux record --content ${ctx.contentArg} \u2026\`, because re-recording over a malformed store does not repair it, then publish again before a customer reviews it.`;
61454
61666
  }
61667
+ if (driftCause) {
61668
+ return `published with no mobile-UX drive this gate accepts for ${ctx.releaseId} (${uxEvidence.state}). The preview link below is the owner-private handover. ${driftCause}; then record the drive with \`himi ux record --content ${ctx.contentArg} \u2026\` and publish again before a customer reviews it.`;
61669
+ }
61455
61670
  return `published with no mobile-UX drive this gate accepts for ${ctx.releaseId} (${uxEvidence.state}). The preview link below is the owner-private handover \u2014 record the drive with \`himi ux record --content ${ctx.contentArg} \u2026\` and publish again before a customer reviews it.`;
61456
61671
  }
61457
61672
  function uxHandoverOverride(uxEvidence, ctx) {
@@ -61527,7 +61742,7 @@ async function producedWidgetFamilies(dir) {
61527
61742
  let js;
61528
61743
  for (const candidate of [`${name}.bundle.js`, `${name}.js`, name]) {
61529
61744
  try {
61530
- js = readFileSync66(join52(outDir, candidate), "utf8");
61745
+ js = readFileSync67(join52(outDir, candidate), "utf8");
61531
61746
  break;
61532
61747
  } catch {
61533
61748
  }
@@ -61902,7 +62117,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
61902
62117
  const sourceDir = resolve44(str5(flags["source-dir"]) ?? appDir2);
61903
62118
  let meta;
61904
62119
  try {
61905
- meta = JSON.parse(readFileSync66(join52(sourceDir, TEMPLATE_META_FILE), "utf8"));
62120
+ meta = JSON.parse(readFileSync67(join52(sourceDir, TEMPLATE_META_FILE), "utf8"));
61906
62121
  } catch {
61907
62122
  io.error(JSON.stringify({ error: `no ${TEMPLATE_META_FILE} in ${sourceDir} \u2014 a template must declare { title, description, tags } to be published`, hint: `add ${TEMPLATE_META_FILE} next to himalaya.content.json (or pass --source-dir <dir>)` }));
61908
62123
  return 2;
@@ -61912,7 +62127,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
61912
62127
  return 2;
61913
62128
  }
61914
62129
  try {
61915
- const appearance = extractTemplateAppearance(JSON.parse(readFileSync66(join52(sourceDir, "tokens.json"), "utf8")));
62130
+ const appearance = extractTemplateAppearance(JSON.parse(readFileSync67(join52(sourceDir, "tokens.json"), "utf8")));
61916
62131
  meta = { ...appearance, ...meta };
61917
62132
  } catch {
61918
62133
  }
@@ -61977,7 +62192,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
61977
62192
  let iconHash;
61978
62193
  if (iconPath) {
61979
62194
  try {
61980
- const bytes2 = readFileSync66(iconPath);
62195
+ const bytes2 = readFileSync67(iconPath);
61981
62196
  payload.icon = bytes2.toString("base64");
61982
62197
  iconHash = createHash24("sha256").update(bytes2).digest("hex");
61983
62198
  } catch {
@@ -62247,7 +62462,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
62247
62462
  const path = dpxSessionTokenPath();
62248
62463
  let raw;
62249
62464
  try {
62250
- raw = readFileSync66(path, "utf8");
62465
+ raw = readFileSync67(path, "utf8");
62251
62466
  } catch {
62252
62467
  throw new Error(`no DPX BO session at ${path}; run dpx auth login, write dpx auth token to that path, then himi login --dpx --target bo`);
62253
62468
  }
@@ -62387,7 +62602,10 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
62387
62602
  io.error(JSON.stringify({ error: `ux record needs --status ${NATIVE_AUDIT_STATUSES.join("|")}` }));
62388
62603
  return 2;
62389
62604
  }
62390
- const uxRelease = await recordedReleaseForContentQuietly(dir, resolutionFlag(flags));
62605
+ let drifting = [];
62606
+ const uxRelease = await recordedReleaseForContentQuietly(dir, resolutionFlag(flags), (workers) => {
62607
+ drifting = workers;
62608
+ });
62391
62609
  try {
62392
62610
  const evidence = recordNativeAudit(dir, platform, status, checks, str5(flags.reason), uxRelease ?? void 0);
62393
62611
  print({
@@ -62398,6 +62616,11 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
62398
62616
  ...uxRelease ? {} : {
62399
62617
  releaseIdNote: "this package could not be built, so the record names no release \u2014 `himi push` will not accept it as evidence for the release it publishes. Fix the build and re-run this command."
62400
62618
  },
62619
+ // #3049 — still written (it is honest about what was driven), but said NOW: the push is
62620
+ // the next step, and without this line it is where the author would find out.
62621
+ ...drifting.length ? {
62622
+ releaseIdWarning: `this record will not reliably match the release \`himi push\` builds: ${describeNondeterministicWorkers(drifting)} ${drifting.length === 1 ? "builds" : "build"} a different initial state depending on when ${drifting.length === 1 ? "it is" : "they are"} built, and that state is hashed into the release. First ${NONDETERMINISTIC_FIX}; then record again, immediately before the push.`
62623
+ } : {},
62401
62624
  evidence
62402
62625
  });
62403
62626
  return 0;
@@ -62409,7 +62632,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
62409
62632
  case "test": {
62410
62633
  const dir = contentDir(flags);
62411
62634
  const structuredOutput = flags.json === true || io.isTTY !== true;
62412
- if (existsSync55(join52(dir, "functions"))) {
62635
+ if (existsSync56(join52(dir, "functions"))) {
62413
62636
  const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
62414
62637
  const loaded = await loadFunctionsApp2(dir);
62415
62638
  const results = [];
@@ -62829,7 +63052,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
62829
63052
  return 2;
62830
63053
  }
62831
63054
  try {
62832
- const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync66(stateArg.replace(/^@/, ""), "utf8");
63055
+ const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync67(stateArg.replace(/^@/, ""), "utf8");
62833
63056
  injectedState = JSON.parse(raw);
62834
63057
  } catch (e) {
62835
63058
  io.error(JSON.stringify({ error: `--state must be inline JSON or a path to a .json file \u2014 ${e.message}` }));
@@ -62844,7 +63067,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
62844
63067
  return 2;
62845
63068
  }
62846
63069
  try {
62847
- const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync66(inputArg.replace(/^@/, ""), "utf8");
63070
+ const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync67(inputArg.replace(/^@/, ""), "utf8");
62848
63071
  const parsed = JSON.parse(raw);
62849
63072
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("must be a JSON object");
62850
63073
  injectedInput = parsed;
@@ -63241,7 +63464,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
63241
63464
  io.error(JSON.stringify(linked));
63242
63465
  return 1;
63243
63466
  }
63244
- if (existsSync55(dest)) {
63467
+ if (existsSync56(dest)) {
63245
63468
  if (!statSync13(dest).isDirectory()) {
63246
63469
  io.error(JSON.stringify({
63247
63470
  error: `${dest} exists and is not a directory`,
@@ -63254,7 +63477,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
63254
63477
  io.error(JSON.stringify({ error: `${dest} already exists and is not empty`, hint: "pass --force to write into it anyway (merging, and naming what it keeps), --replace to restore exactly what was archived, or --out/--name to land somewhere else" }));
63255
63478
  return 1;
63256
63479
  }
63257
- if (replace && occupied && !existsSync55(join52(dest, "himalaya.content.json"))) {
63480
+ if (replace && occupied && !existsSync56(join52(dest, "himalaya.content.json"))) {
63258
63481
  io.error(JSON.stringify({
63259
63482
  error: `${dest} is not a content package \u2014 refusing to --replace it`,
63260
63483
  hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
@@ -63473,7 +63696,10 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
63473
63696
  // bytes to drive.
63474
63697
  baseReleaseId: baseForPlan.manifest.releaseId,
63475
63698
  quote: shellQuote2,
63476
- planeArgs: planeArguments(flags, shellQuote2)
63699
+ planeArgs: planeArguments(flags, shellQuote2),
63700
+ // The patch door reads the same build, so a drifting worker makes its record just as
63701
+ // unmatchable — the partial publish is not exempt from the loop (#3049).
63702
+ nondeterministicWorkers: nondeterministicWorkers(outcome.workers)
63477
63703
  };
63478
63704
  let localSourceHash;
63479
63705
  try {
@@ -63528,15 +63754,15 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
63528
63754
  return 1;
63529
63755
  }
63530
63756
  const zip = zipAppSource2(collected.entries);
63531
- const encoded = zip.toString("base64");
63532
- if (encoded.length > MAX_APP_SOURCE_BYTES2) {
63757
+ const encoded2 = zip.toString("base64");
63758
+ if (encoded2.length > MAX_APP_SOURCE_BYTES2) {
63533
63759
  const largest = largestEntries2(collected.entries);
63534
63760
  io.error(JSON.stringify({
63535
63761
  ok: false,
63536
63762
  pushed: false,
63537
63763
  error: "app_source_too_large",
63538
63764
  archivedBytes: zip.length,
63539
- encodedBytes: encoded.length,
63765
+ encodedBytes: encoded2.length,
63540
63766
  limit: MAX_APP_SOURCE_BYTES2,
63541
63767
  files: collected.entries.length,
63542
63768
  largest,
@@ -63544,7 +63770,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
63544
63770
  }));
63545
63771
  return 1;
63546
63772
  }
63547
- appSourceB64 = encoded;
63773
+ appSourceB64 = encoded2;
63548
63774
  sourceSummary = {
63549
63775
  files: collected.entries.length,
63550
63776
  compressed: zip.length,
@@ -63552,6 +63778,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
63552
63778
  };
63553
63779
  }
63554
63780
  const evidence = pushEvidence(dir, manifest.releaseId, (candidate) => verifyAttestation(candidate, dir, payload.screens, declared, payload, { requireLatest: false }).ok);
63781
+ const drifting = nondeterministicWorkers(outcome.workers);
63555
63782
  const staleEvidence = evidence.staleRuns > 0 ? `${evidence.staleRuns} retained attestation(s) carry this release id, but none describes the content being published` : null;
63556
63783
  const attestationErrors = [...evidence.historyErrors, ...staleEvidence ? [staleEvidence] : []];
63557
63784
  if (attestationErrors.length > 0 && !force) {
@@ -63561,7 +63788,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
63561
63788
  ok: false,
63562
63789
  pushed: false,
63563
63790
  errors: attestationErrors,
63564
- hint: corrupted ? `attestation history in .himi/attestations/ is corrupt, so the retained runs cannot be trusted \u2014 a fresh run does not remove the bad entry. Delete .himi/attestations/, re-attest with ${remedy}, then re-run \`himi push\`. Only if you intend to publish WITHOUT that evidence, \`himi push --force\`.` : `no retained attestation for this release passed live verification \u2014 a release id is the HEAD sha, so runs recorded before your latest edits still carry it while describing a tree that no longer exists. Re-attest the CURRENT release with ${remedy}, then re-run \`himi push\`. Only if you intend to publish WITHOUT that evidence, \`himi push --force\`.`
63791
+ hint: corrupted ? `attestation history in .himi/attestations/ is corrupt, so the retained runs cannot be trusted \u2014 a fresh run does not remove the bad entry. Delete .himi/attestations/, re-attest with ${remedy}, then re-run \`himi push\`. Only if you intend to publish WITHOUT that evidence, \`himi push --force\`.` : `no retained attestation for this release passed live verification${drifting.length ? `. ${releaseDriftCause(drifting, "Re-attesting", "an attestation")}, then re-attest` : " \u2014 a release id is the HEAD sha, so runs recorded before your latest edits still carry it while describing a tree that no longer exists. Re-attest"} the CURRENT release with ${remedy}, then re-run \`himi push\`. Only if you intend to publish WITHOUT that evidence, \`himi push --force\`.`
63565
63792
  });
63566
63793
  return 1;
63567
63794
  }
@@ -63597,9 +63824,10 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
63597
63824
  contentDir: contentRel,
63598
63825
  app,
63599
63826
  door: echoedInvocation("himi push", flags, shellQuote2),
63600
- quote: shellQuote2
63827
+ quote: shellQuote2,
63601
63828
  // No `baseReleaseId`: a full push derives from nothing, so it can never produce
63602
63829
  // `inherited-screens` and has no base to restore.
63830
+ nondeterministicWorkers: drifting
63603
63831
  })
63604
63832
  });
63605
63833
  return 1;
@@ -63758,7 +63986,10 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
63758
63986
  contentDir: contentRel,
63759
63987
  app,
63760
63988
  door: echoedInvocation("himi push", flags, shellQuote2),
63761
- quote: shellQuote2
63989
+ quote: shellQuote2,
63990
+ // #3049 — the same workers the refusal above was told about, so the forced note does
63991
+ // not answer "record it and publish again" to a build that moves the release itself.
63992
+ nondeterministicWorkers: drifting
63762
63993
  }),
63763
63994
  ...loopbackWarning ? { warning: loopbackWarning } : {},
63764
63995
  ...report2.issues ? { issues: report2.issues } : {},
@@ -64108,7 +64339,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
64108
64339
  }));
64109
64340
  return 1;
64110
64341
  }
64111
- const archive = readFileSync66(resolve44(file));
64342
+ const archive = readFileSync67(resolve44(file));
64112
64343
  const result = await client2().createPackageShare({
64113
64344
  app: opened.header.app,
64114
64345
  releaseId: opened.header.releaseId,
@@ -64752,7 +64983,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
64752
64983
  io.error(JSON.stringify({ error: `patch ${kind} needs --file`, usage: PATCH_USAGE }));
64753
64984
  return 2;
64754
64985
  }
64755
- if (!existsSync55(file)) {
64986
+ if (!existsSync56(file)) {
64756
64987
  io.error(JSON.stringify({ error: `no such file: ${file}` }));
64757
64988
  return 2;
64758
64989
  }
@@ -64808,7 +65039,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
64808
65039
  lintNote: "`himi patch` sends a raw file. Nothing here built or linted your app \u2014 `himi push --only <selector>` is the same edit with the full lint gate in front of it."
64809
65040
  };
64810
65041
  if (kind === "tokens" || kind === "app-config") {
64811
- const body = readFileSync66(file, "utf8");
65042
+ const body = readFileSync67(file, "utf8");
64812
65043
  const patch2 = kind === "tokens" ? { tokens: body } : { appConfig: body };
64813
65044
  return runReleasePatch({
64814
65045
  ...common,
@@ -64823,7 +65054,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
64823
65054
  io.error(JSON.stringify({ error: "patch screen needs a <screenId>", usage: PATCH_USAGE }));
64824
65055
  return 2;
64825
65056
  }
64826
- const descriptor = readFileSync66(file, "utf8");
65057
+ const descriptor = readFileSync67(file, "utf8");
64827
65058
  try {
64828
65059
  JSON.parse(descriptor);
64829
65060
  } catch (e) {
@@ -64863,7 +65094,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
64863
65094
  extra: { kind, screen: id, file: { path: file, bytes: Buffer.byteLength(descriptor, "utf8") } }
64864
65095
  });
64865
65096
  }
64866
- const bytes2 = readFileSync66(file);
65097
+ const bytes2 = readFileSync67(file);
64867
65098
  const sha = createHash24("sha256").update(bytes2).digest("hex");
64868
65099
  const forScreens = (str5(flags["for-screen"]) ?? "").split(",").map((s) => s.trim()).filter(Boolean);
64869
65100
  if (flags["no-rebind"] !== void 0 && flags["no-rebind"] !== true) {
@@ -65007,7 +65238,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
65007
65238
  }
65008
65239
  let def;
65009
65240
  try {
65010
- const parsed = JSON.parse(arg.startsWith("@") ? readFileSync66(arg.slice(1), "utf8") : arg);
65241
+ const parsed = JSON.parse(arg.startsWith("@") ? readFileSync67(arg.slice(1), "utf8") : arg);
65011
65242
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
65012
65243
  io.error(JSON.stringify({ error: "invalid_definition", problems: [`--definition must be a JSON object, got ${Array.isArray(parsed) ? "an array" : parsed === null ? "null" : typeof parsed}`] }));
65013
65244
  return 2;
@@ -65471,7 +65702,7 @@ ${label2}`);
65471
65702
  const platform = str5(flags.platform)?.split(",").map((p) => p.trim()).filter(Boolean);
65472
65703
  {
65473
65704
  const distDir = contentDir(flags);
65474
- if (existsSync55(join52(distDir, "himalaya.content.json"))) {
65705
+ if (existsSync56(join52(distDir, "himalaya.content.json"))) {
65475
65706
  const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
65476
65707
  const errors = issues.filter((i) => i.severity === "error");
65477
65708
  for (const i of issues.filter((i2) => i2.severity === "warning")) {
@@ -65740,7 +65971,7 @@ ${label2}`);
65740
65971
  const dpxPath = dpxSessionTokenPath();
65741
65972
  let dpx;
65742
65973
  try {
65743
- dpx = readFileSync66(dpxPath, "utf8").trim();
65974
+ dpx = readFileSync67(dpxPath, "utf8").trim();
65744
65975
  } catch {
65745
65976
  io.error(JSON.stringify({ error: `no dpx session at ${dpxPath} \u2014 run \`dpx auth login\` then \`dpx auth token > ${dpxPath}\` (dpx 2.x keeps its own state in ~/.dpx/auth.json and does NOT write the legacy session file), or omit --dpx` }));
65746
65977
  return 1;
@@ -66141,7 +66372,7 @@ ${report2.ok ? "OK \u2014 data + serve plane reachable." : typeof report2.hint =
66141
66372
  const path = dpxSessionTokenPath();
66142
66373
  let raw;
66143
66374
  try {
66144
- raw = readFileSync66(path, "utf8");
66375
+ raw = readFileSync67(path, "utf8");
66145
66376
  } catch {
66146
66377
  io.error(JSON.stringify({ error: `no DPX BO session at ${path}` }));
66147
66378
  return 1;
@@ -66553,6 +66784,7 @@ export {
66553
66784
  readUpdateCache,
66554
66785
  refreshUpdateCache,
66555
66786
  registryCandidates,
66787
+ releaseDriftCause,
66556
66788
  renderDataSource,
66557
66789
  renderDeviceWidths,
66558
66790
  resolveAppSlug,