@wix/himalaya-cli 0.1441.0 → 0.1443.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.
Files changed (161) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/app-config.d.ts +30 -3
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/state/src/index.d.ts +7 -0
  3. package/dist/cli.mjs +627 -389
  4. package/dist/preview-assets.generated.bin +0 -0
  5. package/guides/hhp.md +4 -0
  6. package/guides/himi-json-output.md +1 -1
  7. package/guides/himi-test.md +3 -2
  8. package/guides/sdk-reference.json +1 -1
  9. package/package.json +2 -2
  10. package/templates/beauty-salon/tier5-src/_shared/collection-query.ts +32 -5
  11. package/templates/beauty-salon/tier5-src/_shared/collection-service.ts +2 -1
  12. package/templates/beauty-salon-owner/tier5-src/_shared/collection-query.ts +32 -5
  13. package/templates/beauty-salon-owner/tier5-src/_shared/collection-service.ts +2 -1
  14. package/templates/beauty-salon-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
  15. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
  16. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
  17. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
  18. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-product/index.ts +2 -0
  19. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-product-form/index.ts +10 -4
  20. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
  21. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
  22. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-service-form/index.ts +2 -1
  23. package/templates/branded-lite/tier5-src/_shared/collection-query.ts +32 -5
  24. package/templates/branded-lite/tier5-src/_shared/collection-service.ts +2 -1
  25. package/templates/community-club/tier5-src/_shared/collection-query.ts +32 -5
  26. package/templates/community-club/tier5-src/_shared/collection-service.ts +2 -1
  27. package/templates/community-club-owner/tier5-src/_shared/collection-query.ts +32 -5
  28. package/templates/community-club-owner/tier5-src/_shared/collection-service.ts +2 -1
  29. package/templates/community-club-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
  30. package/templates/community-club-owner/tier5-src/himi-owner-lite-event/index.ts +2 -0
  31. package/templates/community-club-owner/tier5-src/himi-owner-lite-event-form/index.ts +4 -1
  32. package/templates/community-club-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
  33. package/templates/community-club-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
  34. package/templates/community-club-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
  35. package/templates/community-club-owner/tier5-src/himi-owner-lite-product/index.ts +2 -0
  36. package/templates/community-club-owner/tier5-src/himi-owner-lite-product-form/index.ts +10 -4
  37. package/templates/community-club-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
  38. package/templates/community-club-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
  39. package/templates/events-meetups/tier5-src/_shared/collection-query.ts +32 -5
  40. package/templates/events-meetups/tier5-src/_shared/collection-service.ts +2 -1
  41. package/templates/events-meetups-owner/tier5-src/_shared/collection-query.ts +32 -5
  42. package/templates/events-meetups-owner/tier5-src/_shared/collection-service.ts +2 -1
  43. package/templates/events-meetups-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
  44. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-event/index.ts +2 -0
  45. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-event-form/index.ts +4 -1
  46. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
  47. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
  48. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
  49. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
  50. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
  51. package/templates/gym-fitness/tier5-src/_shared/collection-query.ts +32 -5
  52. package/templates/gym-fitness/tier5-src/_shared/collection-service.ts +2 -1
  53. package/templates/gym-fitness-owner/tier5-src/_shared/collection-query.ts +32 -5
  54. package/templates/gym-fitness-owner/tier5-src/_shared/collection-service.ts +2 -1
  55. package/templates/gym-fitness-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
  56. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-event/index.ts +2 -0
  57. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-event-form/index.ts +4 -1
  58. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
  59. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
  60. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
  61. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-product/index.ts +2 -0
  62. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-product-form/index.ts +10 -4
  63. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
  64. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
  65. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-service-form/index.ts +2 -1
  66. package/templates/nonprofit-cause/tier5-src/_shared/collection-query.ts +32 -5
  67. package/templates/nonprofit-cause/tier5-src/_shared/collection-service.ts +2 -1
  68. package/templates/nonprofit-cause-owner/tier5-src/_shared/collection-query.ts +32 -5
  69. package/templates/nonprofit-cause-owner/tier5-src/_shared/collection-service.ts +2 -1
  70. package/templates/nonprofit-cause-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
  71. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-event/index.ts +2 -0
  72. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-event-form/index.ts +4 -1
  73. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
  74. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
  75. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
  76. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
  77. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
  78. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-service-form/index.ts +2 -1
  79. package/templates/owner-lite/dev/index.ts +8 -2
  80. package/templates/owner-lite/tier5-src/_shared/collection-query.ts +32 -5
  81. package/templates/owner-lite/tier5-src/_shared/collection-service.ts +2 -1
  82. package/templates/owner-lite/tier5-src/_shared/owner-editor-value.ts +10 -0
  83. package/templates/owner-lite/tier5-src/himi-owner-lite-event/index.ts +2 -0
  84. package/templates/owner-lite/tier5-src/himi-owner-lite-event-form/index.ts +4 -1
  85. package/templates/owner-lite/tier5-src/himi-owner-lite-faq-category-form/index.ts +5 -1
  86. package/templates/owner-lite/tier5-src/himi-owner-lite-faq-question-form/index.ts +9 -3
  87. package/templates/owner-lite/tier5-src/himi-owner-lite-manage/index.ts +18 -3
  88. package/templates/owner-lite/tier5-src/himi-owner-lite-post/index.ts +2 -0
  89. package/templates/owner-lite/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
  90. package/templates/owner-lite/tier5-src/himi-owner-lite-product/index.ts +2 -0
  91. package/templates/owner-lite/tier5-src/himi-owner-lite-product-form/index.ts +10 -4
  92. package/templates/owner-lite/tier5-src/himi-owner-lite-search/index.ts +11 -0
  93. package/templates/owner-lite/tier5-src/himi-owner-lite-search/logic.ts +35 -1
  94. package/templates/owner-lite/tier5-src/himi-owner-lite-service-form/index.ts +2 -1
  95. package/templates/podcast-creator/tier5-src/_shared/collection-query.ts +32 -5
  96. package/templates/podcast-creator/tier5-src/_shared/collection-service.ts +2 -1
  97. package/templates/podcast-creator-owner/tier5-src/_shared/collection-query.ts +32 -5
  98. package/templates/podcast-creator-owner/tier5-src/_shared/collection-service.ts +2 -1
  99. package/templates/podcast-creator-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
  100. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-event/index.ts +2 -0
  101. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-event-form/index.ts +4 -1
  102. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
  103. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
  104. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
  105. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-product/index.ts +2 -0
  106. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-product-form/index.ts +10 -4
  107. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
  108. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
  109. package/templates/portfolio-creative/tier5-src/_shared/collection-query.ts +32 -5
  110. package/templates/portfolio-creative/tier5-src/_shared/collection-service.ts +2 -1
  111. package/templates/portfolio-creative-owner/tier5-src/_shared/collection-query.ts +32 -5
  112. package/templates/portfolio-creative-owner/tier5-src/_shared/collection-service.ts +2 -1
  113. package/templates/portfolio-creative-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
  114. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
  115. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
  116. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
  117. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-product/index.ts +2 -0
  118. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-product-form/index.ts +10 -4
  119. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
  120. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
  121. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-service-form/index.ts +2 -1
  122. package/templates/restaurant/tier5-src/_shared/collection-query.ts +32 -5
  123. package/templates/restaurant/tier5-src/_shared/collection-service.ts +2 -1
  124. package/templates/restaurant-owner/tier5-src/_shared/collection-query.ts +32 -5
  125. package/templates/restaurant-owner/tier5-src/_shared/collection-service.ts +2 -1
  126. package/templates/restaurant-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
  127. package/templates/restaurant-owner/tier5-src/himi-owner-lite-event/index.ts +2 -0
  128. package/templates/restaurant-owner/tier5-src/himi-owner-lite-event-form/index.ts +4 -1
  129. package/templates/restaurant-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
  130. package/templates/restaurant-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
  131. package/templates/restaurant-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
  132. package/templates/restaurant-owner/tier5-src/himi-owner-lite-product/index.ts +2 -0
  133. package/templates/restaurant-owner/tier5-src/himi-owner-lite-product-form/index.ts +10 -4
  134. package/templates/restaurant-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
  135. package/templates/restaurant-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
  136. package/templates/restaurant-owner/tier5-src/himi-owner-lite-service-form/index.ts +2 -1
  137. package/templates/retail-store/tier5-src/_shared/collection-query.ts +32 -5
  138. package/templates/retail-store/tier5-src/_shared/collection-service.ts +2 -1
  139. package/templates/retail-store-owner/tier5-src/_shared/collection-query.ts +32 -5
  140. package/templates/retail-store-owner/tier5-src/_shared/collection-service.ts +2 -1
  141. package/templates/retail-store-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
  142. package/templates/retail-store-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
  143. package/templates/retail-store-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
  144. package/templates/retail-store-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
  145. package/templates/retail-store-owner/tier5-src/himi-owner-lite-product/index.ts +2 -0
  146. package/templates/retail-store-owner/tier5-src/himi-owner-lite-product-form/index.ts +10 -4
  147. package/templates/retail-store-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
  148. package/templates/retail-store-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
  149. package/templates/yoga-studio/tier5-src/_shared/collection-query.ts +32 -5
  150. package/templates/yoga-studio/tier5-src/_shared/collection-service.ts +2 -1
  151. package/templates/yoga-studio-owner/tier5-src/_shared/collection-query.ts +32 -5
  152. package/templates/yoga-studio-owner/tier5-src/_shared/collection-service.ts +2 -1
  153. package/templates/yoga-studio-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
  154. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-event/index.ts +2 -0
  155. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-event-form/index.ts +4 -1
  156. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
  157. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
  158. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
  159. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
  160. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
  161. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-service-form/index.ts +2 -1
package/dist/cli.mjs CHANGED
@@ -8115,6 +8115,7 @@ function resolveTranslation(value, catalog3, sourceCatalog) {
8115
8115
  var BINDING_SIGILS, BINDING_SIGIL_RE, TRANSLATION_PREFIX, TRANSLATION_KEY_RE;
8116
8116
  var init_bindings = __esm({
8117
8117
  "../../core/ts/src/bindings.ts"() {
8118
+ "use strict";
8118
8119
  BINDING_SIGILS = ["service", "flag", "item", "t"];
8119
8120
  BINDING_SIGIL_RE = new RegExp(
8120
8121
  `^\\$(?:${BINDING_SIGILS.filter((s2) => s2 !== "t").join("|")})\\b|^\\$t:`
@@ -11358,9 +11359,15 @@ async function bootBundleWorker(bundleJs, opts) {
11358
11359
  });
11359
11360
  }
11360
11361
  def.state = clearRuntimeError({ ...def.state, ...stripped });
11362
+ published(def);
11361
11363
  return;
11362
11364
  }
11363
11365
  def.state = clearRuntimeError({ ...def.state, ...rec });
11366
+ published(def);
11367
+ };
11368
+ const published = (def) => {
11369
+ if (!opts.onPublish) return;
11370
+ opts.onPublish(captured.find(({ def: d2 }) => d2 === def)?.name ?? "", clone(def.state));
11364
11371
  };
11365
11372
  function clearRuntimeError(state) {
11366
11373
  delete state._error;
@@ -18091,6 +18098,64 @@ function configuredTokensPath(dir) {
18091
18098
  }
18092
18099
  return {};
18093
18100
  }
18101
+ function tokenNumericIssues(tokens2, tokensPath = "tokens.json") {
18102
+ const issues = [];
18103
+ const isRecord3 = (v2) => v2 !== null && typeof v2 === "object" && !Array.isArray(v2);
18104
+ if (!isRecord3(tokens2)) return issues;
18105
+ const shown2 = (v2) => typeof v2 === "string" ? JSON.stringify(v2) : JSON.stringify(v2) ?? String(v2);
18106
+ const bad2 = (v2) => !(typeof v2 === "number" && Number.isInteger(v2));
18107
+ const check = (layer, where) => {
18108
+ if (!isRecord3(layer)) return;
18109
+ const loses = where ? `the ${where.slice(0, -1)} overlay is dropped on device and the base look is used instead` : 'iOS and Android reject the WHOLE tokens.json otherwise ("Theme unavailable" on iOS, the default palette and fonts on Android)';
18110
+ for (const { group, field, unit } of INTEGER_TOKEN_FIELDS) {
18111
+ const entries = layer[group];
18112
+ if (!isRecord3(entries)) continue;
18113
+ for (const [name, token] of Object.entries(entries)) {
18114
+ if (!isRecord3(token) || !(field in token)) continue;
18115
+ const value = token[field];
18116
+ if (!bad2(value)) continue;
18117
+ const path2 = `${where}${group}.${name}.${field}`;
18118
+ const fix = typeof value !== "number" || !Number.isFinite(value) ? "" : field === "duration" ? ` Durations are milliseconds (${value} \u2192 ${value < 10 ? Math.round(value * 1e3) : Math.round(value)}).` : ` Write ${Math.round(value)}.`;
18119
+ issues.push({
18120
+ screen: null,
18121
+ pass: "tokens",
18122
+ severity: "error",
18123
+ message: `${tokensPath}: ${path2} is ${shown2(value)} \u2014 it must be an integer (${unit}); ${loses}.${fix}`,
18124
+ path: path2
18125
+ });
18126
+ }
18127
+ }
18128
+ for (const group of INTEGER_TOKEN_MAPS) {
18129
+ const entries = layer[group];
18130
+ if (!isRecord3(entries)) continue;
18131
+ for (const [name, value] of Object.entries(entries)) {
18132
+ if (!bad2(value)) continue;
18133
+ const fix = typeof value === "number" && Number.isFinite(value) ? ` Write ${Math.round(value)}.` : "";
18134
+ issues.push({
18135
+ screen: null,
18136
+ pass: "tokens",
18137
+ severity: "error",
18138
+ message: `${tokensPath}: ${where}${group}.${name} is ${shown2(value)} \u2014 it must be an integer (points); ${loses}.${fix}`,
18139
+ path: `${where}${group}.${name}`
18140
+ });
18141
+ }
18142
+ }
18143
+ };
18144
+ check(tokens2, "");
18145
+ const idiom = tokens2.idiom;
18146
+ if (isRecord3(idiom)) {
18147
+ for (const [overlay, layer] of Object.entries(idiom)) check(layer, `idiom.${overlay}.`);
18148
+ }
18149
+ return issues;
18150
+ }
18151
+ function tokenNumericIssuesFor(dir) {
18152
+ const tokensPath = configuredTokensPath(dir).path ?? "tokens.json";
18153
+ try {
18154
+ return tokenNumericIssues(JSON.parse(readFileSync19(join19(dir, tokensPath), "utf8")), tokensPath);
18155
+ } catch {
18156
+ return [];
18157
+ }
18158
+ }
18094
18159
  function tokenColorIssues(dir, tokensPathOverride) {
18095
18160
  const issues = [];
18096
18161
  const error = (message) => issues.push({ screen: null, pass: "tokens", severity: "error", message });
@@ -18120,6 +18185,7 @@ function tokenColorIssues(dir, tokensPathOverride) {
18120
18185
  error(`${tokensPath}: must be an object`);
18121
18186
  return issues;
18122
18187
  }
18188
+ issues.push(...tokenNumericIssues(raw, tokensPath));
18123
18189
  const kitScheme = raw.kit?.colorScheme;
18124
18190
  if (kitScheme !== void 0 && kitScheme !== null && typeof kitScheme !== "string") {
18125
18191
  error(
@@ -18379,12 +18445,18 @@ function accentOnSurfacesFor(fgName, role, colors, declared, findings) {
18379
18445
  }
18380
18446
  }
18381
18447
  }
18382
- var AA_TEXT, CONTRAST_PAIRS, SCHEMES, channels, toHex2, mixHex, onLightSide;
18448
+ var INTEGER_TOKEN_FIELDS, INTEGER_TOKEN_MAPS, AA_TEXT, CONTRAST_PAIRS, SCHEMES, channels, toHex2, mixHex, onLightSide;
18383
18449
  var init_token_lint = __esm({
18384
18450
  "src/token-lint.ts"() {
18385
18451
  init_token_colors();
18386
18452
  init_idiom();
18387
18453
  init_brand_color_math();
18454
+ INTEGER_TOKEN_FIELDS = [
18455
+ { group: "typography", field: "size", unit: "points" },
18456
+ { group: "typography", field: "weight", unit: "a font weight such as 400 or 700" },
18457
+ { group: "motions", field: "duration", unit: "milliseconds" }
18458
+ ];
18459
+ INTEGER_TOKEN_MAPS = ["spacing", "radius"];
18388
18460
  AA_TEXT = 4.5;
18389
18461
  CONTRAST_PAIRS = [
18390
18462
  {
@@ -29906,6 +29978,67 @@ var init_capabilities = __esm({
29906
29978
  }
29907
29979
  });
29908
29980
 
29981
+ // src/authoring-unavailable.ts
29982
+ var authoring_unavailable_exports = {};
29983
+ __export(authoring_unavailable_exports, {
29984
+ AuthoringUnavailable: () => AuthoringUnavailable,
29985
+ authoringUnavailableFields: () => authoringUnavailableFields,
29986
+ isSourceCheckout: () => isSourceCheckout,
29987
+ namedAuthoringImport: () => namedAuthoringImport
29988
+ });
29989
+ import { existsSync as existsSync41 } from "node:fs";
29990
+ import { fileURLToPath as fileURLToPath16 } from "node:url";
29991
+ function namedAuthoringImport(module, load3) {
29992
+ return load3.catch((cause) => {
29993
+ throw new AuthoringUnavailable({ cause, module });
29994
+ });
29995
+ }
29996
+ function isSourceCheckout(env = process.env) {
29997
+ if (env.HIMI_OFF_REPO === "1") return false;
29998
+ return existsSync41(fileURLToPath16(new URL("../../../core/sdk/state/src/index.ts", import.meta.url)));
29999
+ }
30000
+ function causeMessage(cause) {
30001
+ if (cause === void 0 || cause === null) return void 0;
30002
+ if (cause instanceof Error) return cause.message;
30003
+ return String(cause);
30004
+ }
30005
+ function authoringUnavailableFields(err, context) {
30006
+ const cause = causeMessage(err.cause);
30007
+ const what = `the himi authoring runtime failed to load (himi v${context.version})` + (err.module ? ` \u2014 importing ${err.module}` : "") + (cause ? `: ${cause}` : "");
30008
+ const base = {
30009
+ version: context.version,
30010
+ portal: context.portal,
30011
+ ...cause ? { cause } : {},
30012
+ ...err.module ? { module: err.module } : {},
30013
+ sourceCheckout: context.sourceCheckout
30014
+ };
30015
+ if (context.sourceCheckout) {
30016
+ return {
30017
+ error: `${what}. This is a source checkout, so the usual cause is out-of-date dependencies, not the CLI \u2014 run \`yarn install\` at the repo root and retry.`,
30018
+ ...base,
30019
+ fix: "yarn install"
30020
+ };
30021
+ }
30022
+ return {
30023
+ error: `${what}. Off-repo this almost always means an out-of-date CLI, NOT a platform limitation \u2014 upgrade: \`npm i -g @wix/himalaya-cli@latest\`. If you meant to run in-repo, run from a monorepo checkout.`,
30024
+ ...base,
30025
+ upgrade: "npm i -g @wix/himalaya-cli@latest"
30026
+ };
30027
+ }
30028
+ var AuthoringUnavailable;
30029
+ var init_authoring_unavailable = __esm({
30030
+ "src/authoring-unavailable.ts"() {
30031
+ AuthoringUnavailable = class extends Error {
30032
+ module;
30033
+ constructor(options = {}) {
30034
+ super(`the himi authoring runtime failed to load${options.module ? ` (${options.module})` : ""}`, { cause: options.cause });
30035
+ this.name = "AuthoringUnavailable";
30036
+ this.module = options.module;
30037
+ }
30038
+ };
30039
+ }
30040
+ });
30041
+
29909
30042
  // src/site-analyze/site-view-metadata.ts
29910
30043
  function pages(site) {
29911
30044
  if (!site || typeof site !== "object" || !("pages" in site)) return [];
@@ -30404,13 +30537,13 @@ var init_l10n_catalog = __esm({
30404
30537
  });
30405
30538
 
30406
30539
  // ../../core/dev-server/src/l10n.ts
30407
- import { readFileSync as readFileSync42, existsSync as existsSync41 } from "node:fs";
30540
+ import { readFileSync as readFileSync42, existsSync as existsSync42 } from "node:fs";
30408
30541
  import { resolve as resolve31 } from "node:path";
30409
- import { fileURLToPath as fileURLToPath16 } from "node:url";
30542
+ import { fileURLToPath as fileURLToPath17 } from "node:url";
30410
30543
  function loadCatalog2(tag) {
30411
30544
  if (catalogCache.has(tag)) return catalogCache.get(tag);
30412
30545
  const path2 = resolve31(ROOT3, `tools/l10n/catalog.${tag}.json`);
30413
- const map = existsSync41(path2) ? sourceMap(parseCatalog(readFileSync42(path2, "utf8"))) : /* @__PURE__ */ new Map();
30546
+ const map = existsSync42(path2) ? sourceMap(parseCatalog(readFileSync42(path2, "utf8"))) : /* @__PURE__ */ new Map();
30414
30547
  catalogCache.set(tag, map);
30415
30548
  return map;
30416
30549
  }
@@ -30420,7 +30553,7 @@ function pickLocale(acceptLanguage) {
30420
30553
  for (const tag of tags) {
30421
30554
  if (tag === "en") continue;
30422
30555
  const path2 = resolve31(ROOT3, `tools/l10n/catalog.${tag}.json`);
30423
- if (existsSync41(path2)) return tag;
30556
+ if (existsSync42(path2)) return tag;
30424
30557
  }
30425
30558
  return null;
30426
30559
  }
@@ -30476,7 +30609,7 @@ var init_l10n = __esm({
30476
30609
  "../../core/dev-server/src/l10n.ts"() {
30477
30610
  init_l10n_strings();
30478
30611
  init_l10n_catalog();
30479
- ROOT3 = resolve31(fileURLToPath16(new URL("../../..", import.meta.url)));
30612
+ ROOT3 = resolve31(fileURLToPath17(new URL("../../..", import.meta.url)));
30480
30613
  catalogCache = /* @__PURE__ */ new Map();
30481
30614
  }
30482
30615
  });
@@ -30803,6 +30936,21 @@ function deriveNavigationConfig(app, bundleCtx) {
30803
30936
  if (app.dataSchema !== void 0) config.dataSchema = app.dataSchema;
30804
30937
  return config;
30805
30938
  }
30939
+ function withDevNetMocks(config, declared, fileMocks) {
30940
+ const rules = fileMocks?.rules;
30941
+ if (!Array.isArray(rules) || rules.length === 0 && fileMocks?.unmatched !== "fail") return config;
30942
+ if (declared?.enabled === false) return config;
30943
+ if (Array.isArray(declared?.rules) || declared?.scenarioRef !== void 0) return config;
30944
+ return {
30945
+ ...config,
30946
+ devGatewayConfig: {
30947
+ mode: fileMocks?.mode ?? "mock",
30948
+ ...fileMocks?.unmatched !== void 0 ? { unmatched: fileMocks.unmatched } : {},
30949
+ ...declared ?? {},
30950
+ rules
30951
+ }
30952
+ };
30953
+ }
30806
30954
  function mergeConfig(base, patch) {
30807
30955
  if (patch === null || typeof patch !== "object" || Array.isArray(patch)) return patch;
30808
30956
  const out2 = { ...base };
@@ -30824,8 +30972,9 @@ function withCompleteLinkables(cfg) {
30824
30972
  const list = cfg.linkableScreens;
30825
30973
  return Array.isArray(list) ? { ...cfg, linkableScreens: completeLinkableScreens(list) } : cfg;
30826
30974
  }
30827
- function buildAppConfigDocument(req, meta, override, bundleCtx) {
30828
- const merged = override ? withCompleteLinkables(mergeConfig(deriveNavigationConfig(meta, bundleCtx), override)) : deriveNavigationConfig(meta, bundleCtx);
30975
+ function buildAppConfigDocument(req, meta, override, bundleCtx, devNetMocks) {
30976
+ const derived = withDevNetMocks(deriveNavigationConfig(meta, bundleCtx), meta.devGateway, devNetMocks);
30977
+ const merged = override ? withCompleteLinkables(mergeConfig(derived, override)) : derived;
30829
30978
  const baseline = override ? { ...merged, wixCachePolicy: sanitizeServedOfflineQueue(merged.wixCachePolicy) } : merged;
30830
30979
  const acceptLanguage = req.headers["accept-language"];
30831
30980
  const locale = pickLocale(typeof acceptLanguage === "string" ? acceptLanguage : null);
@@ -30834,7 +30983,7 @@ function buildAppConfigDocument(req, meta, override, bundleCtx) {
30834
30983
  const etag = `"${createHash14("sha1").update(`${locale ?? "en"}:${body}`).digest("hex")}"`;
30835
30984
  return { config, body, etag, locale };
30836
30985
  }
30837
- function handleAppConfigRequest(req, res, meta, override, bundleCtx) {
30986
+ function handleAppConfigRequest(req, res, meta, override, bundleCtx, devNetMocks) {
30838
30987
  const appName2 = decodeURIComponent(
30839
30988
  (req.url ?? "").replace(/^\/v1\/app-config\//, "").split("?")[0]
30840
30989
  );
@@ -30843,7 +30992,7 @@ function handleAppConfigRequest(req, res, meta, override, bundleCtx) {
30843
30992
  res.end(JSON.stringify({ error: "unknown_app", appName: appName2 }));
30844
30993
  return;
30845
30994
  }
30846
- const { body, etag, locale } = buildAppConfigDocument(req, meta, override, bundleCtx);
30995
+ const { body, etag, locale } = buildAppConfigDocument(req, meta, override, bundleCtx, devNetMocks);
30847
30996
  if (req.headers["if-none-match"] === etag) {
30848
30997
  res.writeHead(304, { ETag: etag, "Cache-Control": "max-age=60, stale-while-revalidate=86400" });
30849
30998
  res.end();
@@ -31021,13 +31170,13 @@ var init_inject = __esm({
31021
31170
  // ../../core/dev-server/src/store.ts
31022
31171
  import { mkdirSync as mkdirSync21 } from "node:fs";
31023
31172
  import { dirname as dirname26, resolve as resolve32 } from "node:path";
31024
- import { fileURLToPath as fileURLToPath17 } from "node:url";
31173
+ import { fileURLToPath as fileURLToPath18 } from "node:url";
31025
31174
  import { createRequire } from "node:module";
31026
31175
  var nodeRequire, ROOT4, Store;
31027
31176
  var init_store2 = __esm({
31028
31177
  "../../core/dev-server/src/store.ts"() {
31029
31178
  nodeRequire = createRequire(import.meta.url);
31030
- ROOT4 = resolve32(fileURLToPath17(new URL("../../..", import.meta.url)));
31179
+ ROOT4 = resolve32(fileURLToPath18(new URL("../../..", import.meta.url)));
31031
31180
  Store = class {
31032
31181
  _db;
31033
31182
  dbPath;
@@ -35546,7 +35695,7 @@ var init_wix_member_login = __esm({
35546
35695
  });
35547
35696
 
35548
35697
  // ../../core/dev-server/src/wix-gateway.ts
35549
- import { readFileSync as readFileSync44, existsSync as existsSync42 } from "node:fs";
35698
+ import { readFileSync as readFileSync44, existsSync as existsSync43 } from "node:fs";
35550
35699
  function isSensitiveBodyName(name) {
35551
35700
  const segments = name.split(/[^A-Za-z0-9]+/).filter(Boolean);
35552
35701
  for (let i2 = 0; i2 < segments.length; i2++) {
@@ -35613,7 +35762,7 @@ function resolveNetMocks(fileMocks, appDeclared) {
35613
35762
  }
35614
35763
  function readNetMocksFile(path2) {
35615
35764
  try {
35616
- if (!existsSync42(path2)) return null;
35765
+ if (!existsSync43(path2)) return null;
35617
35766
  const raw = JSON.parse(readFileSync44(path2, "utf-8"));
35618
35767
  if (Array.isArray(raw)) return wixMockRuleErrors(raw).length ? null : { rules: raw };
35619
35768
  if (raw && typeof raw === "object") {
@@ -36574,13 +36723,13 @@ var init_stable_ids = __esm({
36574
36723
  // ../../core/dev-server/src/preview.ts
36575
36724
  import { spawn as spawn4 } from "node:child_process";
36576
36725
  import { createHash as createHash18 } from "node:crypto";
36577
- import { existsSync as existsSync43, createReadStream, statSync as statSync11, readFileSync as readFileSync46, renameSync as renameSync9, unlinkSync as unlinkSync3 } from "node:fs";
36726
+ import { existsSync as existsSync44, createReadStream, statSync as statSync11, readFileSync as readFileSync46, renameSync as renameSync9, unlinkSync as unlinkSync3 } from "node:fs";
36578
36727
  import { homedir as homedir7, tmpdir as tmpdir2 } from "node:os";
36579
36728
  import { resolve as resolvePath, dirname as dirname27 } from "node:path";
36580
- import { fileURLToPath as fileURLToPath18 } from "node:url";
36729
+ import { fileURLToPath as fileURLToPath19 } from "node:url";
36581
36730
  function firstExisting(paths) {
36582
36731
  for (const p2 of paths) {
36583
- if (p2 && existsSync43(p2)) return p2;
36732
+ if (p2 && existsSync44(p2)) return p2;
36584
36733
  }
36585
36734
  return null;
36586
36735
  }
@@ -36619,7 +36768,7 @@ function isHimalayaAppWindow(w2) {
36619
36768
  }
36620
36769
  async function macosWinlistCommand() {
36621
36770
  const bin = macosWinlistBin();
36622
- if (existsSync43(bin)) return compiledWinlist(bin);
36771
+ if (existsSync44(bin)) return compiledWinlist(bin);
36623
36772
  if (macosWinlistCompileFailed) return interpretWinlist();
36624
36773
  if (!macosWinlistInFlight) {
36625
36774
  macosWinlistInFlight = buildMacosWinlist(bin).finally(() => {
@@ -36647,7 +36796,7 @@ async function buildMacosWinlist(bin) {
36647
36796
  unlinkSync3(staging);
36648
36797
  } catch {
36649
36798
  }
36650
- return existsSync43(bin) ? compiledWinlist(bin) : interpretWinlist();
36799
+ return existsSync44(bin) ? compiledWinlist(bin) : interpretWinlist();
36651
36800
  }
36652
36801
  return compiledWinlist(bin);
36653
36802
  }
@@ -37272,7 +37421,7 @@ function finalizeRecording(key3, rec) {
37272
37421
  } catch {
37273
37422
  }
37274
37423
  }
37275
- const sizeBytes = existsSync43(rec.localPath) ? statSync11(rec.localPath).size : 0;
37424
+ const sizeBytes = existsSync44(rec.localPath) ? statSync11(rec.localPath).size : 0;
37276
37425
  clips.set(rec.id, { path: rec.localPath, mime: rec.mime });
37277
37426
  recordings.delete(key3);
37278
37427
  return { sizeBytes };
@@ -37344,7 +37493,7 @@ async function handlePreviewClip(res, url) {
37344
37493
  const q2 = new URLSearchParams(url.split("?")[1] ?? "");
37345
37494
  const id = q2.get("id") ?? "";
37346
37495
  const clip3 = clips.get(id);
37347
- if (!clip3 || !existsSync43(clip3.path)) {
37496
+ if (!clip3 || !existsSync44(clip3.path)) {
37348
37497
  res.statusCode = 404;
37349
37498
  res.setHeader("content-type", "application/json");
37350
37499
  return void res.end(JSON.stringify({ error: "clip_not_found", id }));
@@ -37405,7 +37554,7 @@ var init_preview2 = __esm({
37405
37554
  SWIFT_BIN = process.env.HIMALAYA_SWIFT_PATH ?? "swift";
37406
37555
  SWIFTC_BIN = process.env.HIMALAYA_SWIFTC_PATH ?? "swiftc";
37407
37556
  SCREENCAPTURE_BIN = process.env.HIMALAYA_SCREENCAPTURE_PATH ?? "screencapture";
37408
- MACOS_WINLIST = resolvePath(dirname27(fileURLToPath18(import.meta.url)), "../scripts/macos-winshot.swift");
37557
+ MACOS_WINLIST = resolvePath(dirname27(fileURLToPath19(import.meta.url)), "../scripts/macos-winshot.swift");
37409
37558
  MACOS_WINLIST_BUILD_TIMEOUT_MS = 12e4;
37410
37559
  MACOS_WINLIST_INTERPRET_TIMEOUT_MS = 3e4;
37411
37560
  HIMALAYA_MAC_BUNDLE_ID = /^(com\.himalaya\.|com\.wix\.himi\.|dev\.himalaya\.)/i;
@@ -37462,7 +37611,7 @@ var init_tier4_integrity = __esm({
37462
37611
  });
37463
37612
 
37464
37613
  // ../../core/dev-server/src/tier4-verifier.ts
37465
- import { readFileSync as readFileSync47, existsSync as existsSync44 } from "node:fs";
37614
+ import { readFileSync as readFileSync47, existsSync as existsSync45 } from "node:fs";
37466
37615
  import { resolve as resolve34 } from "node:path";
37467
37616
  var TierFourVerifier;
37468
37617
  var init_tier4_verifier = __esm({
@@ -37480,7 +37629,7 @@ var init_tier4_verifier = __esm({
37480
37629
  const expected = this.expectedSri(bundleId, relPath);
37481
37630
  if (!expected) return { ok: true };
37482
37631
  const path2 = resolve34(this.tier4Root, bundleId, relPath);
37483
- const bytes2 = providedBytes ?? (existsSync44(path2) ? readFileSync47(path2) : null);
37632
+ const bytes2 = providedBytes ?? (existsSync45(path2) ? readFileSync47(path2) : null);
37484
37633
  if (!bytes2) return { ok: false, reason: "file not found" };
37485
37634
  if (computeSri(bytes2) !== expected) return { ok: false, reason: "sri mismatch" };
37486
37635
  return { ok: true };
@@ -37489,7 +37638,7 @@ var init_tier4_verifier = __esm({
37489
37638
  let cached3 = this.cache.get(bundleId);
37490
37639
  if (cached3) return cached3;
37491
37640
  const manifestPath = resolve34(this.tier4Root, bundleId, "manifest.json");
37492
- if (!existsSync44(manifestPath)) return void 0;
37641
+ if (!existsSync45(manifestPath)) return void 0;
37493
37642
  const manifest = JSON.parse(readFileSync47(manifestPath, "utf8"));
37494
37643
  cached3 = { integrity: parseManifestIntegrity(manifest) };
37495
37644
  this.cache.set(bundleId, cached3);
@@ -37557,7 +37706,7 @@ var init_net_mocks_rollover = __esm({
37557
37706
  import { readFileSync as readFileSync48 } from "node:fs";
37558
37707
  import { homedir as homedir8 } from "node:os";
37559
37708
  import { dirname as dirname28, join as join43 } from "node:path";
37560
- import { fileURLToPath as fileURLToPath19 } from "node:url";
37709
+ import { fileURLToPath as fileURLToPath20 } from "node:url";
37561
37710
  function readJson2(path2) {
37562
37711
  try {
37563
37712
  return JSON.parse(readFileSync48(path2, "utf8"));
@@ -37566,7 +37715,7 @@ function readJson2(path2) {
37566
37715
  }
37567
37716
  }
37568
37717
  function ledgerDevServerPort(tenant) {
37569
- const here = dirname28(fileURLToPath19(import.meta.url));
37718
+ const here = dirname28(fileURLToPath20(import.meta.url));
37570
37719
  const ledger = readJson2(join43(here, "..", "..", "..", "tools", "dev-cli", "ports.json"));
37571
37720
  const port = ledger?.apps?.[tenant]?.devServer;
37572
37721
  return typeof port === "number" ? port : void 0;
@@ -132088,12 +132237,12 @@ var init_png_egress = __esm({
132088
132237
  });
132089
132238
 
132090
132239
  // ../../core/dev-server/src/render-fonts.ts
132091
- import { existsSync as existsSync45, readFileSync as readFileSync49 } from "node:fs";
132240
+ import { existsSync as existsSync46, readFileSync as readFileSync49 } from "node:fs";
132092
132241
  import { extname, join as join44 } from "node:path";
132093
132242
  function servedFontFaces(appDir3, tokens2) {
132094
132243
  try {
132095
132244
  const policyPath = join44(appDir3, "fonts.json");
132096
- const policy = existsSync45(policyPath) ? JSON.parse(readFileSync49(policyPath, "utf8")) : {};
132245
+ const policy = existsSync46(policyPath) ? JSON.parse(readFileSync49(policyPath, "utf8")) : {};
132097
132246
  let plan = planFonts(tokens2, policy);
132098
132247
  if (!hasVendoredFloor()) plan = { ...plan, families: plan.families.filter((f2) => !isHostProvided(f2.name)) };
132099
132248
  if (plan.families.length === 0) return void 0;
@@ -132371,7 +132520,7 @@ var init_motion_flags = __esm({
132371
132520
  // ../../core/dev-server/src/kits.ts
132372
132521
  import { readdirSync as readdirSync24, readFileSync as readFileSync51 } from "node:fs";
132373
132522
  import { resolve as resolve36, join as join45 } from "node:path";
132374
- import { fileURLToPath as fileURLToPath20 } from "node:url";
132523
+ import { fileURLToPath as fileURLToPath21 } from "node:url";
132375
132524
  function listKits() {
132376
132525
  return readdirSync24(CATALOG).filter((f2) => f2.endsWith(".json")).map((f2) => {
132377
132526
  const { tokens: tokens2, ...meta } = JSON.parse(readFileSync51(join45(CATALOG, f2), "utf8"));
@@ -132389,7 +132538,7 @@ function readKit(id) {
132389
132538
  var ROOT5, CATALOG;
132390
132539
  var init_kits = __esm({
132391
132540
  "../../core/dev-server/src/kits.ts"() {
132392
- ROOT5 = resolve36(fileURLToPath20(new URL("../../..", import.meta.url)));
132541
+ ROOT5 = resolve36(fileURLToPath21(new URL("../../..", import.meta.url)));
132393
132542
  CATALOG = join45(ROOT5, "stdlib/design-kits");
132394
132543
  }
132395
132544
  });
@@ -133118,7 +133267,7 @@ __export(config_exports2, {
133118
133267
  });
133119
133268
  import { mkdirSync as mkdirSync22, readFileSync as readFileSync52, writeFileSync as writeFileSync19 } from "node:fs";
133120
133269
  import { dirname as dirname29, join as join46, resolve as resolve37 } from "node:path";
133121
- import { fileURLToPath as fileURLToPath21 } from "node:url";
133270
+ import { fileURLToPath as fileURLToPath22 } from "node:url";
133122
133271
  function strip(line) {
133123
133272
  const h2 = line.indexOf("#");
133124
133273
  return (h2 >= 0 ? line.slice(0, h2) : line).replace(/\s+$/, "");
@@ -133292,7 +133441,7 @@ var init_config2 = __esm({
133292
133441
  "../../core/serve-control/src/config.ts"() {
133293
133442
  init_errors();
133294
133443
  init_contract();
133295
- REPO_ROOT6 = resolve37(dirname29(fileURLToPath21(import.meta.url)), "../../..");
133444
+ REPO_ROOT6 = resolve37(dirname29(fileURLToPath22(import.meta.url)), "../../..");
133296
133445
  OPERATIONAL_OVERLAY_KEYS = /* @__PURE__ */ new Set([
133297
133446
  "wixCachePolicy",
133298
133447
  "telemetryConfig",
@@ -133360,10 +133509,10 @@ var init_config2 = __esm({
133360
133509
  // ../../core/dev-server/src/index.ts
133361
133510
  import { createServer as createServer3 } from "node:http";
133362
133511
  import { readFile, stat } from "node:fs/promises";
133363
- import { readFileSync as readFileSync53, existsSync as existsSync46, watch, mkdirSync as mkdirSync23, rmSync as rmSync11 } from "node:fs";
133512
+ import { readFileSync as readFileSync53, existsSync as existsSync47, watch, mkdirSync as mkdirSync23, rmSync as rmSync11 } from "node:fs";
133364
133513
  import { basename as basename10, dirname as dirname30, extname as extname2, join as join47, relative as relative8, resolve as resolve38, normalize as normalize3, sep as sep10 } from "node:path";
133365
133514
  import { createHash as createHash21, randomUUID as randomUUID5 } from "node:crypto";
133366
- import { fileURLToPath as fileURLToPath22, pathToFileURL as pathToFileURL6 } from "node:url";
133515
+ import { fileURLToPath as fileURLToPath23, pathToFileURL as pathToFileURL6 } from "node:url";
133367
133516
  function readLogicBundle(read, tier5Dir, name) {
133368
133517
  return read(tier5Dir ?? TIER5_ROOT2, name) ?? (tier5Dir && tier5Dir !== TIER5_ROOT2 ? read(TIER5_ROOT2, name) : void 0);
133369
133518
  }
@@ -133423,6 +133572,9 @@ function readAppTokens(state) {
133423
133572
  return null;
133424
133573
  }
133425
133574
  }
133575
+ function deviceNetMocks(state) {
133576
+ return state.deviceNetMocks ?? null;
133577
+ }
133426
133578
  function effectiveAppConfigOverride(state) {
133427
133579
  let gitOverlay;
133428
133580
  if (state.app) {
@@ -133488,7 +133640,7 @@ function handleL10nRequest(req, res, state) {
133488
133640
  return sendJson(res, 404, { error: "unknown_app", app }, cors);
133489
133641
  }
133490
133642
  const path2 = resolve38(state.app.dir, "l10n", `${tag}.json`);
133491
- if (!existsSync46(path2)) {
133643
+ if (!existsSync47(path2)) {
133492
133644
  res.writeHead(204, cors);
133493
133645
  res.end();
133494
133646
  return;
@@ -133629,7 +133781,8 @@ async function handleBootRequest(req, res, state) {
133629
133781
  req,
133630
133782
  state.app.meta,
133631
133783
  effectiveAppConfigOverride(state),
133632
- bundleCtx
133784
+ bundleCtx,
133785
+ deviceNetMocks(state)
133633
133786
  );
133634
133787
  const tokenDocument = effectiveAppTokens(req, state);
133635
133788
  const homeScreenId = config.homeScreenId ?? state.app.meta.homeScreenId ?? null;
@@ -134415,7 +134568,7 @@ async function primeAppDependencyWatchers(state) {
134415
134568
  const current = state.app;
134416
134569
  if (!current) return;
134417
134570
  const entry = resolve38(current.dir, "dev/index.ts");
134418
- if (!existsSync46(entry)) return;
134571
+ if (!existsSync47(entry)) return;
134419
134572
  mkdirSync23(HMR_TMP_DIR, { recursive: true });
134420
134573
  const outfile = resolve38(HMR_TMP_DIR, `${current.name}-deps-${++appReloadSeq}.mjs`);
134421
134574
  try {
@@ -136259,6 +136412,9 @@ function createDevServer(opts = {}) {
136259
136412
  const seeded = applyNetMocks(state.wix, resolved2.mocks);
136260
136413
  state.wixSeededOn = todayYmd();
136261
136414
  state.wixSeededFromApp = resolved2.source !== "file";
136415
+ if (resolved2.source === "file" && state.app && existsSync47(resolve38(state.app.dir, "himalaya.content.json"))) {
136416
+ state.deviceNetMocks = resolved2.mocks;
136417
+ }
136262
136418
  const from = resolved2.source === "file" ? netMocksPath : `${state.appName} devGateway.rules`;
136263
136419
  console.error(`[himalaya-dev] net-mocks: seeded ${seeded.rules} rule(s), mode=${seeded.mode} from ${from}`);
136264
136420
  }
@@ -136517,7 +136673,7 @@ function createDevServer(opts = {}) {
136517
136673
  // Through a tenant host's proxy, the nav bundle routes back through that host, as screens do.
136518
136674
  serverBaseUrl: forwardedBaseUrl(req) ?? state.serverBaseUrl,
136519
136675
  bundleIntegrity: (name) => bundleIntegritySync(name, state.tier5Dir)
136520
- });
136676
+ }, deviceNetMocks(state));
136521
136677
  }
136522
136678
  {
136523
136679
  const appRoutes = state.app?.module.dataRoutes;
@@ -136773,7 +136929,7 @@ var init_src6 = __esm({
136773
136929
  init_kits();
136774
136930
  init_widgets();
136775
136931
  init_descriptor_postprocess();
136776
- ROOT6 = resolve38(fileURLToPath22(new URL("../../..", import.meta.url)));
136932
+ ROOT6 = resolve38(fileURLToPath23(new URL("../../..", import.meta.url)));
136777
136933
  setPngFontCss(async (tokens2, idiomContext) => await pngFontFaceCss(tokens2) + (idiomContext ? await idiomFontFaceCss(idiomContext) : ""));
136778
136934
  setPngEgress(startEgressProxy);
136779
136935
  TIER3_ROOT = resolve38(ROOT6, "core/dev-server/web");
@@ -140069,9 +140225,9 @@ __export(build_exports2, {
140069
140225
  withoutDevOnlyAppConfig: () => withoutDevOnlyAppConfig
140070
140226
  });
140071
140227
  import { createHash as createHash25 } from "node:crypto";
140072
- import { readFileSync as readFileSync54, readdirSync as readdirSync25, existsSync as existsSync47 } from "node:fs";
140228
+ import { readFileSync as readFileSync54, readdirSync as readdirSync25, existsSync as existsSync48 } from "node:fs";
140073
140229
  import { dirname as dirname31, join as join48, resolve as resolve39 } from "node:path";
140074
- import { fileURLToPath as fileURLToPath23 } from "node:url";
140230
+ import { fileURLToPath as fileURLToPath24 } from "node:url";
140075
140231
  import { createRequire as createRequire2 } from "node:module";
140076
140232
  import { execFileSync as execFileSync4 } from "node:child_process";
140077
140233
  import { gzipSync as gzipSync2 } from "node:zlib";
@@ -140113,7 +140269,7 @@ function l10nLintOptions(locale, appDir3) {
140113
140269
  const catalog3 = /* @__PURE__ */ new Set();
140114
140270
  for (const tag of tags) {
140115
140271
  const path2 = join48(appDir3, "l10n", `${tag}.json`);
140116
- if (!existsSync47(path2)) continue;
140272
+ if (!existsSync48(path2)) continue;
140117
140273
  try {
140118
140274
  const parsed = JSON.parse(readFileSync54(path2, "utf8"));
140119
140275
  for (const m2 of Object.values(parsed.messages ?? {})) {
@@ -140295,7 +140451,7 @@ function shellSha(root = REPO_ROOT7) {
140295
140451
  function isMonorepoCheckout(dir) {
140296
140452
  try {
140297
140453
  const top = execFileSync4("git", ["rev-parse", "--show-toplevel"], { cwd: dir, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
140298
- return top.length > 0 && existsSync47(join48(top, "core", "schema", "core.proto"));
140454
+ return top.length > 0 && existsSync48(join48(top, "core", "schema", "core.proto"));
140299
140455
  } catch {
140300
140456
  return false;
140301
140457
  }
@@ -140546,9 +140702,9 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
140546
140702
  const tier5Dir = opts.tier5Dir ?? TIER5_DIR;
140547
140703
  const bundlePath = (name) => {
140548
140704
  const own5 = join48(tier5Dir, `${name}.bundle.js`);
140549
- if (existsSync47(own5)) return own5;
140705
+ if (existsSync48(own5)) return own5;
140550
140706
  const shared = join48(TIER5_DIR, `${name}.bundle.js`);
140551
- return resolve39(tier5Dir) !== TIER5_DIR && existsSync47(shared) ? shared : void 0;
140707
+ return resolve39(tier5Dir) !== TIER5_DIR && existsSync48(shared) ? shared : void 0;
140552
140708
  };
140553
140709
  const bundleDirFor = (name) => {
140554
140710
  const path2 = name ? bundlePath(name) : void 0;
@@ -140709,11 +140865,11 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
140709
140865
  };
140710
140866
  checkRegistry(preloaded.module.actions);
140711
140867
  const contentManifestPath2 = join48(preloaded.dir, "himalaya.content.json");
140712
- const contentManifest = existsSync47(contentManifestPath2) ? JSON.parse(readFileSync54(contentManifestPath2, "utf8")) : void 0;
140868
+ const contentManifest = existsSync48(contentManifestPath2) ? JSON.parse(readFileSync54(contentManifestPath2, "utf8")) : void 0;
140713
140869
  let screenMetadata = parseScreenMetadata(contentManifest?.screens);
140714
140870
  if (contentManifest?.shell === "brandy" && screenMetadata) {
140715
140871
  const provisioningPath2 = join48(preloaded.dir, "provisioning.json");
140716
- if (existsSync47(provisioningPath2)) screenMetadata = siteViewMetadataForBuild(screenMetadata, JSON.parse(readFileSync54(provisioningPath2, "utf8")).site);
140872
+ if (existsSync48(provisioningPath2)) screenMetadata = siteViewMetadataForBuild(screenMetadata, JSON.parse(readFileSync54(provisioningPath2, "utf8")).site);
140717
140873
  }
140718
140874
  await store.reset(app);
140719
140875
  const bundles = {};
@@ -140773,7 +140929,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
140773
140929
  if (store.putDoc) {
140774
140930
  for (const [name, file2] of [["spec", "SPEC.md"], ["mobile-ux", "MOBILE-UX.md"]]) {
140775
140931
  const path2 = join48(preloaded.dir, file2);
140776
- if (!existsSync47(path2)) continue;
140932
+ if (!existsSync48(path2)) continue;
140777
140933
  const bytes2 = readFileSync54(path2);
140778
140934
  if (bytes2.length === 0 || bytes2.length > MAX_AUTHORING_DOC_BYTES) {
140779
140935
  throw new Error(`${file2} must be non-empty and at most ${MAX_AUTHORING_DOC_BYTES} bytes to ship with a release.`);
@@ -140833,7 +140989,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
140833
140989
  const fontWarnings = [];
140834
140990
  try {
140835
140991
  const appTokens = readTokensForLint(preloaded) ?? {};
140836
- const policy = existsSync47(join48(preloaded.dir, "fonts.json")) ? JSON.parse(readFileSync54(join48(preloaded.dir, "fonts.json"), "utf8")) : {};
140992
+ const policy = existsSync48(join48(preloaded.dir, "fonts.json")) ? JSON.parse(readFileSync54(join48(preloaded.dir, "fonts.json"), "utf8")) : {};
140837
140993
  fontPlan = planFonts(appTokens, policy);
140838
140994
  } catch (err) {
140839
140995
  throw new Error(
@@ -141405,7 +141561,7 @@ async function buildFunctionsOnlyRelease(preloaded, dest) {
141405
141561
  const sources = {};
141406
141562
  for (const definition of config.functions.functions) {
141407
141563
  const candidates = [".ts", ".js", ".mts", ".mjs"].map((extension) => join48(preloaded.dir, "functions", `${definition.name}${extension}`));
141408
- const source = candidates.find((candidate) => existsSync47(candidate));
141564
+ const source = candidates.find((candidate) => existsSync48(candidate));
141409
141565
  if (!source) throw new Error(`missing source for function ${definition.name}; expected functions/${definition.name}.ts`);
141410
141566
  sources[definition.name] = readFileSync54(source, "utf8");
141411
141567
  }
@@ -141479,7 +141635,7 @@ var init_build3 = __esm({
141479
141635
  BAKE_OFFLINE_BASE = "http://himalaya-bake.invalid";
141480
141636
  KNOWN_ICON_NAMES = [...ICON_NAMES].sort();
141481
141637
  KNOWN_ICONS = new Set(KNOWN_ICON_NAMES);
141482
- REPO_ROOT7 = resolve39(dirname31(fileURLToPath23(import.meta.url)), "../..");
141638
+ REPO_ROOT7 = resolve39(dirname31(fileURLToPath24(import.meta.url)), "../..");
141483
141639
  TIER5_DIR = join48(REPO_ROOT7, "core/dev-server/tier5-bundles");
141484
141640
  requireFromHere = createRequire2(import.meta.url);
141485
141641
  SOURCEMAP_ON_DEMAND_PATH = join48(REPO_ROOT7, "core/dev-server/tier5-bundles-src/sourcemap-on-demand.mjs");
@@ -142043,7 +142199,7 @@ __export(build_changes_exports, {
142043
142199
  diffTokens: () => diffTokens,
142044
142200
  headline: () => headline
142045
142201
  });
142046
- import { existsSync as existsSync48, readdirSync as readdirSync26, readFileSync as readFileSync55 } from "node:fs";
142202
+ import { existsSync as existsSync49, readdirSync as readdirSync26, readFileSync as readFileSync55 } from "node:fs";
142047
142203
  import { join as join49 } from "node:path";
142048
142204
  function componentsOf(descriptor) {
142049
142205
  const out2 = /* @__PURE__ */ new Map();
@@ -142109,7 +142265,7 @@ function diffTokens(before, after) {
142109
142265
  return out2;
142110
142266
  }
142111
142267
  function describeChanges(oldTree, newTree, diff, opts = {}) {
142112
- if (!existsSync48(oldTree) || !existsSync48(newTree)) return { items: [], more: 0 };
142268
+ if (!existsSync49(oldTree) || !existsSync49(newTree)) return { items: [], more: 0 };
142113
142269
  const all = [];
142114
142270
  const before = screensIn(oldTree);
142115
142271
  const after = screensIn(newTree);
@@ -142200,7 +142356,7 @@ var init_build_changes = __esm({
142200
142356
  });
142201
142357
 
142202
142358
  // src/studio-timeline.ts
142203
- import { existsSync as existsSync49, readFileSync as readFileSync56 } from "node:fs";
142359
+ import { existsSync as existsSync50, readFileSync as readFileSync56 } from "node:fs";
142204
142360
  import { join as join50 } from "node:path";
142205
142361
  function stateOf(view) {
142206
142362
  const j2 = view.journal[0];
@@ -142269,7 +142425,7 @@ function validFrame(f2) {
142269
142425
  }
142270
142426
  function readTimeline(dir) {
142271
142427
  const file2 = join50(dir, TIMELINE_FILE);
142272
- if (!existsSync49(file2)) return [];
142428
+ if (!existsSync50(file2)) return [];
142273
142429
  const out2 = [];
142274
142430
  for (const line of readFileSync56(file2, "utf8").split("\n")) {
142275
142431
  if (!line.trim()) continue;
@@ -142295,7 +142451,7 @@ function appendFrame(dir, view, reveal = null) {
142295
142451
  const frames = readTimeline(dir);
142296
142452
  const last = frames[frames.length - 1];
142297
142453
  if (last && last.v === view.v && !reveal) {
142298
- if (!existsSync49(join50(dir, TIMELINE_JS))) writeTimelineJs(dir, frames);
142454
+ if (!existsSync50(join50(dir, TIMELINE_JS))) writeTimelineJs(dir, frames);
142299
142455
  return frames.length;
142300
142456
  }
142301
142457
  let prev = null;
@@ -142367,7 +142523,7 @@ __export(studio_exports, {
142367
142523
  writeStudioRecord: () => writeStudioRecord
142368
142524
  });
142369
142525
  import { createHash as createHash26 } from "node:crypto";
142370
- import { existsSync as existsSync50, readdirSync as readdirSync27, readFileSync as readFileSync57, realpathSync as realpathSync8, statSync as statSync12 } from "node:fs";
142526
+ import { existsSync as existsSync51, readdirSync as readdirSync27, readFileSync as readFileSync57, realpathSync as realpathSync8, statSync as statSync12 } from "node:fs";
142371
142527
  import { basename as basename11, extname as extname3, join as join51, relative as relative9, resolve as resolve40, sep as sep11 } from "node:path";
142372
142528
  import { pathToFileURL as pathToFileURL7 } from "node:url";
142373
142529
  function realInside(dir, abs) {
@@ -142393,7 +142549,7 @@ function archiveFile(dir, memory, abs) {
142393
142549
  if (size === 0) return null;
142394
142550
  const key3 = relative9(dir, abs);
142395
142551
  const hit = memory.files?.[key3];
142396
- if (hit && hit.size === size && hit.mtimeMs === mtimeMs && hit.ino === ino && existsSync50(join51(dir, HISTORY_DIR, `${hit.sha}.${hit.ext}`))) {
142552
+ if (hit && hit.size === size && hit.mtimeMs === mtimeMs && hit.ino === ino && existsSync51(join51(dir, HISTORY_DIR, `${hit.sha}.${hit.ext}`))) {
142397
142553
  return { sha: hit.sha, ext: hit.ext, file: `${hit.sha}.${hit.ext}` };
142398
142554
  }
142399
142555
  let archived;
@@ -142414,7 +142570,7 @@ function loadMemory(dir, now) {
142414
142570
  function observeShots(dir, memory, now) {
142415
142571
  const shotsDir = join51(dir, ".himi", "shots");
142416
142572
  const seen = /* @__PURE__ */ new Set();
142417
- const files = existsSync50(shotsDir) ? readdirSync27(shotsDir).filter((f2) => /\.(png|jpe?g)$/i.test(f2)).sort() : [];
142573
+ const files = existsSync51(shotsDir) ? readdirSync27(shotsDir).filter((f2) => /\.(png|jpe?g)$/i.test(f2)).sort() : [];
142418
142574
  for (const f2 of files) {
142419
142575
  const id = basename11(f2, extname3(f2));
142420
142576
  const archived = archiveFile(dir, memory, join51(shotsDir, f2));
@@ -142432,7 +142588,7 @@ function observeShots(dir, memory, now) {
142432
142588
  memory.shots[id] = { ...prev, present: true };
142433
142589
  }
142434
142590
  }
142435
- if (existsSync50(shotsDir)) {
142591
+ if (existsSync51(shotsDir)) {
142436
142592
  for (const [id, shot] of Object.entries(memory.shots)) if (!seen.has(id) && shot.present) memory.shots[id] = { ...shot, present: false };
142437
142593
  }
142438
142594
  if (memory.timeline.length > MAX_TIMELINE) memory.timeline = memory.timeline.slice(-MAX_TIMELINE);
@@ -142458,7 +142614,7 @@ function appIdentity(dir) {
142458
142614
  }
142459
142615
  function testRuns(dir) {
142460
142616
  const att = join51(dir, ".himi", "attestations");
142461
- if (!existsSync50(att)) return [];
142617
+ if (!existsSync51(att)) return [];
142462
142618
  const runs = [];
142463
142619
  for (const f2 of readdirSync27(att)) {
142464
142620
  if (!f2.endsWith(".json") || f2 === "latest.json") continue;
@@ -142479,7 +142635,7 @@ function testRuns(dir) {
142479
142635
  }
142480
142636
  function siteHome(dir) {
142481
142637
  for (const pages2 of [join51(dir, ".himi", "business-book", "evidence", "pages"), join51(dir, "evidence", "pages")]) {
142482
- if (!existsSync50(pages2)) continue;
142638
+ if (!existsSync51(pages2)) continue;
142483
142639
  const home = readdirSync27(pages2).filter((f2) => /^home.*\.(png|jpe?g)$/i.test(f2)).sort()[0];
142484
142640
  if (home) return join51(pages2, home);
142485
142641
  }
@@ -142685,7 +142841,7 @@ function writeBoard(dir, now) {
142685
142841
  }
142686
142842
  function refreshStudio(dir, now = /* @__PURE__ */ new Date()) {
142687
142843
  try {
142688
- if (!existsSync50(join51(dir, STUDIO_PAGE))) return { refreshed: false };
142844
+ if (!existsSync51(join51(dir, STUDIO_PAGE))) return { refreshed: false };
142689
142845
  return { refreshed: true, view: writeBoard(dir, now.toISOString()) };
142690
142846
  } catch {
142691
142847
  return { refreshed: false };
@@ -143368,7 +143524,7 @@ __export(preflight_exports, {
143368
143524
  parseStoreConfig: () => parseStoreConfig,
143369
143525
  requireEnv: () => requireEnv
143370
143526
  });
143371
- import { existsSync as existsSync51, readFileSync as readFileSync59 } from "node:fs";
143527
+ import { existsSync as existsSync52, readFileSync as readFileSync59 } from "node:fs";
143372
143528
  import { isAbsolute as isAbsolute4, relative as relative10, resolve as resolve42 } from "node:path";
143373
143529
  function isInsideRepo(p2) {
143374
143530
  const rel = relative10(REPO_ROOT3, resolve42(p2));
@@ -143425,7 +143581,7 @@ function parseStoreConfig(text9) {
143425
143581
  }
143426
143582
  function loadStoreConfig(app) {
143427
143583
  const p2 = storeConfigPath(app);
143428
- if (!existsSync51(p2)) {
143584
+ if (!existsSync52(p2)) {
143429
143585
  throw new Error(`No store config at ${p2}. Create apps/${app}/store/store.config.yaml first (see /setup-store-signing).`);
143430
143586
  }
143431
143587
  return parseStoreConfig(readFileSync59(p2, "utf8"));
@@ -150157,7 +150313,7 @@ var init_customer_signing_inspect = __esm({
150157
150313
  });
150158
150314
 
150159
150315
  // src/push-onboarding.ts
150160
- import { existsSync as existsSync52, mkdirSync as mkdirSync24, readFileSync as readFileSync60, statSync as statSync13, writeFileSync as writeFileSync20, chmodSync as chmodSync2 } from "node:fs";
150316
+ import { existsSync as existsSync53, mkdirSync as mkdirSync24, readFileSync as readFileSync60, statSync as statSync13, writeFileSync as writeFileSync20, chmodSync as chmodSync2 } from "node:fs";
150161
150317
  import { basename as basename12, dirname as dirname32, join as join52, resolve as resolve43 } from "node:path";
150162
150318
  function readJson5(path2) {
150163
150319
  try {
@@ -150169,7 +150325,7 @@ function readJson5(path2) {
150169
150325
  }
150170
150326
  function pushInputsFromContent(dir) {
150171
150327
  const root = resolve43(dir);
150172
- if (!existsSync52(join52(root, "himalaya.content.json"))) return { initialized: false };
150328
+ if (!existsSync53(join52(root, "himalaya.content.json"))) return { initialized: false };
150173
150329
  const content = readJson5(join52(root, "himalaya.content.json"));
150174
150330
  const provisioning = readJson5(join52(root, "provisioning.json"));
150175
150331
  const native = provisioning.native ?? {};
@@ -150301,7 +150457,7 @@ function buildPushSetupBody(i2, keys) {
150301
150457
  }
150302
150458
  function readPushOnboarding(dir) {
150303
150459
  const path2 = join52(resolve43(dir), PUSH_ONBOARDING_PATH);
150304
- if (!existsSync52(path2)) return { version: 1 };
150460
+ if (!existsSync53(path2)) return { version: 1 };
150305
150461
  const parsed = readJson5(path2);
150306
150462
  return { version: 1, ...parsed };
150307
150463
  }
@@ -150336,7 +150492,7 @@ function recordPushDeferral(dir, d2) {
150336
150492
  }
150337
150493
  function clearPushDeferral(dir) {
150338
150494
  const path2 = join52(resolve43(dir), PUSH_ONBOARDING_PATH);
150339
- if (!existsSync52(path2)) return;
150495
+ if (!existsSync53(path2)) return;
150340
150496
  const { push: _dropped, ...rest } = readPushOnboarding(dir);
150341
150497
  writeFile(dir, { ...rest, version: 1 });
150342
150498
  }
@@ -150404,7 +150560,7 @@ var signing_inspect_exports = {};
150404
150560
  __export(signing_inspect_exports, {
150405
150561
  runSigningInspect: () => runSigningInspect
150406
150562
  });
150407
- import { existsSync as existsSync53, readFileSync as readFileSync61, statSync as statSync14 } from "node:fs";
150563
+ import { existsSync as existsSync54, readFileSync as readFileSync61, statSync as statSync14 } from "node:fs";
150408
150564
  import { isAbsolute as isAbsolute5, resolve as resolve44 } from "node:path";
150409
150565
  function fail4(io2, code, fields = {}) {
150410
150566
  io2.error(JSON.stringify({ ok: false, code, ...fields }));
@@ -150494,7 +150650,7 @@ async function runSigningInspect(pos, flags, io2, deps = {}) {
150494
150650
  } catch (error) {
150495
150651
  return fail4(io2, "signing_inspect_key_inside_repo", { error: error.message });
150496
150652
  }
150497
- if (!existsSync53(certPath) || !existsSync53(profilePath2)) {
150653
+ if (!existsSync54(certPath) || !existsSync54(profilePath2)) {
150498
150654
  return fail4(io2, "signing_inspect_local_assets_unreadable", { error: "cannot read --cert-file or --profile-file" });
150499
150655
  }
150500
150656
  if (statSync14(certPath).size > 1048576 || statSync14(profilePath2).size > 1048576) {
@@ -151237,7 +151393,7 @@ __export(pack_exports, {
151237
151393
  });
151238
151394
  import { createHash as createHash29 } from "node:crypto";
151239
151395
  import { deflateRawSync, inflateRawSync } from "node:zlib";
151240
- import { existsSync as existsSync54, mkdirSync as mkdirSync25, readFileSync as readFileSync63, readdirSync as readdirSync28, rmSync as rmSync12, statSync as statSync15, writeFileSync as writeFileSync21 } from "node:fs";
151396
+ import { existsSync as existsSync55, mkdirSync as mkdirSync25, readFileSync as readFileSync63, readdirSync as readdirSync28, rmSync as rmSync12, statSync as statSync15, writeFileSync as writeFileSync21 } from "node:fs";
151241
151397
  import { dirname as dirname33, join as join54, resolve as resolve46 } from "node:path";
151242
151398
  function writeZip(entries) {
151243
151399
  const sorted2 = entries.slice().sort((a2, b2) => a2.path < b2.path ? -1 : a2.path > b2.path ? 1 : 0);
@@ -151332,10 +151488,10 @@ function inflateEntry(buf, entry) {
151332
151488
  return bytes2;
151333
151489
  }
151334
151490
  function readIf(path2) {
151335
- return existsSync54(path2) && statSync15(path2).isFile() ? readFileSync63(path2) : null;
151491
+ return existsSync55(path2) && statSync15(path2).isFile() ? readFileSync63(path2) : null;
151336
151492
  }
151337
151493
  function listDir(dir) {
151338
- return existsSync54(dir) ? readdirSync28(dir).filter((f2) => statSync15(join54(dir, f2)).isFile()) : [];
151494
+ return existsSync55(dir) ? readdirSync28(dir).filter((f2) => statSync15(join54(dir, f2)).isFile()) : [];
151339
151495
  }
151340
151496
  function gatherReleaseEntries(appDir3) {
151341
151497
  const manifestPath = join54(appDir3, HIMI_PACKAGE_MANIFEST_PATH);
@@ -151414,7 +151570,7 @@ function packRelease(releaseRoot, app, out2, opts = {}) {
151414
151570
  const appDir3 = join54(resolve46(releaseRoot), app);
151415
151571
  const { all, header, skipped } = buildEntries(appDir3, app, opts);
151416
151572
  const buf = writeZip(all);
151417
- const isDir2 = existsSync54(out2) && statSync15(out2).isDirectory();
151573
+ const isDir2 = existsSync55(out2) && statSync15(out2).isDirectory();
151418
151574
  const outFile = isDir2 ? join54(resolve46(out2), packageFileName(app, header.releaseId)) : resolve46(out2);
151419
151575
  mkdirSync25(dirname33(outFile), { recursive: true });
151420
151576
  writeFileSync21(outFile, buf);
@@ -151431,11 +151587,11 @@ function resolvePackageDirDest(outDir, app, releaseId) {
151431
151587
  }
151432
151588
  };
151433
151589
  const replaceable = (dir) => {
151434
- if (!existsSync54(dir)) return true;
151590
+ if (!existsSync55(dir)) return true;
151435
151591
  if (!statSync15(dir).isDirectory()) return false;
151436
151592
  return readdirSync28(dir).length === 0 || packagedApp(dir) === app;
151437
151593
  };
151438
- if (existsSync54(outDir) && !statSync15(outDir).isDirectory()) {
151594
+ if (existsSync55(outDir) && !statSync15(outDir).isDirectory()) {
151439
151595
  throw new Error(`refusing to write a package tree over ${outDir} \u2014 it is a file, not a directory`);
151440
151596
  }
151441
151597
  if (replaceable(outDir)) return outDir;
@@ -151496,7 +151652,7 @@ function openPackageDir(dir) {
151496
151652
  else if (isSafeEntryName(childRel)) entries.set(childRel, readFileSync63(childAbs));
151497
151653
  }
151498
151654
  };
151499
- if (!existsSync54(root)) throw new Error(`no such package directory: ${root}`);
151655
+ if (!existsSync55(root)) throw new Error(`no such package directory: ${root}`);
151500
151656
  walk2("");
151501
151657
  const manifestBytes = entries.get(HIMI_PACKAGE_MANIFEST_PATH);
151502
151658
  if (manifestBytes) {
@@ -151581,7 +151737,7 @@ __export(app_source_exports, {
151581
151737
  zipAppSource: () => zipAppSource
151582
151738
  });
151583
151739
  import { createHash as createHash30 } from "node:crypto";
151584
- import { readdirSync as readdirSync29, lstatSync as lstatSync15, readFileSync as readFileSync64, mkdirSync as mkdirSync26, writeFileSync as writeFileSync22, existsSync as existsSync55, rmSync as rmSync13, rmdirSync as rmdirSync2, unlinkSync as unlinkSync4 } from "node:fs";
151740
+ import { readdirSync as readdirSync29, lstatSync as lstatSync15, readFileSync as readFileSync64, mkdirSync as mkdirSync26, writeFileSync as writeFileSync22, existsSync as existsSync56, rmSync as rmSync13, rmdirSync as rmdirSync2, unlinkSync as unlinkSync4 } from "node:fs";
151585
151741
  import { join as join55, resolve as resolve47, sep as sep13 } from "node:path";
151586
151742
  import { createRequire as createRequire3 } from "node:module";
151587
151743
  import { deflateRawSync as deflateRawSync2 } from "node:zlib";
@@ -151597,7 +151753,7 @@ function walkSourceTree(dir, file2, skip, enter = () => {
151597
151753
  continue;
151598
151754
  }
151599
151755
  if (st2.isDirectory()) {
151600
- if (isDeniedSourceDir(name, relDir) || existsSync55(join55(dir, rel, PACKAGE_DIR_MARKER))) skip(rel);
151756
+ if (isDeniedSourceDir(name, relDir) || existsSync56(join55(dir, rel, PACKAGE_DIR_MARKER))) skip(rel);
151601
151757
  else walk2(rel);
151602
151758
  continue;
151603
151759
  }
@@ -151765,7 +151921,7 @@ function writeAppSource(entries, destDir) {
151765
151921
  return written;
151766
151922
  }
151767
151923
  function staleSourcePaths(entries, destDir) {
151768
- if (!existsSync55(destDir)) return [];
151924
+ if (!existsSync56(destDir)) return [];
151769
151925
  const archived = new Set(entries.map((e2) => e2.path));
151770
151926
  const stale = [];
151771
151927
  walkSourceTree(destDir, (archivePath) => {
@@ -151821,7 +151977,7 @@ function removeStaleSource(entries, destDir) {
151821
151977
  const segments = entry.path.split("/");
151822
151978
  for (let i2 = 1; i2 < segments.length; i2++) needed.add(segments.slice(0, i2).join("/"));
151823
151979
  }
151824
- if (existsSync55(root)) pruneEmptyDirs(root, "", needed, removed);
151980
+ if (existsSync56(root)) pruneEmptyDirs(root, "", needed, removed);
151825
151981
  return removed.sort();
151826
151982
  }
151827
151983
  function pruneEmptyDirs(root, rel, needed, removed) {
@@ -151909,7 +152065,7 @@ __export(run_watch_exports, {
151909
152065
  watchedContentDir: () => watchedContentDir,
151910
152066
  writeRunRecord: () => writeRunRecord
151911
152067
  });
151912
- import { closeSync as closeSync4, constants as constants2, existsSync as existsSync56, fstatSync, lstatSync as lstatSync16, statSync as statSync16, readdirSync as readdirSync30, mkdirSync as mkdirSync27, openSync as openSync4, readFileSync as readFileSync65, realpathSync as realpathSync9, renameSync as renameSync10, rmSync as rmSync14, writeFileSync as writeFileSync23, watch as fsWatch } from "node:fs";
152068
+ import { closeSync as closeSync4, constants as constants2, existsSync as existsSync57, fstatSync, lstatSync as lstatSync16, statSync as statSync16, readdirSync as readdirSync30, mkdirSync as mkdirSync27, openSync as openSync4, readFileSync as readFileSync65, realpathSync as realpathSync9, renameSync as renameSync10, rmSync as rmSync14, writeFileSync as writeFileSync23, watch as fsWatch } from "node:fs";
151913
152069
  import { randomUUID as randomUUID6 } from "node:crypto";
151914
152070
  import { extname as extname4, join as join56, resolve as resolve48, sep as sep14 } from "node:path";
151915
152071
  function diffReleases(prev, next) {
@@ -152016,7 +152172,7 @@ function watchedContentDir(source) {
152016
152172
  if (!source || /^https?:\/\//i.test(source)) return null;
152017
152173
  const dir = resolve48(source);
152018
152174
  try {
152019
- return statSync16(dir).isDirectory() && existsSync56(join56(dir, "himalaya.content.json")) ? dir : null;
152175
+ return statSync16(dir).isDirectory() && existsSync57(join56(dir, "himalaya.content.json")) ? dir : null;
152020
152176
  } catch {
152021
152177
  return null;
152022
152178
  }
@@ -152671,7 +152827,7 @@ __export(milestones_exports, {
152671
152827
  });
152672
152828
  import { createHash as createHash33, randomUUID as randomUUID7 } from "node:crypto";
152673
152829
  import { spawn as spawn5 } from "node:child_process";
152674
- import { closeSync as closeSync5, existsSync as existsSync57, lstatSync as lstatSync19, readFileSync as readFileSync69, statSync as statSync17 } from "node:fs";
152830
+ import { closeSync as closeSync5, existsSync as existsSync58, lstatSync as lstatSync19, readFileSync as readFileSync69, statSync as statSync17 } from "node:fs";
152675
152831
  import { createServer as createServer4 } from "node:net";
152676
152832
  import { basename as basename15, dirname as dirname34, isAbsolute as isAbsolute6, join as join60, relative as relative11, resolve as resolve49, sep as sep15 } from "node:path";
152677
152833
  function homeShotPath(dir, home) {
@@ -152784,7 +152940,7 @@ function autoPictureGate(dir) {
152784
152940
  }
152785
152941
  async function homePictureAtValidate(dir, opts) {
152786
152942
  if (!opts.ok) return { skipped: "validate found errors, so the picture was left as it is" };
152787
- if (!existsSync57(join60(dir, "himalaya.content.json"))) return { skipped: "not a content package" };
152943
+ if (!existsSync58(join60(dir, "himalaya.content.json"))) return { skipped: "not a content package" };
152788
152944
  const env = opts.env ?? process.env;
152789
152945
  if (ciSet(env)) return { skipped: "the CI environment variable is set" };
152790
152946
  if (env.NODE_TEST_CONTEXT) return { skipped: "running under `node --test`" };
@@ -152854,7 +153010,7 @@ function stillBuilding(dir, image, now) {
152854
153010
  }
152855
153011
  }
152856
153012
  function firstLookBeforeOwnPostcard(dir, image, now) {
152857
- if (!image || !existsSync57(image) || initDivergence(dir).state !== "diverged") return void 0;
153013
+ if (!image || !existsSync58(image) || initDivergence(dir).state !== "diverged") return void 0;
152858
153014
  return journal(dir, "first-look", withHomeCaveat(yourFirstLookMessage(dir), homeCaveat(dir, image)), { image, ...now ? { now } : {} });
152859
153015
  }
152860
153016
  function afterRenderPng(dir, input) {
@@ -152919,13 +153075,13 @@ function testChangeNote(headline2, change) {
152919
153075
  }
152920
153076
  function afterTestRun(dir, input) {
152921
153077
  const firstLook = firstLookBeforeOwnPostcard(dir, input.homeShot, input.now);
152922
- const shot = input.homeShot && existsSync57(input.homeShot) ? input.homeShot : void 0;
153078
+ const shot = input.homeShot && existsSync58(input.homeShot) ? input.homeShot : void 0;
152923
153079
  const caveat = shot ? homeCaveat(dir, shot) : void 0;
152924
153080
  const counts = testPostcardMessage(input);
152925
153081
  const headline2 = caveat ? `${counts} But ${caveat}.` : counts;
152926
153082
  const postcard = journal(dir, "test", headline2, {
152927
153083
  ref: input.runId,
152928
- ...input.homeShot && existsSync57(input.homeShot) ? { image: input.homeShot } : {},
153084
+ ...input.homeShot && existsSync58(input.homeShot) ? { image: input.homeShot } : {},
152929
153085
  ...input.now ? { now: input.now } : {},
152930
153086
  unlessUnchanged: true,
152931
153087
  changeNote: (change) => testChangeNote(headline2, change)
@@ -152968,7 +153124,7 @@ function draftPictureGap(input) {
152968
153124
  if (!input.home) return { reason: "the app's dev/index.ts names no literal homeScreenId, so there is no home screen to picture" };
152969
153125
  if (!input.homeShot) return { reason: "the homeScreenId does not name a file under .himi/shots" };
152970
153126
  const render = `himi render ${shellQuote(input.home)} --png${contentArg(input.content)}`;
152971
- if (!existsSync57(input.homeShot)) return { reason: "there is no home shot yet", render };
153127
+ if (!existsSync58(input.homeShot)) return { reason: "there is no home shot yet", render };
152972
153128
  if (input.sourceChangedAtMs === void 0) return { reason: "the source's last change could not be read, so the home shot cannot be shown to be current", render };
152973
153129
  if (!shotIsCurrent(input.homeShot, input.sourceChangedAtMs)) return { reason: "the home shot is older than the last source edit, so it is not a picture of this draft", render };
152974
153130
  return null;
@@ -153046,7 +153202,7 @@ function draftChangeNote(dir, input) {
153046
153202
  if (!previous) return void 0;
153047
153203
  const shaOf = (i2) => i2 && typeof i2 === "object" && typeof i2.sha256 === "string" ? i2.sha256 : void 0;
153048
153204
  const had = Array.isArray(previous.images) ? previous.images.map(shaOf).find(Boolean) : void 0;
153049
- const has = input.picture && existsSync57(input.picture) ? sha256Of2(input.picture) : void 0;
153205
+ const has = input.picture && existsSync58(input.picture) ? sha256Of2(input.picture) : void 0;
153050
153206
  if (had && has) parts.push(had === has ? "the home screen looks the same" : "the home screen changed");
153051
153207
  else if (has) parts.push("a home picture this time");
153052
153208
  else return void 0;
@@ -153112,7 +153268,7 @@ function homeShotForPostcard(dir, opts = {}) {
153112
153268
  const shot = homeShotPath(dir, home);
153113
153269
  if (!shot) return { skipped: "the homeScreenId does not name a file under .himi/shots" };
153114
153270
  const render = `\`himi render ${shellQuote(home)} --png\``;
153115
- if (!existsSync57(shot)) return { skipped: `no home shot yet \u2014 ${render} makes one, and the next postcard carries it` };
153271
+ if (!existsSync58(shot)) return { skipped: `no home shot yet \u2014 ${render} makes one, and the next postcard carries it` };
153116
153272
  let changed;
153117
153273
  try {
153118
153274
  changed = newestSourceChangeMs(dir);
@@ -153192,7 +153348,7 @@ function liveWatchRunning(dir, isAlive = pidAlive, now) {
153192
153348
  }
153193
153349
  function watchReminder(dir, opts = {}) {
153194
153350
  try {
153195
- if (!existsSync57(join60(dir, "himalaya.content.json"))) return void 0;
153351
+ if (!existsSync58(join60(dir, "himalaya.content.json"))) return void 0;
153196
153352
  const nowDate = opts.now ?? /* @__PURE__ */ new Date();
153197
153353
  const live3 = liveWatch(dir, opts.isAlive, nowDate);
153198
153354
  const now = nowDate.getTime();
@@ -153748,17 +153904,17 @@ __export(template_recommend_exports, {
153748
153904
  recommendTemplates: () => recommendTemplates,
153749
153905
  verticalsFromBook: () => verticalsFromBook
153750
153906
  });
153751
- import { existsSync as existsSync58, readFileSync as readFileSync71 } from "node:fs";
153907
+ import { existsSync as existsSync59, readFileSync as readFileSync71 } from "node:fs";
153752
153908
  import { join as join62 } from "node:path";
153753
153909
  function verticalsFromBook(path2) {
153754
- const dir = existsSync58(join62(path2, "book.json")) || existsSync58(join62(path2, "provisioning.overlay.json")) ? path2 : join62(path2, ".himi", "business-book");
153910
+ const dir = existsSync59(join62(path2, "book.json")) || existsSync59(join62(path2, "provisioning.overlay.json")) ? path2 : join62(path2, ".himi", "business-book");
153755
153911
  const overlay = join62(dir, "provisioning.overlay.json");
153756
- if (existsSync58(overlay)) {
153912
+ if (existsSync59(overlay)) {
153757
153913
  const v2 = JSON.parse(readFileSync71(overlay, "utf8")).installedVerticals;
153758
153914
  if (Array.isArray(v2) && v2.length) return v2.filter((x2) => typeof x2 === "string");
153759
153915
  }
153760
153916
  const book = join62(dir, "book.json");
153761
- if (existsSync58(book)) {
153917
+ if (existsSync59(book)) {
153762
153918
  const probes = JSON.parse(readFileSync71(book, "utf8")).probes;
153763
153919
  if (Array.isArray(probes)) return installedFromProbes(probes);
153764
153920
  }
@@ -154176,7 +154332,7 @@ __export(base44_types_exports, {
154176
154332
  renderBase44Types: () => renderBase44Types,
154177
154333
  writeBase44Types: () => writeBase44Types
154178
154334
  });
154179
- import { existsSync as existsSync59, mkdirSync as mkdirSync28, readFileSync as readFileSync72, writeFileSync as writeFileSync25 } from "node:fs";
154335
+ import { existsSync as existsSync60, mkdirSync as mkdirSync28, readFileSync as readFileSync72, writeFileSync as writeFileSync25 } from "node:fs";
154180
154336
  import { dirname as dirname35, join as join63 } from "node:path";
154181
154337
  function logicalName(spec) {
154182
154338
  return (isAdoptedEntity(spec) ? spec.base44Name : spec.name) ?? "";
@@ -154256,7 +154412,7 @@ async function writeBase44Types(dir, app) {
154256
154412
  if (!list?.length) throw new Base44TypesError("no_base44_entities", "config.ts declares no base44.entities \u2014 nothing to type. Declare them (or run `himi base44 adopt`) first.");
154257
154413
  const text9 = renderBase44Types(list, app);
154258
154414
  const path2 = join63(dir, BASE44_TYPES_PATH);
154259
- const changed = !existsSync59(path2) || readFileSync72(path2, "utf8") !== text9;
154415
+ const changed = !existsSync60(path2) || readFileSync72(path2, "utf8") !== text9;
154260
154416
  if (changed) {
154261
154417
  mkdirSync28(dirname35(path2), { recursive: true });
154262
154418
  writeFileSync25(path2, text9);
@@ -154265,7 +154421,7 @@ async function writeBase44Types(dir, app) {
154265
154421
  }
154266
154422
  async function base44TypesIssues(dir, app, strict) {
154267
154423
  const path2 = join63(dir, BASE44_TYPES_PATH);
154268
- if (!existsSync59(path2)) return [];
154424
+ if (!existsSync60(path2)) return [];
154269
154425
  let list;
154270
154426
  try {
154271
154427
  list = await declaredEntities(dir);
@@ -154408,13 +154564,13 @@ __export(eject_exports, {
154408
154564
  EJECTABLE: () => EJECTABLE,
154409
154565
  ejectModule: () => ejectModule
154410
154566
  });
154411
- import { existsSync as existsSync60, mkdirSync as mkdirSync29, readFileSync as readFileSync73, writeFileSync as writeFileSync26 } from "node:fs";
154567
+ import { existsSync as existsSync61, mkdirSync as mkdirSync29, readFileSync as readFileSync73, writeFileSync as writeFileSync26 } from "node:fs";
154412
154568
  import { dirname as dirname36, join as join64, relative as relative12, resolve as resolve50, sep as sep16 } from "node:path";
154413
154569
  function locate(repoRootOrCwd, mod) {
154414
154570
  const inRepo = resolve50(repoRootOrCwd, `stdlib/flows/${mod}/src/index.ts`);
154415
- if (existsSync60(inRepo)) return { path: inRepo, form: "source" };
154571
+ if (existsSync61(inRepo)) return { path: inRepo, form: "source" };
154416
154572
  const dist = resolve50(repoRootOrCwd, `node_modules/@wix/himalaya/dist/${mod}.mjs`);
154417
- if (existsSync60(dist)) return { path: dist, form: "bundle" };
154573
+ if (existsSync61(dist)) return { path: dist, form: "bundle" };
154418
154574
  return null;
154419
154575
  }
154420
154576
  function specifiersFor(mod) {
@@ -154459,7 +154615,7 @@ function ejectModule(opts) {
154459
154615
  writeFileSync26(target, banner + normalized);
154460
154616
  const rewired = [];
154461
154617
  for (const f2 of files) {
154462
- if (!existsSync60(f2)) continue;
154618
+ if (!existsSync61(f2)) continue;
154463
154619
  const before = readFileSync73(f2, "utf8");
154464
154620
  let after = before;
154465
154621
  let rel = relative12(dirname36(f2), target).split(sep16).join("/").replace(/\.tsx?$/, ".js");
@@ -154580,7 +154736,7 @@ var init_app_map = __esm({
154580
154736
  });
154581
154737
 
154582
154738
  // src/wix-writes.ts
154583
- import { existsSync as existsSync61, readFileSync as readFileSync74 } from "node:fs";
154739
+ import { existsSync as existsSync62, readFileSync as readFileSync74 } from "node:fs";
154584
154740
  import { join as join65 } from "node:path";
154585
154741
  function isProvenRead(method, path2) {
154586
154742
  if (/[#\x00-\x1F\x7F]/.test(path2)) return false;
@@ -154700,7 +154856,7 @@ function parseDataAccess(text9, from) {
154700
154856
  function readDataAccess(dir) {
154701
154857
  for (const name of ["SPEC.md", "MOBILE-UX.md"]) {
154702
154858
  const p2 = join65(dir, name);
154703
- if (!existsSync61(p2)) continue;
154859
+ if (!existsSync62(p2)) continue;
154704
154860
  let text9;
154705
154861
  try {
154706
154862
  text9 = readFileSync74(p2, "utf8");
@@ -154819,11 +154975,11 @@ __export(test_exports, {
154819
154975
  scopeDescriptors: () => scopeDescriptors,
154820
154976
  writeRecordedMocks: () => writeRecordedMocks
154821
154977
  });
154822
- import { existsSync as existsSync62, mkdirSync as mkdirSync30, readFileSync as readFileSync75, writeFileSync as writeFileSync27 } from "node:fs";
154978
+ import { existsSync as existsSync63, mkdirSync as mkdirSync30, readFileSync as readFileSync75, writeFileSync as writeFileSync27 } from "node:fs";
154823
154979
  import { join as join66, resolve as resolve51 } from "node:path";
154824
154980
  function readTestConfig(dir) {
154825
154981
  const p2 = resolve51(dir, TEST_CONFIG_FILE);
154826
- if (!existsSync62(p2)) return {};
154982
+ if (!existsSync63(p2)) return {};
154827
154983
  let parsed;
154828
154984
  try {
154829
154985
  parsed = JSON.parse(readFileSync75(p2, "utf8"));
@@ -154894,7 +155050,7 @@ function readNetRules(path2) {
154894
155050
  function defaultNetRules(dir) {
154895
155051
  for (const rel of ["dev/net-mocks.json", "tests/net-mocks.json"]) {
154896
155052
  const p2 = resolve51(dir, rel);
154897
- if (existsSync62(p2)) {
155053
+ if (existsSync63(p2)) {
154898
155054
  const rules = readNetRules(p2);
154899
155055
  if (rules.length) return { rules, from: rel };
154900
155056
  }
@@ -155328,7 +155484,17 @@ async function runCrawl(opts) {
155328
155484
  const unreachedWrites = targets.flatMap((d2) => unreachedNativeWrites(d2.screenId, d2.bundleJs, inventory));
155329
155485
  const plan = readDataAccess(opts.dir);
155330
155486
  const writeFindings = unapprovedWriteFindings([...inventory, ...unreachedWrites], plan);
155331
- const all = [...results.flatMap((r2) => r2.findings), ...hostileFindings, ...deepFindings, ...journeyFindings, ...edgeFindings, ...relationFindings, ...writeFindings].filter((f2) => {
155487
+ const tokenFindings = tokenNumericIssuesFor(opts.dir).map((issue2) => ({
155488
+ screen: TOKENS_FINDING_SCREEN,
155489
+ trigger: "boot",
155490
+ invariant: "token-type-invalid",
155491
+ severity: "error",
155492
+ // The token path keeps each finding's stable id distinct (findingId hashes `at`).
155493
+ ...issue2.path ? { at: issue2.path } : {},
155494
+ message: issue2.message,
155495
+ hint: "Fix the value in the tokens file; `himi validate` reports the same finding."
155496
+ }));
155497
+ const all = [...results.flatMap((r2) => r2.findings), ...hostileFindings, ...deepFindings, ...journeyFindings, ...edgeFindings, ...relationFindings, ...writeFindings, ...tokenFindings].filter((f2) => {
155332
155498
  if (f2.invariant === "no-request-issued" && !f2.axis && fetchProven.has(f2.screen)) {
155333
155499
  const by = fetchProven.get(f2.screen);
155334
155500
  if (!retired.some((x2) => x2.screen === f2.screen)) retired.push({ screen: f2.screen, from: by.from, params: by.params });
@@ -155338,7 +155504,7 @@ async function runCrawl(opts) {
155338
155504
  }).filter(keep);
155339
155505
  const failures = all.filter((f2) => f2.severity === "error");
155340
155506
  const warnings = all.filter((f2) => f2.severity === "warning");
155341
- const failedScreens = new Set(failures.map((f2) => f2.screen));
155507
+ const failedScreens = new Set(failures.map((f2) => f2.screen).filter((screen) => screen !== TOKENS_FINDING_SCREEN));
155342
155508
  const blockedReasons = [];
155343
155509
  if (unknownScreens.length) blockedReasons.push(`not in this release: ${unknownScreens.join(", ")}`);
155344
155510
  if (notCrawled.length) blockedReasons.push(`${notCrawled.length} screen(s) skipped because they fail \`himi validate\` \u2014 fix those first`);
@@ -155412,9 +155578,12 @@ function formatReport(r2) {
155412
155578
  for (const platform of ["ios", "android"]) {
155413
155579
  const summary2 = r2.nativeDecode[platform];
155414
155580
  if (!summary2) continue;
155415
- out2.push("unavailable" in summary2 ? `native decode ${platform}: unavailable \u2014 ${summary2.reason}` : `native decode ${platform}: ${summary2.checked} checked, ${summary2.failed} failed in ${r2.nativeDecode.wallMs}ms`);
155581
+ out2.push("unavailable" in summary2 ? `native decode ${platform}: unavailable \u2014 ${summary2.reason}` : `native decode ${platform}: ${summary2.checked} checked, ${summary2.failed} failed${summary2.tokens ? `, tokens.json ${summary2.tokens}` : ""} in ${r2.nativeDecode.wallMs}ms`);
155416
155582
  }
155417
155583
  }
155584
+ if (r2.skippedPlatforms?.length) {
155585
+ out2.push(`SKIPPED native platforms (NOT checked, not passing): ${r2.skippedPlatforms.map((skip) => skip.platform).join(", ")}`);
155586
+ }
155418
155587
  out2.push("");
155419
155588
  const grouped = /* @__PURE__ */ new Map();
155420
155589
  const rest = [];
@@ -155532,17 +155701,19 @@ function formatReport(r2) {
155532
155701
  }
155533
155702
  return out2.join("\n");
155534
155703
  }
155535
- var TEST_CONFIG_FILE, mapResult, triggerLabel;
155704
+ var TEST_CONFIG_FILE, mapResult, TOKENS_FINDING_SCREEN, triggerLabel;
155536
155705
  var init_test = __esm({
155537
155706
  "src/test.ts"() {
155538
155707
  init_app_map();
155539
155708
  init_screen_crawl();
155540
155709
  init_wix_gateway_rules();
155541
155710
  init_crawl_layers();
155711
+ init_token_lint();
155542
155712
  init_screen_state();
155543
155713
  init_wix_writes();
155544
155714
  TEST_CONFIG_FILE = "himi-test.json";
155545
155715
  mapResult = (r2) => ({ screen: r2.screen, navEdges: r2.navEdges ?? [], navUnfollowed: r2.navUnfollowed ?? 0, failed: (r2.findings ?? []).some((x2) => x2.severity === "error") });
155716
+ TOKENS_FINDING_SCREEN = "tokens.json";
155546
155717
  triggerLabel = (f2) => (f2.trigger === "boot" ? "on appear" : `${f2.trigger.key} ${f2.trigger.tap ?? "(no id)"} \u2192 ${f2.trigger.action}`) + (f2.axis ? ` [${f2.axis}]` : "");
155547
155718
  }
155548
155719
  });
@@ -155552,11 +155723,11 @@ var mobile_ux_lint_exports = {};
155552
155723
  __export(mobile_ux_lint_exports, {
155553
155724
  mobileUxIssues: () => mobileUxIssues
155554
155725
  });
155555
- import { existsSync as existsSync63, readFileSync as readFileSync76 } from "node:fs";
155726
+ import { existsSync as existsSync64, readFileSync as readFileSync76 } from "node:fs";
155556
155727
  import { join as join67 } from "node:path";
155557
155728
  function mobileUxIssues(dir, strict) {
155558
155729
  const file2 = join67(dir, "MOBILE-UX.md");
155559
- if (!existsSync63(file2)) return [];
155730
+ if (!existsSync64(file2)) return [];
155560
155731
  let text9;
155561
155732
  try {
155562
155733
  text9 = readFileSync76(file2, "utf8");
@@ -157240,7 +157411,7 @@ __export(functions_exports, {
157240
157411
  resolveFunctionsTarget: () => resolveFunctionsTarget,
157241
157412
  runRemoteFunctionOperation: () => runRemoteFunctionOperation
157242
157413
  });
157243
- import { readFileSync as readFileSync77, existsSync as existsSync64 } from "node:fs";
157414
+ import { readFileSync as readFileSync77, existsSync as existsSync65 } from "node:fs";
157244
157415
  import { join as join68, resolve as resolve52 } from "node:path";
157245
157416
  function resolveFunctionsTarget(input) {
157246
157417
  const explicitUrl = input.functionsUrl?.trim();
@@ -157260,7 +157431,7 @@ async function loadFunctionsApp(dir) {
157260
157431
  }
157261
157432
  const sources = {};
157262
157433
  for (const definition of config.functions.functions) {
157263
- const source = [".ts", ".js", ".mts", ".mjs"].map((extension) => join68(loaded.dir, "functions", `${definition.name}${extension}`)).find(existsSync64);
157434
+ const source = [".ts", ".js", ".mts", ".mjs"].map((extension) => join68(loaded.dir, "functions", `${definition.name}${extension}`)).find(existsSync65);
157264
157435
  if (!source) throw new Error(`missing source for function ${definition.name}; expected functions/${definition.name}.ts`);
157265
157436
  sources[definition.name] = readFileSync77(source, "utf8");
157266
157437
  }
@@ -157450,7 +157621,7 @@ var init_cli_bridge = __esm({
157450
157621
  });
157451
157622
 
157452
157623
  // src/mcp/file-tools.ts
157453
- import { closeSync as closeSync6, constants as constants3, lstatSync as lstatSync20, mkdirSync as mkdirSync31, openSync as openSync5, readdirSync as readdirSync31, readFileSync as readFileSync78, realpathSync as realpathSync10, renameSync as renameSync11, rmSync as rmSync15, statSync as statSync18, writeSync, existsSync as existsSync65 } from "node:fs";
157624
+ import { closeSync as closeSync6, constants as constants3, lstatSync as lstatSync20, mkdirSync as mkdirSync31, openSync as openSync5, readdirSync as readdirSync31, readFileSync as readFileSync78, realpathSync as realpathSync10, renameSync as renameSync11, rmSync as rmSync15, statSync as statSync18, writeSync, existsSync as existsSync66 } from "node:fs";
157454
157625
  import { randomBytes as randomBytes4 } from "node:crypto";
157455
157626
  import { dirname as dirname37, isAbsolute as isAbsolute7, join as join69, relative as relative13, resolve as resolve53, sep as sep17 } from "node:path";
157456
157627
  import * as z2 from "zod";
@@ -157460,7 +157631,7 @@ function within(root, p2) {
157460
157631
  function realish(p2) {
157461
157632
  let cur = p2;
157462
157633
  const tail = [];
157463
- while (!existsSync65(cur)) {
157634
+ while (!existsSync66(cur)) {
157464
157635
  const up = dirname37(cur);
157465
157636
  if (up === cur) break;
157466
157637
  tail.unshift(cur.slice(up.length + (up.endsWith(sep17) ? 0 : 1)));
@@ -157483,7 +157654,7 @@ function symlinkComponent(base, abs) {
157483
157654
  function workspaceRefusal(root, target) {
157484
157655
  const r2 = resolve53(root);
157485
157656
  const t2 = resolve53(r2, target);
157486
- if (!existsSync65(r2)) return `the workspace folder ${r2} does not exist`;
157657
+ if (!existsSync66(r2)) return `the workspace folder ${r2} does not exist`;
157487
157658
  if (!within(r2, t2) || !within(realpathSync10(r2), realish(t2))) return `"${target}" is outside the workspace folder ${r2}`;
157488
157659
  const link = symlinkComponent(r2, t2);
157489
157660
  if (link) return `"${link}" is a symlink \u2014 paths must stay in real folders inside the workspace`;
@@ -157492,13 +157663,13 @@ function workspaceRefusal(root, target) {
157492
157663
  async function confinedAppDir(args, deps) {
157493
157664
  const root = resolve53(await deps.defaultDir());
157494
157665
  const dir = typeof args.dir === "string" && args.dir ? resolve53(root, args.dir) : root;
157495
- if (!existsSync65(root)) return refuse5("no_workspace", `the workspace folder ${root} does not exist`);
157666
+ if (!existsSync66(root)) return refuse5("no_workspace", `the workspace folder ${root} does not exist`);
157496
157667
  if (!within(root, dir) || !within(realpathSync10(root), realish(dir))) return refuse5("outside_workspace", `"${String(args.dir)}" is outside the workspace folder`);
157497
157668
  const link = symlinkComponent(root, dir);
157498
157669
  if (link) return refuse5("outside_workspace", `"${link}" is a symlink \u2014 the app folder must be a real folder in the workspace`);
157499
157670
  const rel = relative13(root, dir);
157500
157671
  if (rel && (isDeniedSourcePath(`${rel}/x`) || isDeniedSourcePath(`${rel.toLowerCase()}/x`))) return refuse5("denied", `"${rel}" is a folder this tool does not touch`);
157501
- if (!existsSync65(join69(dir, CONTENT_MARKER))) {
157672
+ if (!existsSync66(join69(dir, CONTENT_MARKER))) {
157502
157673
  return refuse5("not_an_app", `"${rel || "."}" is not an app folder (no ${CONTENT_MARKER}) \u2014 see himi_list_apps, or create one with himi_init`);
157503
157674
  }
157504
157675
  return dir;
@@ -157506,7 +157677,7 @@ async function confinedAppDir(args, deps) {
157506
157677
  function onDiskSpelling(abs) {
157507
157678
  let cur = abs;
157508
157679
  const tail = [];
157509
- while (!existsSync65(cur)) {
157680
+ while (!existsSync66(cur)) {
157510
157681
  const up = dirname37(cur);
157511
157682
  if (up === cur) break;
157512
157683
  tail.unshift(cur.slice(up.length + (up.endsWith(sep17) ? 0 : 1)));
@@ -157530,7 +157701,7 @@ function confinedPath(appDir3, rel) {
157530
157701
  const abs = resolve53(appDir3, rel);
157531
157702
  if (!within(appDir3, abs) || abs === appDir3) return { error: `"${rel}" is outside the app folder` };
157532
157703
  const real = realish(abs);
157533
- const base = existsSync65(appDir3) ? realpathSync10(appDir3) : realish(appDir3);
157704
+ const base = existsSync66(appDir3) ? realpathSync10(appDir3) : realish(appDir3);
157534
157705
  if (!within(base, real) || real === base) return { error: `"${rel}" is outside the app folder` };
157535
157706
  const link = symlinkComponent(appDir3, abs);
157536
157707
  if (link) return { error: `"${link}" is a symlink, which this tool does not follow` };
@@ -157587,11 +157758,11 @@ function fileTools() {
157587
157758
  inputSchema: z2.object({}),
157588
157759
  handler: async (_a3, d2) => {
157589
157760
  const root = resolve53(await d2.defaultDir());
157590
- if (!existsSync65(root)) return ok({ ok: true, workspace: root, apps: [] });
157761
+ if (!existsSync66(root)) return ok({ ok: true, workspace: root, apps: [] });
157591
157762
  const apps = [];
157592
- if (existsSync65(join69(root, CONTENT_MARKER))) apps.push(".");
157763
+ if (existsSync66(join69(root, CONTENT_MARKER))) apps.push(".");
157593
157764
  for (const e2 of readdirSync31(root, { withFileTypes: true })) {
157594
- if (e2.isDirectory() && !e2.name.startsWith(".") && existsSync65(join69(root, e2.name, CONTENT_MARKER))) apps.push(e2.name);
157765
+ if (e2.isDirectory() && !e2.name.startsWith(".") && existsSync66(join69(root, e2.name, CONTENT_MARKER))) apps.push(e2.name);
157595
157766
  }
157596
157767
  return ok({ ok: true, workspace: root, apps: apps.sort() });
157597
157768
  }
@@ -157605,7 +157776,7 @@ function fileTools() {
157605
157776
  handler: async (a2, d2) => {
157606
157777
  const app = await confinedAppDir(a2, d2);
157607
157778
  if (typeof app !== "string") return app;
157608
- if (!existsSync65(app) || !statSync18(app).isDirectory()) return refuse5("no_app", `no folder at ${app}`);
157779
+ if (!existsSync66(app) || !statSync18(app).isDirectory()) return refuse5("no_app", `no folder at ${app}`);
157609
157780
  return ok({ ok: true, dir: app, ...listFiles(app) });
157610
157781
  }
157611
157782
  },
@@ -157620,7 +157791,7 @@ function fileTools() {
157620
157791
  if (typeof app !== "string") return app;
157621
157792
  const p2 = confinedPath(app, a2.path);
157622
157793
  if (typeof p2 !== "string") return refuse5("bad_path", p2.error);
157623
- if (!existsSync65(p2) || !lstatSync20(p2).isFile()) return refuse5("not_found", `no file "${String(a2.path)}"`);
157794
+ if (!existsSync66(p2) || !lstatSync20(p2).isFile()) return refuse5("not_found", `no file "${String(a2.path)}"`);
157624
157795
  const size = statSync18(p2).size;
157625
157796
  if (size > MAX_FILE_BYTES) return refuse5("too_large", `"${String(a2.path)}" is ${size} bytes \u2014 over the ${MAX_FILE_BYTES}-byte read limit`);
157626
157797
  return ok({ ok: true, path: a2.path, bytes: size, content: readFileSync78(p2, "utf8") });
@@ -157647,7 +157818,7 @@ function fileTools() {
157647
157818
  if (typeof p2 !== "string") refused2.push({ path: f2.path, error: p2.error });
157648
157819
  else if (typeof f2.content !== "string") refused2.push({ path: f2.path, error: "content must be text" });
157649
157820
  else if (Buffer.byteLength(f2.content) > MAX_FILE_BYTES) refused2.push({ path: f2.path, error: `over the ${MAX_FILE_BYTES}-byte limit` });
157650
- else if (existsSync65(p2) && !lstatSync20(p2).isFile()) refused2.push({ path: f2.path, error: "not a regular file" });
157821
+ else if (existsSync66(p2) && !lstatSync20(p2).isFile()) refused2.push({ path: f2.path, error: "not a regular file" });
157651
157822
  else if (planned2.some((q2) => q2.abs === p2)) refused2.push({ path: f2.path, error: "the same file twice in one call" });
157652
157823
  else planned2.push({ abs: p2, rel: String(f2.path), content: f2.content });
157653
157824
  }
@@ -157680,7 +157851,7 @@ function fileTools() {
157680
157851
  for (const rel of paths) {
157681
157852
  const p2 = confinedPath(app, rel);
157682
157853
  if (typeof p2 !== "string") refused2.push({ path: rel, error: p2.error });
157683
- else if (!existsSync65(p2)) refused2.push({ path: rel, error: "no such file" });
157854
+ else if (!existsSync66(p2)) refused2.push({ path: rel, error: "no such file" });
157684
157855
  else if (!lstatSync20(p2).isFile()) refused2.push({ path: rel, error: "not a regular file" });
157685
157856
  else if (!planned2.includes(p2)) {
157686
157857
  planned2.push(p2);
@@ -158236,7 +158407,7 @@ __export(server_exports, {
158236
158407
  startMcpServer: () => startMcpServer
158237
158408
  });
158238
158409
  import { mkdirSync as mkdirSync32, readFileSync as readFileSync79 } from "node:fs";
158239
- import { fileURLToPath as fileURLToPath24 } from "node:url";
158410
+ import { fileURLToPath as fileURLToPath25 } from "node:url";
158240
158411
  import { McpServer } from "@modelcontextprotocol/server";
158241
158412
  import { serveStdio, StdioServerTransport } from "@modelcontextprotocol/server/stdio";
158242
158413
  function protectStdout() {
@@ -158261,7 +158432,7 @@ async function firstRoot(server) {
158261
158432
  if (!server.server.getClientCapabilities()?.roots) return void 0;
158262
158433
  const { roots } = await server.server.listRoots();
158263
158434
  const uri = roots.find((r2) => r2.uri.startsWith("file://"))?.uri;
158264
- return uri ? fileURLToPath24(uri) : void 0;
158435
+ return uri ? fileURLToPath25(uri) : void 0;
158265
158436
  } catch {
158266
158437
  return void 0;
158267
158438
  }
@@ -158327,32 +158498,36 @@ var init_server = __esm({
158327
158498
  // src/native-decode.ts
158328
158499
  var native_decode_exports = {};
158329
158500
  __export(native_decode_exports, {
158501
+ NATIVE_TOKENS_DOCUMENT: () => NATIVE_TOKENS_DOCUMENT,
158502
+ defaultAndroidSdkDir: () => defaultAndroidSdkDir,
158330
158503
  detectAndroidNativeDecode: () => detectAndroidNativeDecode,
158331
158504
  detectNativeDecode: () => detectNativeDecode,
158505
+ markNativeSkipped: () => markNativeSkipped,
158332
158506
  mergeNativeDecode: () => mergeNativeDecode,
158333
158507
  nativeDecodeAndroidHarnessDir: () => nativeDecodeAndroidHarnessDir,
158334
158508
  nativeDecodePackageDir: () => nativeDecodePackageDir,
158335
158509
  nativeDecodePlatforms: () => nativeDecodePlatforms,
158336
158510
  nativeOracleShipped: () => nativeOracleShipped,
158337
158511
  parseNativeDecodeOutput: () => parseNativeDecodeOutput,
158512
+ parseNativeDecodeRun: () => parseNativeDecodeRun,
158338
158513
  runAndroidNativeDecode: () => runAndroidNativeDecode,
158339
158514
  runNativeDecode: () => runNativeDecode
158340
158515
  });
158341
158516
  import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
158342
- import { existsSync as existsSync66, mkdtempSync as mkdtempSync2, readFileSync as readFileSync80, rmSync as rmSync16, writeFileSync as writeFileSync28 } from "node:fs";
158343
- import { tmpdir as tmpdir3 } from "node:os";
158517
+ import { existsSync as existsSync67, mkdirSync as mkdirSync33, mkdtempSync as mkdtempSync2, readFileSync as readFileSync80, rmSync as rmSync16, writeFileSync as writeFileSync28 } from "node:fs";
158518
+ import { homedir as homedir9, tmpdir as tmpdir3 } from "node:os";
158344
158519
  import { join as join70 } from "node:path";
158345
- import { fileURLToPath as fileURLToPath25 } from "node:url";
158520
+ import { fileURLToPath as fileURLToPath26 } from "node:url";
158346
158521
  function nativeDecodePackageDir() {
158347
- return fileURLToPath25(new URL("../../../core/runtime/ios/HimalayaCore/", import.meta.url));
158522
+ return fileURLToPath26(new URL("../../../core/runtime/ios/HimalayaCore/", import.meta.url));
158348
158523
  }
158349
158524
  function nativeDecodeAndroidHarnessDir() {
158350
- return fileURLToPath25(new URL("../../../tools/wix-sdk-android-tests/", import.meta.url));
158525
+ return fileURLToPath26(new URL("../../../tools/wix-sdk-android-tests/", import.meta.url));
158351
158526
  }
158352
158527
  function nativeOracleShipped() {
158353
158528
  return {
158354
- ios: existsSync66(join70(nativeDecodePackageDir(), "Package.swift")),
158355
- android: existsSync66(join70(nativeDecodeAndroidHarnessDir(), "gradlew"))
158529
+ ios: existsSync67(join70(nativeDecodePackageDir(), "Package.swift")),
158530
+ android: existsSync67(join70(nativeDecodeAndroidHarnessDir(), "gradlew"))
158356
158531
  };
158357
158532
  }
158358
158533
  function detectNativeDecode(options = {}) {
@@ -158363,7 +158538,7 @@ function detectNativeDecode(options = {}) {
158363
158538
  return { platform: "ios", available: false, reason: `the iOS decoder oracle requires macOS (darwin); this host is ${hostPlatform}` };
158364
158539
  }
158365
158540
  if (!swiftAvailable) return { platform: "ios", available: false, reason: "swift is not on PATH" };
158366
- const packageAvailable = options.packageAvailable ?? existsSync66(join70(packageDir, "Package.swift"));
158541
+ const packageAvailable = options.packageAvailable ?? existsSync67(join70(packageDir, "Package.swift"));
158367
158542
  if (!packageAvailable) {
158368
158543
  return {
158369
158544
  platform: "ios",
@@ -158381,10 +158556,15 @@ function localPropertiesSdk(harnessDir) {
158381
158556
  return null;
158382
158557
  }
158383
158558
  }
158559
+ function defaultAndroidSdkDir(hostPlatform, home) {
158560
+ if (hostPlatform === "darwin") return join70(home, "Library", "Android", "sdk");
158561
+ if (hostPlatform === "linux") return join70(home, "Android", "Sdk");
158562
+ return null;
158563
+ }
158384
158564
  function detectAndroidNativeDecode(options = {}) {
158385
158565
  const harnessDir = options.harnessDir ?? nativeDecodeAndroidHarnessDir();
158386
158566
  const gradlew = join70(harnessDir, "gradlew");
158387
- const gradlewAvailable = options.gradlewAvailable ?? existsSync66(gradlew);
158567
+ const gradlewAvailable = options.gradlewAvailable ?? existsSync67(gradlew);
158388
158568
  if (!gradlewAvailable) {
158389
158569
  return {
158390
158570
  platform: "android",
@@ -158392,17 +158572,23 @@ function detectAndroidNativeDecode(options = {}) {
158392
158572
  reason: "the in-repo Android Gradle harness is unavailable (off-repo installs do not ship the decoder oracle)"
158393
158573
  };
158394
158574
  }
158395
- const androidHome = options.androidHome ?? process.env.ANDROID_HOME ?? "";
158396
- const sdk = androidHome.trim() || (options.localPropertiesSdk !== void 0 ? options.localPropertiesSdk : localPropertiesSdk(harnessDir));
158397
- const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync66(sdk));
158398
- if (!sdkAvailable) {
158575
+ const exists = typeof options.sdkAvailable === "function" ? options.sdkAvailable : typeof options.sdkAvailable === "boolean" ? /* @__PURE__ */ ((answer) => () => answer)(options.sdkAvailable) : existsSync67;
158576
+ const defaultDir = defaultAndroidSdkDir(options.hostPlatform ?? process.platform, options.homeDir ?? homedir9());
158577
+ const candidates = [
158578
+ options.androidHome ?? process.env.ANDROID_HOME,
158579
+ options.androidSdkRoot ?? process.env.ANDROID_SDK_ROOT,
158580
+ options.localPropertiesSdk !== void 0 ? options.localPropertiesSdk : localPropertiesSdk(harnessDir),
158581
+ defaultDir
158582
+ ].map((candidate) => candidate?.trim() ?? "").filter((candidate) => candidate.length > 0);
158583
+ const sdkDir = candidates.find((candidate) => exists(candidate));
158584
+ if (sdkDir === void 0) {
158399
158585
  return {
158400
158586
  platform: "android",
158401
158587
  available: false,
158402
- reason: "the Android SDK is unavailable (set ANDROID_HOME or sdk.dir in tools/wix-sdk-android-tests/local.properties)"
158588
+ reason: `the Android SDK is unavailable (set ANDROID_HOME or ANDROID_SDK_ROOT, sdk.dir in tools/wix-sdk-android-tests/local.properties, or install it at the default path${defaultDir ? ` ${defaultDir}` : ""})`
158403
158589
  };
158404
158590
  }
158405
- return { platform: "android", available: true, harnessDir, gradlew };
158591
+ return { platform: "android", available: true, harnessDir, gradlew, sdkDir };
158406
158592
  }
158407
158593
  function nativeDecodePlatforms(value) {
158408
158594
  if (value === true) return ["ios", "android"];
@@ -158436,10 +158622,14 @@ function parseError(value, line, platform) {
158436
158622
  };
158437
158623
  }
158438
158624
  function parseNativeDecodeOutput(stdout, expectedScreenIds, platform = "ios") {
158625
+ return parseNativeDecodeRun(stdout, expectedScreenIds, platform, false).verdicts;
158626
+ }
158627
+ function parseNativeDecodeRun(stdout, expectedScreenIds, platform, expectTokens) {
158439
158628
  const platformLabel = platform === "ios" ? "iOS" : "Android";
158440
158629
  const expected = new Set(expectedScreenIds);
158441
158630
  if (expected.size !== expectedScreenIds.length) throw new Error("native decode input contains duplicate screen ids");
158442
158631
  const verdicts = [];
158632
+ let tokens2;
158443
158633
  const seen = /* @__PURE__ */ new Set();
158444
158634
  const lines = stdout.split(/\r?\n/).filter((line) => line.trim() !== "");
158445
158635
  for (let index = 0; index < lines.length; index++) {
@@ -158449,6 +158639,19 @@ function parseNativeDecodeOutput(stdout, expectedScreenIds, platform = "ios") {
158449
158639
  } catch (error) {
158450
158640
  throw new Error(`malformed NDJSON from ${platformLabel} decoder oracle at line ${index + 1}: ${error.message}`);
158451
158641
  }
158642
+ if (record(value) && "document" in value) {
158643
+ if (value.document !== "tokens" || value.platform !== platform || typeof value.ok !== "boolean" || !Array.isArray(value.errors)) {
158644
+ throw new Error(`malformed NDJSON from ${platformLabel} decoder oracle at line ${index + 1}: document verdict must be { document:"tokens", platform:"${platform}", ok, errors }`);
158645
+ }
158646
+ rejectUnknownKeys(value, DOCUMENT_VERDICT_KEYS, "document verdict", index + 1, platformLabel);
158647
+ if (!expectTokens) throw new Error(`${platformLabel} decoder oracle returned a tokens verdict it was not asked for`);
158648
+ if (tokens2) throw new Error(`${platformLabel} decoder oracle returned a duplicate tokens verdict`);
158649
+ const errors2 = value.errors.map((item) => parseError(item, index + 1, platform));
158650
+ if (value.ok && errors2.length) throw new Error(`malformed NDJSON from ${platformLabel} decoder oracle at line ${index + 1}: ok=true must have no errors`);
158651
+ if (!value.ok && !errors2.length) throw new Error(`malformed NDJSON from ${platformLabel} decoder oracle at line ${index + 1}: ok=false must have at least one error`);
158652
+ tokens2 = { platform, ok: value.ok, errors: errors2 };
158653
+ continue;
158654
+ }
158452
158655
  if (!record(value) || typeof value.screenId !== "string" || value.platform !== platform || typeof value.ok !== "boolean" || !Array.isArray(value.errors)) {
158453
158656
  throw new Error(`malformed NDJSON from ${platformLabel} decoder oracle at line ${index + 1}: verdict must be { screenId, platform:"${platform}", ok, errors }`);
158454
158657
  }
@@ -158463,18 +158666,27 @@ function parseNativeDecodeOutput(stdout, expectedScreenIds, platform = "ios") {
158463
158666
  }
158464
158667
  const missing = expectedScreenIds.filter((screenId) => !seen.has(screenId));
158465
158668
  if (missing.length) throw new Error(`${platformLabel} decoder oracle output is missing verdict${missing.length === 1 ? "" : "s"} for: ${missing.join(", ")}`);
158466
- return verdicts;
158669
+ if (expectTokens && !tokens2) throw new Error(`${platformLabel} decoder oracle output is missing the tokens verdict`);
158670
+ return tokens2 ? { verdicts, tokens: tokens2 } : { verdicts };
158671
+ }
158672
+ function writeDecodeInputs(descriptorDir, descriptors, tokensJson) {
158673
+ for (const descriptor of descriptors) {
158674
+ if (typeof descriptor.descriptorJson !== "string") {
158675
+ throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
158676
+ }
158677
+ writeFileSync28(join70(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
158678
+ }
158679
+ if (tokensJson === void 0) return void 0;
158680
+ mkdirSync33(join70(descriptorDir, "tokens"));
158681
+ const tokensPath = join70(descriptorDir, "tokens", NATIVE_TOKENS_DOCUMENT);
158682
+ writeFileSync28(tokensPath, tokensJson);
158683
+ return tokensPath;
158467
158684
  }
158468
158685
  function runNativeDecode(options) {
158469
158686
  const descriptorDir = mkdtempSync2(join70(tmpdir3(), "himi-native-decode-"));
158470
158687
  const startedAt = Date.now();
158471
158688
  try {
158472
- for (const descriptor of options.descriptors) {
158473
- if (typeof descriptor.descriptorJson !== "string") {
158474
- throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
158475
- }
158476
- writeFileSync28(join70(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
158477
- }
158689
+ const tokensPath = writeDecodeInputs(descriptorDir, options.descriptors, options.tokensJson);
158478
158690
  options.progress?.("building cached Swift oracle");
158479
158691
  execFileSync5("swift", ["build", "--package-path", options.packageDir, "--product", "himi-decode-oracle"], {
158480
158692
  stdio: ["ignore", "ignore", "pipe"],
@@ -158485,13 +158697,13 @@ function runNativeDecode(options) {
158485
158697
  encoding: "utf8"
158486
158698
  }).trim();
158487
158699
  options.progress?.(`running real Swift decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
158488
- const stdout = execFileSync5(join70(binPath, "himi-decode-oracle"), ["--dir", descriptorDir], {
158700
+ const stdout = execFileSync5(join70(binPath, "himi-decode-oracle"), ["--dir", descriptorDir, ...tokensPath ? ["--tokens", tokensPath] : []], {
158489
158701
  stdio: ["ignore", "pipe", "pipe"],
158490
158702
  encoding: "utf8"
158491
158703
  });
158492
158704
  return {
158493
158705
  platform: "ios",
158494
- verdicts: parseNativeDecodeOutput(stdout, options.descriptors.map((descriptor) => descriptor.screenId)),
158706
+ ...parseNativeDecodeRun(stdout, options.descriptors.map((descriptor) => descriptor.screenId), "ios", tokensPath !== void 0),
158495
158707
  wallMs: Date.now() - startedAt
158496
158708
  };
158497
158709
  } catch (error) {
@@ -158507,12 +158719,7 @@ function runAndroidNativeDecode(options) {
158507
158719
  const outputPath = join70(descriptorDir, "verdicts.ndjson");
158508
158720
  const startedAt = Date.now();
158509
158721
  try {
158510
- for (const descriptor of options.descriptors) {
158511
- if (typeof descriptor.descriptorJson !== "string") {
158512
- throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
158513
- }
158514
- writeFileSync28(join70(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
158515
- }
158722
+ const tokensPath = writeDecodeInputs(descriptorDir, options.descriptors, options.tokensJson);
158516
158723
  options.progress?.(`running real Kotlin decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
158517
158724
  execFileSync5(options.gradlew, [
158518
158725
  "-p",
@@ -158521,15 +158728,17 @@ function runAndroidNativeDecode(options) {
158521
158728
  "--tests",
158522
158729
  "io.himalaya.core.NativeDecodeOracleRunner",
158523
158730
  `-PhimiDecodeDir=${descriptorDir}`,
158524
- `-PhimiDecodeOut=${outputPath}`
158731
+ `-PhimiDecodeOut=${outputPath}`,
158732
+ ...tokensPath ? [`-PhimiDecodeTokens=${tokensPath}`] : []
158525
158733
  ], {
158526
158734
  stdio: ["ignore", "ignore", "pipe"],
158527
- encoding: "utf8"
158735
+ encoding: "utf8",
158736
+ ...options.sdkDir ? { env: { ...process.env, ANDROID_HOME: options.sdkDir, ANDROID_SDK_ROOT: options.sdkDir } } : {}
158528
158737
  });
158529
158738
  const stdout = readFileSync80(outputPath, "utf8");
158530
158739
  return {
158531
158740
  platform: "android",
158532
- verdicts: parseNativeDecodeOutput(stdout, options.descriptors.map((descriptor) => descriptor.screenId), "android"),
158741
+ ...parseNativeDecodeRun(stdout, options.descriptors.map((descriptor) => descriptor.screenId), "android", tokensPath !== void 0),
158533
158742
  wallMs: Date.now() - startedAt
158534
158743
  };
158535
158744
  } catch (error) {
@@ -158540,6 +158749,17 @@ function runAndroidNativeDecode(options) {
158540
158749
  rmSync16(descriptorDir, { recursive: true, force: true });
158541
158750
  }
158542
158751
  }
158752
+ function markNativeSkipped(report3, skipped) {
158753
+ return {
158754
+ ...report3,
158755
+ nativeDecode: {
158756
+ ...report3.nativeDecode,
158757
+ [skipped.platform]: { unavailable: true, reason: skipped.reason },
158758
+ wallMs: report3.nativeDecode?.wallMs ?? 0
158759
+ },
158760
+ skippedPlatforms: [...report3.skippedPlatforms ?? [], { platform: skipped.platform, reason: skipped.reason }]
158761
+ };
158762
+ }
158543
158763
  function fieldAt(path2) {
158544
158764
  if (path2 === null) return void 0;
158545
158765
  return path2.match(/\.([^.[\]]+)$/)?.[1];
@@ -158557,8 +158777,20 @@ function mergeNativeDecode(report3, run2) {
158557
158777
  ...error.actual ? { actual: error.actual } : {},
158558
158778
  hint: `This descriptor ships as a full-screen \u201CCouldn't load\u201D; fix the typed field and rerun \`himi test --native ${run2.platform}\`.`
158559
158779
  })));
158780
+ const tokenFailures = (run2.tokens?.errors ?? []).map((error) => ({
158781
+ screen: NATIVE_TOKENS_DOCUMENT,
158782
+ trigger: "boot",
158783
+ invariant: "native-decode-failed",
158784
+ severity: "error",
158785
+ message: `${platformLabel} ${error.kind} decoding ${NATIVE_TOKENS_DOCUMENT}: ${error.message}${error.expected ? ` (expected ${error.expected})` : ""}`,
158786
+ ...error.path ? { at: error.path } : {},
158787
+ ...fieldAt(error.path) ? { field: fieldAt(error.path) } : {},
158788
+ ...error.actual ? { actual: error.actual } : {},
158789
+ hint: `${platformLabel} decodes tokens.json in one strict pass, so this one value drops the WHOLE theme on device (iOS shows \u201CTheme unavailable\u201D; Android falls back to its default palette and fonts). Typography \`size\`, spacing, radius and motion \`duration\` (milliseconds: 0.3 \u2192 300) are integers. Fix it and rerun \`himi test --native ${run2.platform}\`.`
158790
+ }));
158791
+ nativeFailures.push(...tokenFailures);
158560
158792
  const failures = [...report3.failures, ...nativeFailures];
158561
- const failedScreens = new Set(failures.map((finding) => finding.screen));
158793
+ const failedScreens = new Set(failures.map((finding) => finding.screen).filter((screen) => screen !== NATIVE_TOKENS_DOCUMENT));
158562
158794
  return {
158563
158795
  ...report3,
158564
158796
  ok: report3.ok && nativeFailures.length === 0,
@@ -158567,17 +158799,23 @@ function mergeNativeDecode(report3, run2) {
158567
158799
  screens: { ...report3.screens, clean: report3.screens.total - failedScreens.size, failed: failedScreens.size },
158568
158800
  nativeDecode: {
158569
158801
  ...report3.nativeDecode,
158570
- [run2.platform]: { checked: run2.verdicts.length, failed: run2.verdicts.filter((verdict) => !verdict.ok).length },
158802
+ [run2.platform]: {
158803
+ checked: run2.verdicts.length,
158804
+ failed: run2.verdicts.filter((verdict) => !verdict.ok).length,
158805
+ ...run2.tokens ? { tokens: run2.tokens.ok ? "ok" : "rejected" } : {}
158806
+ },
158571
158807
  wallMs: (report3.nativeDecode?.wallMs ?? 0) + run2.wallMs
158572
158808
  }
158573
158809
  };
158574
158810
  }
158575
- var KINDS, record, VERDICT_KEYS, ERROR_KEYS;
158811
+ var NATIVE_TOKENS_DOCUMENT, KINDS, record, VERDICT_KEYS, DOCUMENT_VERDICT_KEYS, ERROR_KEYS;
158576
158812
  var init_native_decode = __esm({
158577
158813
  "src/native-decode.ts"() {
158814
+ NATIVE_TOKENS_DOCUMENT = "tokens.json";
158578
158815
  KINDS = /* @__PURE__ */ new Set(["typeMismatch", "valueNotFound", "keyNotFound", "dataCorrupted"]);
158579
158816
  record = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
158580
158817
  VERDICT_KEYS = /* @__PURE__ */ new Set(["screenId", "platform", "ok", "errors"]);
158818
+ DOCUMENT_VERDICT_KEYS = /* @__PURE__ */ new Set(["document", "platform", "ok", "errors"]);
158581
158819
  ERROR_KEYS = /* @__PURE__ */ new Set(["kind", "path", "message", "expected", "actual"]);
158582
158820
  }
158583
158821
  });
@@ -158596,7 +158834,7 @@ __export(browser_authoring_exports, {
158596
158834
  });
158597
158835
  import { createServer as createServer5 } from "node:http";
158598
158836
  import { createHash as createHash36, randomBytes as randomBytes5 } from "node:crypto";
158599
- import { existsSync as existsSync67, readdirSync as readdirSync32, readFileSync as readFileSync81, realpathSync as realpathSync11, statSync as statSync19 } from "node:fs";
158837
+ import { existsSync as existsSync68, readdirSync as readdirSync32, readFileSync as readFileSync81, realpathSync as realpathSync11, statSync as statSync19 } from "node:fs";
158600
158838
  import { join as join71, posix as posix3, relative as relative14, sep as sep18 } from "node:path";
158601
158839
  function humanMs(ms2) {
158602
158840
  return ms2 < 1e3 ? `${ms2}ms` : `${Math.round(ms2 / 1e3)}s`;
@@ -158619,7 +158857,7 @@ function collectWorkerSources(tier5SrcDir, bundleName) {
158619
158857
  }
158620
158858
  }
158621
158859
  };
158622
- if (!existsSync67(root)) return null;
158860
+ if (!existsSync68(root)) return null;
158623
158861
  walk2(root, `/tier5-src/${bundleName}`);
158624
158862
  const entry = [`/tier5-src/${bundleName}/index.ts`, `/tier5-src/${bundleName}/index.js`].find((p2) => p2 in files);
158625
158863
  if (!entry) return null;
@@ -158646,7 +158884,7 @@ function collectRelativeSiblings(files, tier5SrcDir) {
158646
158884
  join71(onDisk, "index.js")
158647
158885
  ];
158648
158886
  for (const abs of candidates) {
158649
- if (!existsSync67(abs) || statSync19(abs).isDirectory()) continue;
158887
+ if (!existsSync68(abs) || statSync19(abs).isDirectory()) continue;
158650
158888
  const key3 = `/tier5-src/${relative14(tier5SrcDir, abs).split(sep18).join(posix3.sep)}`;
158651
158889
  if (key3 in files) break;
158652
158890
  files[key3] = readFileSync81(abs, "utf8");
@@ -158856,7 +159094,7 @@ __export(coverage_exports, {
158856
159094
  suppressedNativeKeys: () => suppressedNativeKeys,
158857
159095
  trendAndStore: () => trendAndStore
158858
159096
  });
158859
- import { existsSync as existsSync68, mkdirSync as mkdirSync33, readFileSync as readFileSync82, writeFileSync as writeFileSync29 } from "node:fs";
159097
+ import { existsSync as existsSync69, mkdirSync as mkdirSync34, readFileSync as readFileSync82, writeFileSync as writeFileSync29 } from "node:fs";
158860
159098
  import { dirname as dirname38, join as join72 } from "node:path";
158861
159099
  function suppressedNativeKeys(oracle) {
158862
159100
  return [...oracle.ios ? [] : ["native-decode|ios"], ...oracle.android ? [] : ["native-decode|android"]];
@@ -159040,7 +159278,7 @@ function trendAndStore(dir, entries, suppressed) {
159040
159278
  const p2 = join72(dir, LEDGER_FILE);
159041
159279
  let previous = null;
159042
159280
  try {
159043
- if (existsSync68(p2)) {
159281
+ if (existsSync69(p2)) {
159044
159282
  const parsed = JSON.parse(readFileSync82(p2, "utf8"));
159045
159283
  if (Array.isArray(parsed.keys)) previous = parsed.keys.filter((k2) => typeof k2 === "string");
159046
159284
  }
@@ -159049,7 +159287,7 @@ function trendAndStore(dir, entries, suppressed) {
159049
159287
  const current = entries.map((e2) => e2.key);
159050
159288
  const stored = [.../* @__PURE__ */ new Set([...current, ...(previous ?? []).filter((key3) => (suppressed ?? []).includes(key3))])];
159051
159289
  try {
159052
- mkdirSync33(dirname38(p2), { recursive: true });
159290
+ mkdirSync34(dirname38(p2), { recursive: true });
159053
159291
  writeFileSync29(p2, JSON.stringify({ keys: stored, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
159054
159292
  } catch {
159055
159293
  return null;
@@ -159083,7 +159321,7 @@ function diffAndStoreObservations(dir, current) {
159083
159321
  const p2 = join72(dir, OBS_FILE);
159084
159322
  let previous = null;
159085
159323
  try {
159086
- if (existsSync68(p2)) {
159324
+ if (existsSync69(p2)) {
159087
159325
  const parsed = JSON.parse(readFileSync82(p2, "utf8"));
159088
159326
  if (parsed.screens && typeof parsed.screens === "object" && !Array.isArray(parsed.screens) && Object.values(parsed.screens).every(
159089
159327
  (v2) => Array.isArray(v2) && v2.every((l2) => typeof l2 === "string")
@@ -159094,7 +159332,7 @@ function diffAndStoreObservations(dir, current) {
159094
159332
  } catch {
159095
159333
  }
159096
159334
  try {
159097
- mkdirSync33(dirname38(p2), { recursive: true });
159335
+ mkdirSync34(dirname38(p2), { recursive: true });
159098
159336
  writeFileSync29(p2, JSON.stringify({ screens: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
159099
159337
  } catch {
159100
159338
  return null;
@@ -159145,11 +159383,11 @@ __export(design_kits_exports, {
159145
159383
  kitsDir: () => kitsDir,
159146
159384
  listKits: () => listKits2
159147
159385
  });
159148
- import { existsSync as existsSync69, readFileSync as readFileSync83, readdirSync as readdirSync33 } from "node:fs";
159386
+ import { existsSync as existsSync70, readFileSync as readFileSync83, readdirSync as readdirSync33 } from "node:fs";
159149
159387
  import { join as join73, basename as basename16 } from "node:path";
159150
- import { fileURLToPath as fileURLToPath26 } from "node:url";
159388
+ import { fileURLToPath as fileURLToPath27 } from "node:url";
159151
159389
  function kitsDir() {
159152
- return KIT_DIR_CANDIDATES.find((p2) => existsSync69(p2));
159390
+ return KIT_DIR_CANDIDATES.find((p2) => existsSync70(p2));
159153
159391
  }
159154
159392
  function listKits2() {
159155
159393
  const dir = kitsDir();
@@ -159197,9 +159435,9 @@ var init_design_kits = __esm({
159197
159435
  "src/design-kits.ts"() {
159198
159436
  KIT_DIR_CANDIDATES = [
159199
159437
  // in-repo: tools/himi-cli/src/design-kits.ts → <repo>/stdlib/design-kits/
159200
- join73(fileURLToPath26(new URL("../../..", import.meta.url)), "stdlib", "design-kits"),
159438
+ join73(fileURLToPath27(new URL("../../..", import.meta.url)), "stdlib", "design-kits"),
159201
159439
  // published CLI: <pkg>/dist/cli.mjs → <pkg>/stdlib/design-kits/
159202
- join73(fileURLToPath26(new URL("..", import.meta.url)), "stdlib", "design-kits")
159440
+ join73(fileURLToPath27(new URL("..", import.meta.url)), "stdlib", "design-kits")
159203
159441
  ];
159204
159442
  }
159205
159443
  });
@@ -161275,32 +161513,32 @@ var init_preview_assets_generated = __esm({
161275
161513
  "../../packages/serve/src/preview-assets.generated.ts"() {
161276
161514
  init_preview_assets_format();
161277
161515
  PREVIEW_ASSET_MANIFEST = [
161278
- { key: "assets/DashboardHost-3-2Jf3cl.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 2916, sha256: "16067cee02695e0e78e872b92dd41d85dd30c9c29d04f45db43126c4452b0156" },
161279
- { key: "assets/DevDrawer-CiwSZJ0n.js", contentType: "application/javascript; charset=utf-8", offset: 2924, length: 16744, sha256: "a570bdc5f979ddd8b5c677886d980f41ff8d7c9e54a0461487cd1b9e5c83ad66" },
161280
- { key: "assets/IdiomCompare-CJAnEFoY.js", contentType: "application/javascript; charset=utf-8", offset: 19668, length: 1892, sha256: "4ede78710504fa2f22e7e4dc75f95c52f64b0d7c8defb53333ce4ed32ae678f6" },
161281
- { key: "assets/LightboxViewer-BOY9iVs-.js", contentType: "application/javascript; charset=utf-8", offset: 21560, length: 8132, sha256: "0d11ab35256faae44aed69854dc3b5cf42bdcfefaccb6cc833ecb401ee5c6e03" },
161282
- { key: "assets/PhonePreviewControl-BqaJPdhq.js", contentType: "application/javascript; charset=utf-8", offset: 29692, length: 37729, sha256: "2373e4117a568f4788edec591429b6c81291b572caf11d511e1d17f10701da5a" },
161283
- { key: "assets/SchemeCompare-j4m0nu1j.js", contentType: "application/javascript; charset=utf-8", offset: 67421, length: 1824, sha256: "4e41c913297e35eda4816f5646d678f83eeb974944378f2627a31ad97c5829df" },
161284
- { key: "assets/index-Cak7Oz8v.js", contentType: "application/javascript; charset=utf-8", offset: 69245, length: 1266847, sha256: "015168656f2d2f8a22589c77e2f46cc917e7fc2dfa96c8f2f498acb0e4778946" },
161285
- { key: "assets/pdf-BdBVqwzN.js", contentType: "application/javascript; charset=utf-8", offset: 1336092, length: 488199, sha256: "cfdedd9cca30899c52b4d5d14612b20ead4699afef16253f3d8a1b4995cffff0" },
161286
- { key: "assets/pdf.worker.min-BQa_JDET.js", contentType: "application/javascript; charset=utf-8", offset: 1824291, length: 73, sha256: "41bcfda4f3c8c0a81c785ea87c69afc8e7d0ed8c333324aee94c273d881bb6aa" },
161287
- { key: "assets/pdf.worker.min-BmVo14Nb.mjs", contentType: "application/javascript; charset=utf-8", offset: 1824364, length: 1317034, sha256: "a33cfe728c584fdba4fcc1fd54bcdc2f9f2f13889ddbb5b2bd1d0f8cbe49b84e" },
161288
- { key: "assets/pdfDocument-CWUvZXa-.js", contentType: "application/javascript; charset=utf-8", offset: 3141398, length: 2868, sha256: "d06defc34d8fb99209b44a1f16397d33c2fa0f36c72a76692261ee2900304f9b" },
161289
- { key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset: 3144266, length: 4610, sha256: "994062dd7af4186a739de55dd9e151c63b6301f8e2cbafc608d35c2e87da0cd2" },
161290
- { key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset: 3148876, length: 488584, sha256: "d7598e12c5dbef095ff8272cfc55da0250bd07fbdecbac8a530b9b277872a134" },
161291
- { key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 3637460, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
161292
- { key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 3728384, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
161293
- { key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 3819368, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
161294
- { key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 3910348, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
161295
- { key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 4001220, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
161296
- { key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 4092200, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
161297
- { key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 4200836, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
161298
- { key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 4309920, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
161299
- { key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 4418968, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
161300
- { key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 4526668, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
161301
- { key: "himi-sw.js", contentType: "application/javascript; charset=utf-8", offset: 4614776, length: 6748, sha256: "4a92459977d7cefa1a6a7e020c3a63509737f083b3f2773557c1a5771665811a" },
161302
- { key: "index.html", contentType: "text/html; charset=utf-8", offset: 4621524, length: 4947, sha256: "3b2cf7b22b8a77eaabfb1634073d256c7aa367b91d0cc70081bea99b12b77fb0" },
161303
- { key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 4626471, length: 17786, sha256: "084107ca997628c248f1b0ba3a7494744850df39fad813546ab8bdb82a6058da" }
161516
+ { key: "assets/DashboardHost-CWbeef06.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 2916, sha256: "9ab72647e78bee902e76c4672f3d22b18d9b7a79892e0e64ae80ffb574417911" },
161517
+ { key: "assets/DevDrawer-mM0I8ALw.js", contentType: "application/javascript; charset=utf-8", offset: 2924, length: 16744, sha256: "9bbb22f0ee24b6782c4645da75788028c942122748f0149d00e9039cdd09f0b1" },
161518
+ { key: "assets/IdiomCompare-SDHU6iNa.js", contentType: "application/javascript; charset=utf-8", offset: 19668, length: 1892, sha256: "2af535cb7bb80d6f90d99bbb67470e4f9754949b62e08f4767a977a3414ae43e" },
161519
+ { key: "assets/LightboxViewer-YV8gCISo.js", contentType: "application/javascript; charset=utf-8", offset: 21560, length: 8132, sha256: "e3c873007b6790042640966c3fb0d19f16d2f0ca4c41276838d38e90c852391a" },
161520
+ { key: "assets/PhonePreviewControl-Dl_3aZaI.js", contentType: "application/javascript; charset=utf-8", offset: 29692, length: 37729, sha256: "f8d15085d2b83522584fd3a30bc5bead6d68c885e2987e7df12035c45d1aa003" },
161521
+ { key: "assets/SchemeCompare-VEnYs5jY.js", contentType: "application/javascript; charset=utf-8", offset: 67421, length: 1824, sha256: "9f51da5008d043106847efb01ab675ae9c4ed58e6745cba03b1fd0b5f173a520" },
161522
+ { key: "assets/index-zKquXoS4.js", contentType: "application/javascript; charset=utf-8", offset: 69245, length: 1268324, sha256: "4d6fe8fe1939fbc4a50b528233ff482afc6f615a0df92b54847386d0557b837a" },
161523
+ { key: "assets/pdf-ipblMaD0.js", contentType: "application/javascript; charset=utf-8", offset: 1337569, length: 488199, sha256: "f103cd80a3f9a971e1be6162886350314c28bd42c1cb998210147e4a5a23a947" },
161524
+ { key: "assets/pdf.worker.min-BQa_JDET.js", contentType: "application/javascript; charset=utf-8", offset: 1825768, length: 73, sha256: "41bcfda4f3c8c0a81c785ea87c69afc8e7d0ed8c333324aee94c273d881bb6aa" },
161525
+ { key: "assets/pdf.worker.min-BmVo14Nb.mjs", contentType: "application/javascript; charset=utf-8", offset: 1825841, length: 1317034, sha256: "a33cfe728c584fdba4fcc1fd54bcdc2f9f2f13889ddbb5b2bd1d0f8cbe49b84e" },
161526
+ { key: "assets/pdfDocument-BLnEEkur.js", contentType: "application/javascript; charset=utf-8", offset: 3142875, length: 2868, sha256: "3913f6a2cc3e3eda95617b848a6240dfd132d2da9629fc429b144b722401e2f0" },
161527
+ { key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset: 3145743, length: 4610, sha256: "994062dd7af4186a739de55dd9e151c63b6301f8e2cbafc608d35c2e87da0cd2" },
161528
+ { key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset: 3150353, length: 488584, sha256: "d7598e12c5dbef095ff8272cfc55da0250bd07fbdecbac8a530b9b277872a134" },
161529
+ { key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 3638937, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
161530
+ { key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 3729861, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
161531
+ { key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 3820845, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
161532
+ { key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 3911825, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
161533
+ { key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 4002697, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
161534
+ { key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 4093677, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
161535
+ { key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 4202313, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
161536
+ { key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 4311397, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
161537
+ { key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 4420445, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
161538
+ { key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 4528145, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
161539
+ { key: "himi-sw.js", contentType: "application/javascript; charset=utf-8", offset: 4616253, length: 6748, sha256: "4a92459977d7cefa1a6a7e020c3a63509737f083b3f2773557c1a5771665811a" },
161540
+ { key: "index.html", contentType: "text/html; charset=utf-8", offset: 4623001, length: 4947, sha256: "ac12b463d6c2a4195ff7f6fb911b79c7e14de48488493bf6480b660866f833f9" },
161541
+ { key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 4627948, length: 17786, sha256: "084107ca997628c248f1b0ba3a7494744850df39fad813546ab8bdb82a6058da" }
161304
161542
  ];
161305
161543
  }
161306
161544
  });
@@ -161309,6 +161547,7 @@ var init_preview_assets_generated = __esm({
161309
161547
  var run_exports = {};
161310
161548
  __export(run_exports, {
161311
161549
  NO_SPA_MESSAGE: () => NO_SPA_MESSAGE,
161550
+ RUN_CONTENT_BUILD: () => RUN_CONTENT_BUILD,
161312
161551
  lanAddress: () => lanAddress,
161313
161552
  lanFlagConflict: () => lanFlagConflict,
161314
161553
  loadPreviewAssets: () => loadPreviewAssets,
@@ -161318,10 +161557,10 @@ __export(run_exports, {
161318
161557
  runPackage: () => runPackage,
161319
161558
  withoutProdServe: () => withoutProdServe
161320
161559
  });
161321
- import { cpSync as cpSync2, existsSync as existsSync70, mkdirSync as mkdirSync34, mkdtempSync as mkdtempSync3, readFileSync as readFileSync85, rmSync as rmSync17, statSync as statSync20 } from "node:fs";
161560
+ import { cpSync as cpSync2, existsSync as existsSync71, mkdirSync as mkdirSync35, mkdtempSync as mkdtempSync3, readFileSync as readFileSync85, rmSync as rmSync17, statSync as statSync20 } from "node:fs";
161322
161561
  import { networkInterfaces as osNetworkInterfaces, tmpdir as tmpdir4 } from "node:os";
161323
161562
  import { dirname as dirname39, join as join74 } from "node:path";
161324
- import { fileURLToPath as fileURLToPath27 } from "node:url";
161563
+ import { fileURLToPath as fileURLToPath28 } from "node:url";
161325
161564
  function makePackageRunHandler(opts) {
161326
161565
  const store = new FileReleaseStore(opts.releaseRoot);
161327
161566
  const webwixDirect = async () => {
@@ -161348,9 +161587,9 @@ async function fetchBytes(url) {
161348
161587
  }
161349
161588
  async function resolvePackage(source, workDir) {
161350
161589
  const isUrl2 = /^https?:\/\//i.test(source);
161351
- if (!isUrl2 && existsSync70(source) && statSync20(source).isDirectory()) {
161590
+ if (!isUrl2 && existsSync71(source) && statSync20(source).isDirectory()) {
161352
161591
  const appDirManifest = join74(source, "release-manifest.json");
161353
- if (existsSync70(appDirManifest)) {
161592
+ if (existsSync71(appDirManifest)) {
161354
161593
  const opened2 = openPackageDir(source);
161355
161594
  if (!opened2.validation.ok) {
161356
161595
  throw new Error(`package is not valid:
@@ -161362,7 +161601,7 @@ async function resolvePackage(source, workDir) {
161362
161601
  const root2 = workDir ?? mkdtempSync3(join74(tmpdir4(), "himi-run-"));
161363
161602
  const target = join74(root2, app2);
161364
161603
  if (join74(source) !== target) {
161365
- mkdirSync34(root2, { recursive: true });
161604
+ mkdirSync35(root2, { recursive: true });
161366
161605
  rmSync17(target, { recursive: true, force: true });
161367
161606
  cpSync2(source, target, { recursive: true });
161368
161607
  }
@@ -161400,7 +161639,7 @@ async function resolvePackage(source, workDir) {
161400
161639
  async function loadPreviewAssets() {
161401
161640
  try {
161402
161641
  const mod = await Promise.resolve().then(() => (init_preview_assets_generated(), preview_assets_generated_exports));
161403
- const here = dirname39(fileURLToPath27(import.meta.url));
161642
+ const here = dirname39(fileURLToPath28(import.meta.url));
161404
161643
  const candidates = [
161405
161644
  join74(here, "preview-assets.generated.bin"),
161406
161645
  // published: copied next to the bundled CLI
@@ -161408,7 +161647,7 @@ async function loadPreviewAssets() {
161408
161647
  // in-repo checkout
161409
161648
  ];
161410
161649
  for (const path2 of candidates) {
161411
- if (!existsSync70(path2)) continue;
161650
+ if (!existsSync71(path2)) continue;
161412
161651
  const blob = readFileSync85(path2);
161413
161652
  return mod.assemblePreviewAssetsFromBlob(new Uint8Array(blob.buffer, blob.byteOffset, blob.byteLength));
161414
161653
  }
@@ -161521,7 +161760,7 @@ async function runPackage(source, opts = {}) {
161521
161760
  }
161522
161761
  };
161523
161762
  }
161524
- var NO_SPA_MESSAGE, UNREACHABLE_IFACE, LIKELY_LAN_IFACE;
161763
+ var RUN_CONTENT_BUILD, NO_SPA_MESSAGE, UNREACHABLE_IFACE, LIKELY_LAN_IFACE;
161525
161764
  var init_run = __esm({
161526
161765
  "src/run.ts"() {
161527
161766
  init_open_url();
@@ -161532,6 +161771,7 @@ var init_run = __esm({
161532
161771
  init_pack();
161533
161772
  init_himi_package();
161534
161773
  init_himi_package();
161774
+ RUN_CONTENT_BUILD = { keepDevOnlyAppConfig: true };
161535
161775
  NO_SPA_MESSAGE = "the web-host SPA is not embedded in this build \u2014 run `node packages/serve/scripts/embed-preview-assets.mjs` (in a monorepo checkout), or pass --spa <url> to use a hosted preview host instead";
161536
161776
  UNREACHABLE_IFACE = /^(utun|tun|tap|ppp|ipsec|wg|gif|stf|bridge|vmnet|vboxnet|virbr|docker|br-|veth|awdl|llw|anpi|tailscale|zt|zerotier|nordlynx)|vpn/i;
161537
161777
  LIKELY_LAN_IFACE = /^(en|eth|wlan|wl|wifi)/i;
@@ -161546,15 +161786,15 @@ __export(run_browser_exports, {
161546
161786
  runInBrowser: () => runInBrowser
161547
161787
  });
161548
161788
  import { createServer as createServer7 } from "node:http";
161549
- import { existsSync as existsSync71, readFileSync as readFileSync86 } from "node:fs";
161789
+ import { existsSync as existsSync72, readFileSync as readFileSync86 } from "node:fs";
161550
161790
  import { spawnSync as spawnSync3 } from "node:child_process";
161551
161791
  import { dirname as dirname40, resolve as resolve55 } from "node:path";
161552
- import { fileURLToPath as fileURLToPath28 } from "node:url";
161792
+ import { fileURLToPath as fileURLToPath29 } from "node:url";
161553
161793
  function stagedDir() {
161554
161794
  return process.env.HIMI_BROWSER_PLANE_OUT ? resolve55(process.env.HIMI_BROWSER_PLANE_OUT) : resolve55(REPO2, "packages", "serve", "dist", "browser-plane");
161555
161795
  }
161556
161796
  function missingStaged() {
161557
- return [...SERVED].filter((f2) => !existsSync71(resolve55(stagedDir(), f2))).sort();
161797
+ return [...SERVED].filter((f2) => !existsSync72(resolve55(stagedDir(), f2))).sort();
161558
161798
  }
161559
161799
  function ensureBrowserPlaneStaged() {
161560
161800
  if (missingStaged().length === 0) return { ok: true, detail: "already staged" };
@@ -161644,7 +161884,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
161644
161884
  }
161645
161885
  const name = path2 === "/" || path2 === "/index.html" ? "host.html" : path2.slice(1);
161646
161886
  if (SERVED.has(name)) {
161647
- if (!existsSync71(resolve55(stagedDir(), name))) {
161887
+ if (!existsSync72(resolve55(stagedDir(), name))) {
161648
161888
  const restaged = ensureBrowserPlaneStaged();
161649
161889
  if (!restaged.ok) {
161650
161890
  res.writeHead(503, { "content-type": "application/json" });
@@ -161696,7 +161936,7 @@ var init_run_browser = __esm({
161696
161936
  init_open_url();
161697
161937
  init_file_store();
161698
161938
  init_wix_client_id();
161699
- HERE2 = dirname40(fileURLToPath28(import.meta.url));
161939
+ HERE2 = dirname40(fileURLToPath29(import.meta.url));
161700
161940
  REPO2 = resolve55(HERE2, "..", "..", "..");
161701
161941
  SERVED = /* @__PURE__ */ new Set(["host.html", "sw.js", "package-reader.js"]);
161702
161942
  }
@@ -161707,14 +161947,14 @@ var hhp_preview_exports = {};
161707
161947
  __export(hhp_preview_exports, {
161708
161948
  hhpPreviewResponse: () => hhpPreviewResponse
161709
161949
  });
161710
- import { existsSync as existsSync72, readFileSync as readFileSync87 } from "node:fs";
161950
+ import { existsSync as existsSync73, readFileSync as readFileSync87 } from "node:fs";
161711
161951
  import { join as join75 } from "node:path";
161712
161952
  function hhpPreviewResponse(root, request) {
161713
- if (new URL(request.url).pathname !== "/__himi/hhp-preview" || !existsSync72(join75(root, "hhp.json"))) return null;
161953
+ if (new URL(request.url).pathname !== "/__himi/hhp-preview" || !existsSync73(join75(root, "hhp.json"))) return null;
161714
161954
  if (request.method !== "GET") return new Response(null, { status: 405 });
161715
161955
  try {
161716
161956
  const file2 = localPath(root, ".himi/hhp-preview.json");
161717
- const authored2 = existsSync72(file2) ? JSON.parse(readFileSync87(file2, "utf8")) : {};
161957
+ const authored2 = existsSync73(file2) ? JSON.parse(readFileSync87(file2, "utf8")) : {};
161718
161958
  if (authored2.mockCapabilities && (!Array.isArray(authored2.mockCapabilities) || authored2.mockCapabilities.some((v2) => typeof v2 !== "string"))) throw new Error("mockCapabilities must be a string array.");
161719
161959
  const fixtures = authored2.fixtures ?? {};
161720
161960
  if (typeof fixtures !== "object" || Array.isArray(fixtures) || fixtures === null) throw new Error("fixtures must be an object.");
@@ -163762,13 +164002,13 @@ __export(credential_profile_exports, {
163762
164002
  profilePath: () => profilePath,
163763
164003
  resolveStoreCredentials: () => resolveStoreCredentials
163764
164004
  });
163765
- import { existsSync as existsSync73, readFileSync as readFileSync89 } from "node:fs";
163766
- import { homedir as homedir9 } from "node:os";
164005
+ import { existsSync as existsSync74, readFileSync as readFileSync89 } from "node:fs";
164006
+ import { homedir as homedir10 } from "node:os";
163767
164007
  import { join as join76 } from "node:path";
163768
- function credentialsDir(home = homedir9()) {
164008
+ function credentialsDir(home = homedir10()) {
163769
164009
  return join76(home, ".himalaya", "store-credentials");
163770
164010
  }
163771
- function profilePath(name, home = homedir9()) {
164011
+ function profilePath(name, home = homedir10()) {
163772
164012
  if (!PROFILE_NAME.test(name)) {
163773
164013
  throw new Error(
163774
164014
  `credential profile ${JSON.stringify(name)} is not a profile name \u2014 use letters, digits, ".", "_" or "-" starting with a letter or digit. It names ${join76(credentialsDir(home), "<name>.json")}; it is never a path.`
@@ -163804,9 +164044,9 @@ function namedProfile(cfg, profileFlag) {
163804
164044
  function resolveStoreCredentials(opts) {
163805
164045
  const { app, cfg } = opts;
163806
164046
  const env = opts.env ?? process.env;
163807
- const home = opts.home ?? homedir9();
164047
+ const home = opts.home ?? homedir10();
163808
164048
  const read = opts.readProfile ?? ((p2) => readFileSync89(p2, "utf8"));
163809
- const exists = opts.profileExists ?? existsSync73;
164049
+ const exists = opts.profileExists ?? existsSync74;
163810
164050
  const ios = cfg.ios ?? {};
163811
164051
  const flagName = opts.profileFlag?.trim();
163812
164052
  const named = namedProfile(cfg, opts.profileFlag);
@@ -163872,8 +164112,8 @@ var init_credential_profile = __esm({
163872
164112
 
163873
164113
  // ../store-release/iap-credentials.ts
163874
164114
  import { createHash as createHash39 } from "node:crypto";
163875
- import { existsSync as existsSync74, readFileSync as readFileSync90, realpathSync as realpathSync12 } from "node:fs";
163876
- import { homedir as homedir10 } from "node:os";
164115
+ import { existsSync as existsSync75, readFileSync as readFileSync90, realpathSync as realpathSync12 } from "node:fs";
164116
+ import { homedir as homedir11 } from "node:os";
163877
164117
  function accountFingerprint(keyId, issuerId) {
163878
164118
  return `sha256:${createHash39("sha256").update(`${issuerId}:${keyId}`).digest("hex").slice(0, 16)}`;
163879
164119
  }
@@ -163905,7 +164145,7 @@ function canonicalKeyPath(path2, profile, realpath) {
163905
164145
  }
163906
164146
  function resolveIapCredentials(options) {
163907
164147
  const { target } = options;
163908
- const home = options.home ?? homedir10();
164148
+ const home = options.home ?? homedir11();
163909
164149
  const readFile3 = options.readFile ?? ((p2) => readFileSync90(p2, "utf8"));
163910
164150
  const realpath = options.realpath ?? realpathSync12;
163911
164151
  const profile = requireExplicitProfile(options.profileFlag, target);
@@ -163916,7 +164156,7 @@ function resolveIapCredentials(options) {
163916
164156
  env: {},
163917
164157
  home,
163918
164158
  readProfile: readFile3,
163919
- profileExists: options.exists ?? existsSync74
164159
+ profileExists: options.exists ?? existsSync75
163920
164160
  });
163921
164161
  assertCredentialOutsideRepo(`credential profile "${profile}"`, realpath(profilePath(profile, home)));
163922
164162
  assertCredentialOutsideRepo(`credential profile "${profile}" ascKeyPath`, canonicalKeyPath(creds.ascKeyPath, profile, realpath));
@@ -164437,7 +164677,7 @@ var init_store_spec = __esm({
164437
164677
  });
164438
164678
 
164439
164679
  // src/iap-config-edit.ts
164440
- import { existsSync as existsSync75, readFileSync as readFileSync92 } from "node:fs";
164680
+ import { existsSync as existsSync76, readFileSync as readFileSync92 } from "node:fs";
164441
164681
  import { basename as basename20, join as join77 } from "node:path";
164442
164682
  import ts8 from "typescript";
164443
164683
  function bindPurchasesAppInConfig(source, options) {
@@ -164518,7 +164758,7 @@ function capabilityFinding(app, fileName) {
164518
164758
  function withStoreBundle(dir, options) {
164519
164759
  if (options.storeBundleId) return options;
164520
164760
  const path2 = join77(dir, "store", "store.config.yaml");
164521
- if (!existsSync75(path2)) return options;
164761
+ if (!existsSync76(path2)) return options;
164522
164762
  const storeBundleId = parseStoreConfig(readFileSync92(path2, "utf8")).ios?.bundleId;
164523
164763
  return storeBundleId ? { ...options, storeBundleId } : options;
164524
164764
  }
@@ -165169,7 +165409,7 @@ var init_store_iap_screenshots = __esm({
165169
165409
  });
165170
165410
 
165171
165411
  // src/store-iap-screenshot-render.ts
165172
- import { existsSync as existsSync76, mkdtempSync as mkdtempSync4, readFileSync as readFileSync93, rmSync as rmSync18 } from "node:fs";
165412
+ import { existsSync as existsSync77, mkdtempSync as mkdtempSync4, readFileSync as readFileSync93, rmSync as rmSync18 } from "node:fs";
165173
165413
  import { tmpdir as tmpdir5 } from "node:os";
165174
165414
  import { join as join79 } from "node:path";
165175
165415
  function renderProblems(render, entityId) {
@@ -165232,7 +165472,7 @@ function createReviewScreenRenderer() {
165232
165472
  async capture(html, contentDir2) {
165233
165473
  const { pngPageHtml: pngPageHtml2, stabilizePngPage: stabilizePngPage2 } = await Promise.resolve().then(() => (init_render_descriptor(), render_descriptor_exports));
165234
165474
  const tokensPath = join79(contentDir2, "tokens.json");
165235
- const tokens2 = existsSync76(tokensPath) ? JSON.parse(readFileSync93(tokensPath, "utf8")) : null;
165475
+ const tokens2 = existsSync77(tokensPath) ? JSON.parse(readFileSync93(tokensPath, "utf8")) : null;
165236
165476
  const { width, height, scale } = REVIEW_SCREENSHOT_FRAME;
165237
165477
  const page = await (await (browser ??= launch())).newPage({ viewport: { width, height }, deviceScaleFactor: scale, colorScheme: "light" });
165238
165478
  try {
@@ -165313,8 +165553,8 @@ __export(store_iap_exports, {
165313
165553
  runStoreIap: () => runStoreIap
165314
165554
  });
165315
165555
  import { randomUUID as randomUUID8 } from "node:crypto";
165316
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync35, readFileSync as readFileSync94, realpathSync as realpathSync13, renameSync as renameSync12, rmSync as rmSync19, writeFileSync as writeFileSync31 } from "node:fs";
165317
- import { homedir as homedir11, hostname } from "node:os";
165556
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync36, readFileSync as readFileSync94, realpathSync as realpathSync13, renameSync as renameSync12, rmSync as rmSync19, writeFileSync as writeFileSync31 } from "node:fs";
165557
+ import { homedir as homedir12, hostname } from "node:os";
165318
165558
  import { dirname as dirname42, join as join80, resolve as resolve57 } from "node:path";
165319
165559
  function scrubDeep(value, scrub) {
165320
165560
  if (typeof value === "string") return scrub(value);
@@ -165838,7 +166078,7 @@ async function screenshotsCommand(flags, deps, out2) {
165838
166078
  return report3.complete ? 0 : 1;
165839
166079
  }
165840
166080
  function writeBinaryFile(path2, bytes2) {
165841
- mkdirSync35(dirname42(path2), { recursive: true });
166081
+ mkdirSync36(dirname42(path2), { recursive: true });
165842
166082
  const partial = `${path2}.${process.pid}.partial`;
165843
166083
  writeFileSync31(partial, bytes2);
165844
166084
  renameSync12(partial, path2);
@@ -165891,8 +166131,8 @@ function acquireApplyLock(dir, appleAppId) {
165891
166131
  };
165892
166132
  }
165893
166133
  function stateDir(appleAppId) {
165894
- const dir = join80(homedir11(), ".himalaya", "store-iap", appleAppId);
165895
- mkdirSync35(dir, { recursive: true, mode: 448 });
166134
+ const dir = join80(homedir12(), ".himalaya", "store-iap", appleAppId);
166135
+ mkdirSync36(dir, { recursive: true, mode: 448 });
165896
166136
  return dir;
165897
166137
  }
165898
166138
  async function confirmOnTerminal(question) {
@@ -166395,7 +166635,7 @@ __export(preflight_app_exports, {
166395
166635
  profileAccount: () => profileAccount,
166396
166636
  readXcconfigVars: () => readXcconfigVars
166397
166637
  });
166398
- import { readFileSync as readFileSync95, existsSync as existsSync77, readdirSync as readdirSync34, statSync as statSync21 } from "node:fs";
166638
+ import { readFileSync as readFileSync95, existsSync as existsSync78, readdirSync as readdirSync34, statSync as statSync21 } from "node:fs";
166399
166639
  import { createHash as createHash41 } from "node:crypto";
166400
166640
  import { dirname as dirname43, join as join81 } from "node:path";
166401
166641
  function analyze(projectYml, storeConfig, icon, account) {
@@ -166522,7 +166762,7 @@ function readXcconfigVars(iosDir, projectYml) {
166522
166762
  const vars = {};
166523
166763
  const seen = /* @__PURE__ */ new Set();
166524
166764
  const read = (path2) => {
166525
- if (seen.has(path2) || !existsSync77(path2)) return;
166765
+ if (seen.has(path2) || !existsSync78(path2)) return;
166526
166766
  seen.add(path2);
166527
166767
  for (const raw of readFileSync95(path2, "utf8").split("\n")) {
166528
166768
  const inc = /^\s*#include\??\s+"([^"]+)"/.exec(raw);
@@ -166551,8 +166791,8 @@ function profileAccount(app, storeConfig, opts = {}) {
166551
166791
  }
166552
166792
  }
166553
166793
  async function preflightApp(app, opts = {}) {
166554
- const projectYml = existsSync77(iosProjectYml(app)) ? readFileSync95(iosProjectYml(app), "utf8") : "";
166555
- const storeConfig = existsSync77(storeConfigPath(app)) ? readFileSync95(storeConfigPath(app), "utf8") : "";
166794
+ const projectYml = existsSync78(iosProjectYml(app)) ? readFileSync95(iosProjectYml(app), "utf8") : "";
166795
+ const storeConfig = existsSync78(storeConfigPath(app)) ? readFileSync95(storeConfigPath(app), "utf8") : "";
166556
166796
  const identity = projectYml ? analyzeStoreIdentity(projectYml, storeConfig, readXcconfigVars(join81(appDir(app), "ios"), projectYml)) : [];
166557
166797
  if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }, ...identity];
166558
166798
  const findings = analyze(
@@ -166590,15 +166830,15 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
166590
166830
  function appLevelMetadataFiles(app, locale = "en-US") {
166591
166831
  const root = join81(storeDir(app), "metadata");
166592
166832
  const out2 = /* @__PURE__ */ new Set();
166593
- if (existsSync77(root)) {
166833
+ if (existsSync78(root)) {
166594
166834
  for (const n2 of readdirSync34(root)) if (n2.endsWith(".txt")) out2.add(n2);
166595
166835
  }
166596
- if (existsSync77(join81(root, locale, "privacy_url.txt"))) out2.add("privacy_url.txt");
166836
+ if (existsSync78(join81(root, locale, "privacy_url.txt"))) out2.add("privacy_url.txt");
166597
166837
  return out2;
166598
166838
  }
166599
166839
  function reviewInfoFiles(app) {
166600
166840
  const dir = join81(storeDir(app), "review_information");
166601
- if (!existsSync77(dir)) return /* @__PURE__ */ new Set();
166841
+ if (!existsSync78(dir)) return /* @__PURE__ */ new Set();
166602
166842
  return new Set(readdirSync34(dir).filter((n2) => n2.endsWith(".txt")));
166603
166843
  }
166604
166844
  function isValidAppStoreSize(w2, h2) {
@@ -166745,20 +166985,20 @@ function analyzeListing(metaFiles, shots) {
166745
166985
  }
166746
166986
  function metadataFilesPresent(app, locale = "en-US") {
166747
166987
  const dir = join81(storeDir(app), "metadata", locale);
166748
- if (!existsSync77(dir)) return /* @__PURE__ */ new Set();
166988
+ if (!existsSync78(dir)) return /* @__PURE__ */ new Set();
166749
166989
  return new Set(readdirSync34(dir).filter((n2) => n2.endsWith(".txt")));
166750
166990
  }
166751
166991
  function listScreenshots(app, locale = "en-US") {
166752
166992
  const out2 = [];
166753
166993
  const flat = join81(storeDir(app), "screenshots", locale);
166754
- if (existsSync77(flat)) {
166994
+ if (existsSync78(flat)) {
166755
166995
  for (const png of readdirSync34(flat).filter((n2) => n2.endsWith(".png"))) {
166756
166996
  const sz = pngSize2(readFileSync95(join81(flat, png)));
166757
166997
  if (sz) out2.push({ name: png, w: sz.w, h: sz.h });
166758
166998
  }
166759
166999
  }
166760
167000
  const legacy = join81(storeDir(app), "metadata", locale, "screenshots");
166761
- if (existsSync77(legacy)) {
167001
+ if (existsSync78(legacy)) {
166762
167002
  for (const deviceDir of readdirSync34(legacy)) {
166763
167003
  const d2 = join81(legacy, deviceDir);
166764
167004
  if (!statSync21(d2).isDirectory()) continue;
@@ -166772,7 +167012,7 @@ function listScreenshots(app, locale = "en-US") {
166772
167012
  }
166773
167013
  function placeholderHashes2() {
166774
167014
  const templateIos = join81(appDir("_template"), "ios");
166775
- if (!existsSync77(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
167015
+ if (!existsSync78(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
166776
167016
  for (const target of readdirSync34(templateIos)) {
166777
167017
  const p2 = join81(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
166778
167018
  try {
@@ -166808,7 +167048,7 @@ async function pixelIssues(bytes2) {
166808
167048
  }
166809
167049
  }
166810
167050
  async function appIconState(iosDir) {
166811
- if (!existsSync77(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
167051
+ if (!existsSync78(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
166812
167052
  for (const target of readdirSync34(iosDir)) {
166813
167053
  const p2 = join81(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
166814
167054
  try {
@@ -167721,11 +167961,11 @@ __export(notify_exports, {
167721
167961
  runNotify: () => runNotify,
167722
167962
  saveAdminSession: () => saveAdminSession
167723
167963
  });
167724
- import { chmodSync as chmodSync3, mkdirSync as mkdirSync36, readFileSync as readFileSync98, writeFileSync as writeFileSync32 } from "node:fs";
167725
- import { homedir as homedir12 } from "node:os";
167964
+ import { chmodSync as chmodSync3, mkdirSync as mkdirSync37, readFileSync as readFileSync98, writeFileSync as writeFileSync32 } from "node:fs";
167965
+ import { homedir as homedir13 } from "node:os";
167726
167966
  import { dirname as dirname45, join as join82 } from "node:path";
167727
167967
  function defaultSessionsPath() {
167728
- return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join82(homedir12(), ".himalaya", "admin-sessions.json");
167968
+ return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join82(homedir13(), ".himalaya", "admin-sessions.json");
167729
167969
  }
167730
167970
  function loadSessionsFile(path2 = defaultSessionsPath()) {
167731
167971
  try {
@@ -167737,7 +167977,7 @@ function loadSessionsFile(path2 = defaultSessionsPath()) {
167737
167977
  function saveAdminSession(adminUrl, session, path2 = defaultSessionsPath()) {
167738
167978
  const file2 = loadSessionsFile(path2);
167739
167979
  file2.sessions = { ...file2.sessions, [adminUrl]: session };
167740
- mkdirSync36(dirname45(path2), { recursive: true, mode: 448 });
167980
+ mkdirSync37(dirname45(path2), { recursive: true, mode: 448 });
167741
167981
  writeFileSync32(path2, JSON.stringify(file2, null, 2) + "\n", { mode: 384 });
167742
167982
  try {
167743
167983
  chmodSync3(dirname45(path2), 448);
@@ -168098,7 +168338,7 @@ __export(base44_adopt_exports, {
168098
168338
  renderAdoptModule: () => renderAdoptModule,
168099
168339
  runBase44Adopt: () => runBase44Adopt
168100
168340
  });
168101
- import { existsSync as existsSync78, readFileSync as readFileSync99, writeFileSync as writeFileSync33 } from "node:fs";
168341
+ import { existsSync as existsSync79, readFileSync as readFileSync99, writeFileSync as writeFileSync33 } from "node:fs";
168102
168342
  import { join as join83, resolve as resolve59 } from "node:path";
168103
168343
  function prop(entity, key3) {
168104
168344
  const props = entity.schema?.properties;
@@ -168207,7 +168447,7 @@ function runBase44Adopt(opts) {
168207
168447
  const issues = validateBase44Entities({ entities: result.entities, functions: result.functions }, opts.app);
168208
168448
  if (opts.write === void 0 || opts.write === false || issues.some((i2) => i2.severity === "error")) return { result, module, issues };
168209
168449
  const target = typeof opts.write === "string" ? resolve59(opts.cwd, opts.write) : join83(opts.cwd, ADOPT_MODULE_FILENAME);
168210
- if (existsSync78(target)) {
168450
+ if (existsSync79(target)) {
168211
168451
  throw new AdoptError("adopt_target_exists", `${target} already exists \u2014 adopt never overwrites. Delete or rename it, or pass --write <other path>.`, 1, { path: target });
168212
168452
  }
168213
168453
  writeFileSync33(target, module);
@@ -168456,7 +168696,7 @@ __export(generate_exports, {
168456
168696
  writeGenerated: () => writeGenerated
168457
168697
  });
168458
168698
  import { createHash as createHash43 } from "node:crypto";
168459
- import { existsSync as existsSync79, mkdirSync as mkdirSync37, readdirSync as readdirSync35, readFileSync as readFileSync100, writeFileSync as writeFileSync34 } from "node:fs";
168699
+ import { existsSync as existsSync80, mkdirSync as mkdirSync38, readdirSync as readdirSync35, readFileSync as readFileSync100, writeFileSync as writeFileSync34 } from "node:fs";
168460
168700
  import { dirname as dirname46, join as join84 } from "node:path";
168461
168701
  function withHeader(body) {
168462
168702
  return `${GENERATED_HEADER}${sha2566(body)}
@@ -168583,7 +168823,7 @@ function writeGenerated(dir, files, opts = {}) {
168583
168823
  const abs = join84(dir, f2.path);
168584
168824
  const next = withHeader(f2.body);
168585
168825
  let outcome;
168586
- if (!existsSync79(abs)) outcome = "written";
168826
+ if (!existsSync80(abs)) outcome = "written";
168587
168827
  else {
168588
168828
  const cur = readFileSync100(abs, "utf8");
168589
168829
  if (cur === next) outcome = "unchanged";
@@ -168591,7 +168831,7 @@ function writeGenerated(dir, files, opts = {}) {
168591
168831
  else outcome = "written";
168592
168832
  }
168593
168833
  if (outcome === "written" && !opts.dryRun) {
168594
- mkdirSync37(dirname46(abs), { recursive: true });
168834
+ mkdirSync38(dirname46(abs), { recursive: true });
168595
168835
  writeFileSync34(abs, next);
168596
168836
  }
168597
168837
  out2.push({ path: f2.path, outcome });
@@ -168602,14 +168842,14 @@ function orphanedFiles(dir, current) {
168602
168842
  const keep = new Set(current.map((f2) => f2.path));
168603
168843
  const found = [];
168604
168844
  const t5 = join84(dir, "tier5-src");
168605
- if (!existsSync79(t5)) return found;
168845
+ if (!existsSync80(t5)) return found;
168606
168846
  const candidates = readdirSync35(t5).filter((d2) => d2.startsWith("b44-")).map((d2) => `tier5-src/${d2}/index.ts`);
168607
168847
  const shared = join84(t5, "_shared");
168608
- if (existsSync79(shared)) {
168848
+ if (existsSync80(shared)) {
168609
168849
  for (const f2 of readdirSync35(shared)) if (/^b44-.*-plan\.ts$/.test(f2)) candidates.push(`tier5-src/_shared/${f2}`);
168610
168850
  }
168611
168851
  for (const rel of candidates.sort()) {
168612
- if (keep.has(rel) || !existsSync79(join84(dir, rel))) continue;
168852
+ if (keep.has(rel) || !existsSync80(join84(dir, rel))) continue;
168613
168853
  if (readFileSync100(join84(dir, rel), "utf8").startsWith(GENERATED_HEADER)) found.push(rel);
168614
168854
  }
168615
168855
  return found;
@@ -168648,18 +168888,18 @@ __export(base44_auth_exports, {
168648
168888
  usableBase44Auth: () => usableBase44Auth,
168649
168889
  writeBase44Session: () => writeBase44Session
168650
168890
  });
168651
- import { chmodSync as chmodSync4, existsSync as existsSync80, mkdirSync as mkdirSync38, readFileSync as readFileSync101, rmSync as rmSync20, writeFileSync as writeFileSync35 } from "node:fs";
168652
- import { homedir as homedir13 } from "node:os";
168891
+ import { chmodSync as chmodSync4, existsSync as existsSync81, mkdirSync as mkdirSync39, readFileSync as readFileSync101, rmSync as rmSync20, writeFileSync as writeFileSync35 } from "node:fs";
168892
+ import { homedir as homedir14 } from "node:os";
168653
168893
  import { dirname as dirname47, join as join85 } from "node:path";
168654
168894
  function base44ApiBase(env = process.env) {
168655
168895
  return (env.BASE44_API_URL?.trim() || "https://app.base44.com").replace(/\/+$/, "");
168656
168896
  }
168657
- function base44SessionPath(home = homedir13()) {
168897
+ function base44SessionPath(home = homedir14()) {
168658
168898
  return join85(home, ".himi", "base44", "session.json");
168659
168899
  }
168660
168900
  function readBase44Session(home) {
168661
168901
  const p2 = base44SessionPath(home);
168662
- if (!existsSync80(p2)) return void 0;
168902
+ if (!existsSync81(p2)) return void 0;
168663
168903
  try {
168664
168904
  const s2 = JSON.parse(readFileSync101(p2, "utf8"));
168665
168905
  return typeof s2.accessToken === "string" && s2.accessToken ? s2 : void 0;
@@ -168669,7 +168909,7 @@ function readBase44Session(home) {
168669
168909
  }
168670
168910
  function writeBase44Session(session, home) {
168671
168911
  const p2 = base44SessionPath(home);
168672
- mkdirSync38(dirname47(p2), { recursive: true, mode: 448 });
168912
+ mkdirSync39(dirname47(p2), { recursive: true, mode: 448 });
168673
168913
  writeFileSync35(p2, `${JSON.stringify(session, null, 2)}
168674
168914
  `, { mode: 384 });
168675
168915
  chmodSync4(p2, 384);
@@ -168677,7 +168917,7 @@ function writeBase44Session(session, home) {
168677
168917
  }
168678
168918
  function deleteBase44Session(home) {
168679
168919
  const p2 = base44SessionPath(home);
168680
- if (!existsSync80(p2)) return false;
168920
+ if (!existsSync81(p2)) return false;
168681
168921
  rmSync20(p2, { force: true });
168682
168922
  return true;
168683
168923
  }
@@ -168778,9 +169018,9 @@ function hasBase44WriteScope(auth) {
168778
169018
  if (!scopes) return "unknown";
168779
169019
  return scopes.includes("apps:write");
168780
169020
  }
168781
- function importBase44CliSession(home = homedir13(), env = process.env) {
169021
+ function importBase44CliSession(home = homedir14(), env = process.env) {
168782
169022
  const src = join85(home, ".base44", "auth", "auth.json");
168783
- if (!existsSync80(src)) throw new Error(`no Base44 CLI session at ${src} \u2014 run \`npx base44 login\` first, or use \`himi base44 login\``);
169023
+ if (!existsSync81(src)) throw new Error(`no Base44 CLI session at ${src} \u2014 run \`npx base44 login\` first, or use \`himi base44 login\``);
168784
169024
  const a2 = JSON.parse(readFileSync101(src, "utf8"));
168785
169025
  if (typeof a2.accessToken !== "string" || !a2.accessToken) throw new Error(`${src} holds no access token`);
168786
169026
  const session = {
@@ -168878,11 +169118,11 @@ __export(seed_exports, {
168878
169118
  seedBase44Entities: () => seedBase44Entities,
168879
169119
  writeBase44SeedRows: () => writeBase44SeedRows
168880
169120
  });
168881
- import { existsSync as existsSync81, readFileSync as readFileSync102, writeFileSync as writeFileSync36 } from "node:fs";
169121
+ import { existsSync as existsSync82, readFileSync as readFileSync102, writeFileSync as writeFileSync36 } from "node:fs";
168882
169122
  import { join as join86 } from "node:path";
168883
169123
  function readBase44SeedFile(dir) {
168884
169124
  const file2 = join86(dir, BASE44_SEED_FILE);
168885
- if (!existsSync81(file2)) return {};
169125
+ if (!existsSync82(file2)) return {};
168886
169126
  let parsed;
168887
169127
  try {
168888
169128
  parsed = JSON.parse(readFileSync102(file2, "utf8"));
@@ -169042,7 +169282,7 @@ function writeBase44SeedRows(opts) {
169042
169282
  return { ok: false, path: path2, entities: {}, agentPrompt: "", next: [], note: opts.only ? `--only ${opts.only.join(",")} matched no owned entity` : `no owned Base44 entities declared \u2014 add one with \`name\` (physically ${base44Prefix(app)}<Name>). Adopted entities are never seeded.` };
169043
169283
  }
169044
169284
  let existing = {};
169045
- if (existsSync81(path2)) {
169285
+ if (existsSync82(path2)) {
169046
169286
  let parsed;
169047
169287
  try {
169048
169288
  parsed = JSON.parse(readFileSync102(path2, "utf8"));
@@ -169397,7 +169637,7 @@ __export(functions_exports2, {
169397
169637
  markerContent: () => markerContent,
169398
169638
  readFunctionSource: () => readFunctionSource
169399
169639
  });
169400
- import { existsSync as existsSync82, lstatSync as lstatSync21 } from "node:fs";
169640
+ import { existsSync as existsSync83, lstatSync as lstatSync21 } from "node:fs";
169401
169641
  import { join as join87 } from "node:path";
169402
169642
  function markerContent(app) {
169403
169643
  return `${JSON.stringify({ app, by: "himi" })}
@@ -169406,7 +169646,7 @@ function markerContent(app) {
169406
169646
  function readFunctionSource(appDir3, name, app) {
169407
169647
  const rel = `base44/functions/${name}/`;
169408
169648
  const folder = join87(appDir3, "base44", "functions", name);
169409
- if (!existsSync82(folder) || !lstatSync21(folder).isDirectory()) throw new FunctionSourceError("function_source_missing", `no source folder at ${rel}`);
169649
+ if (!existsSync83(folder) || !lstatSync21(folder).isDirectory()) throw new FunctionSourceError("function_source_missing", `no source folder at ${rel}`);
169410
169650
  const { entries, skipped } = collectAppSource(folder);
169411
169651
  if (skipped.length) throw new FunctionSourceError("function_source_unsafe", `${rel} holds paths himi will not upload (symlinks or denied names): ${skipped.join(", ")} \u2014 remove them`);
169412
169652
  const secrets = secretFindings(entries);
@@ -169744,12 +169984,12 @@ __export(apply_exports, {
169744
169984
  createBase44Entities: () => createBase44Entities,
169745
169985
  fileLedger: () => fileLedger
169746
169986
  });
169747
- import { existsSync as existsSync83, readFileSync as readFileSync103, writeFileSync as writeFileSync37 } from "node:fs";
169987
+ import { existsSync as existsSync84, readFileSync as readFileSync103, writeFileSync as writeFileSync37 } from "node:fs";
169748
169988
  import { join as join88 } from "node:path";
169749
169989
  function fileLedger(dir, appId2) {
169750
169990
  const path2 = join88(dir, LEDGER_FILE2);
169751
169991
  const load3 = () => {
169752
- if (!existsSync83(path2)) return {};
169992
+ if (!existsSync84(path2)) return {};
169753
169993
  let v2;
169754
169994
  try {
169755
169995
  v2 = JSON.parse(readFileSync103(path2, "utf8"));
@@ -172122,7 +172362,7 @@ var init_brand_font = __esm({
172122
172362
  });
172123
172363
 
172124
172364
  // src/site-analyze/write-artifacts.ts
172125
- import { mkdirSync as mkdirSync39, rmSync as rmSync21, writeFileSync as writeFileSync38 } from "node:fs";
172365
+ import { mkdirSync as mkdirSync40, rmSync as rmSync21, writeFileSync as writeFileSync38 } from "node:fs";
172126
172366
  import { join as join89 } from "node:path";
172127
172367
  function attachVeloSources(book, sources, put) {
172128
172368
  const byPath = new Map((sources ?? []).map((s2) => [s2.path, s2.text]));
@@ -172278,12 +172518,12 @@ async function downloadMedia(book, fetchImpl, put) {
172278
172518
  }
172279
172519
  async function writeBusinessBook(result, opts) {
172280
172520
  const out2 = opts.outDir;
172281
- mkdirSync39(join89(out2, "evidence/pages"), { recursive: true });
172282
- mkdirSync39(join89(out2, "media/catalog"), { recursive: true });
172521
+ mkdirSync40(join89(out2, "evidence/pages"), { recursive: true });
172522
+ mkdirSync40(join89(out2, "media/catalog"), { recursive: true });
172283
172523
  const files = [];
172284
172524
  const put = (rel, body) => {
172285
172525
  const p2 = join89(out2, rel);
172286
- mkdirSync39(join89(p2, ".."), { recursive: true });
172526
+ mkdirSync40(join89(p2, ".."), { recursive: true });
172287
172527
  writeFileSync38(p2, body);
172288
172528
  files.push(rel);
172289
172529
  };
@@ -172909,7 +173149,7 @@ var init_analyze = __esm({
172909
173149
  });
172910
173150
 
172911
173151
  // src/base44-analyze/write-artifacts.ts
172912
- import { existsSync as existsSync84, mkdirSync as mkdirSync40, readFileSync as readFileSync104, rmSync as rmSync22, writeFileSync as writeFileSync39 } from "node:fs";
173152
+ import { existsSync as existsSync85, mkdirSync as mkdirSync41, readFileSync as readFileSync104, rmSync as rmSync22, writeFileSync as writeFileSync39 } from "node:fs";
172913
173153
  import { dirname as dirname48, join as join90, resolve as resolve60, sep as sep19 } from "node:path";
172914
173154
  function isBookFolder(dir) {
172915
173155
  try {
@@ -173000,17 +173240,17 @@ function writeBase44Book(result, outDir, opts = {}) {
173000
173240
  const md = renderBookMd(book);
173001
173241
  assertNoSecrets(json8);
173002
173242
  assertNoSecrets(md);
173003
- const owned = ["book.json", "BOOK.md", "source", "screenshots"].filter((n2) => existsSync84(join90(out2, n2)));
173243
+ const owned = ["book.json", "BOOK.md", "source", "screenshots"].filter((n2) => existsSync85(join90(out2, n2)));
173004
173244
  if (owned.length) {
173005
173245
  if (!isBookFolder(out2)) throw new Error(`refusing to write the app book into ${out2}: it already has ${owned.join(", ")} that ${owned.length === 1 ? "is" : "are"} not from an app book \u2014 pick an empty --out`);
173006
173246
  for (const d2 of ["source", "screenshots"]) rmSync22(join90(out2, d2), { recursive: true, force: true });
173007
173247
  }
173008
- mkdirSync40(out2, { recursive: true });
173248
+ mkdirSync41(out2, { recursive: true });
173009
173249
  writeFileSync39(join90(out2, "book.json"), json8);
173010
173250
  writeFileSync39(join90(out2, "BOOK.md"), md);
173011
173251
  files.push("book.json", "BOOK.md");
173012
173252
  for (const s2 of shots) {
173013
- mkdirSync40(join90(out2, "screenshots"), { recursive: true });
173253
+ mkdirSync41(join90(out2, "screenshots"), { recursive: true });
173014
173254
  writeFileSync39(join90(out2, "screenshots", s2.filename), s2.bytes);
173015
173255
  files.push(`screenshots/${s2.filename}`);
173016
173256
  }
@@ -173019,7 +173259,7 @@ function writeBase44Book(result, outDir, opts = {}) {
173019
173259
  if (!safeRel(f2.path)) continue;
173020
173260
  const dest = join90(sourceRoot, ...f2.path.split("/"));
173021
173261
  if (!dest.startsWith(sourceRoot + sep19)) continue;
173022
- mkdirSync40(dirname48(dest), { recursive: true });
173262
+ mkdirSync41(dirname48(dest), { recursive: true });
173023
173263
  writeFileSync39(dest, f2.bytes);
173024
173264
  }
173025
173265
  if (result.sourceFiles.length) files.push(`source/ (${result.sourceFiles.length} files)`);
@@ -176561,7 +176801,7 @@ __export(cli_exports, {
176561
176801
  systemTar: () => systemTar
176562
176802
  });
176563
176803
  import { execFile } from "node:child_process";
176564
- import { mkdirSync as mkdirSync41, mkdtempSync as mkdtempSync5, rmSync as rmSync23, writeFileSync as writeFileSync40 } from "node:fs";
176804
+ import { mkdirSync as mkdirSync42, mkdtempSync as mkdtempSync5, rmSync as rmSync23, writeFileSync as writeFileSync40 } from "node:fs";
176565
176805
  import { tmpdir as tmpdir6 } from "node:os";
176566
176806
  import { join as join91, resolve as resolve61 } from "node:path";
176567
176807
  import { promisify } from "node:util";
@@ -176582,7 +176822,7 @@ function projectDownloader(apiFetch, apiBase, token, extract = systemTar) {
176582
176822
  const archive = join91(root, "project.tar");
176583
176823
  const dir = join91(root, "project");
176584
176824
  writeFileSync40(archive, bytes2);
176585
- mkdirSync41(dir);
176825
+ mkdirSync42(dir);
176586
176826
  await extract(archive, dir);
176587
176827
  return { dir, cleanup };
176588
176828
  } catch (e2) {
@@ -177497,7 +177737,7 @@ __export(cli_exports2, {
177497
177737
  ONE_APP_WORKFLOW: () => ONE_APP_WORKFLOW,
177498
177738
  runOneAppCommand: () => runOneAppCommand
177499
177739
  });
177500
- import { closeSync as closeSync7, constants as constants4, lstatSync as lstatSync22, mkdirSync as mkdirSync42, openSync as openSync6, readFileSync as readFileSync105, realpathSync as realpathSync14, writeFileSync as writeFileSync41 } from "node:fs";
177740
+ import { closeSync as closeSync7, constants as constants4, lstatSync as lstatSync22, mkdirSync as mkdirSync43, openSync as openSync6, readFileSync as readFileSync105, realpathSync as realpathSync14, writeFileSync as writeFileSync41 } from "node:fs";
177501
177741
  import { createHash as createHash45 } from "node:crypto";
177502
177742
  import { dirname as dirname49, join as join92, parse as parse3, resolve as resolve62 } from "node:path";
177503
177743
  function readOptions(argv, cwd, commandIncluded) {
@@ -177648,12 +177888,12 @@ Collect the source mobile app and hand it to the current coding agent. The agent
177648
177888
  try {
177649
177889
  options = readOptions(argv, deps.cwd ?? process.cwd(), commandIncluded);
177650
177890
  try {
177651
- mkdirSync42(options.parentDir, { recursive: true, mode: 448 });
177891
+ mkdirSync43(options.parentDir, { recursive: true, mode: 448 });
177652
177892
  assertSafeParents(options.parentDir);
177653
- mkdirSync42(options.workspace, { mode: 448 });
177893
+ mkdirSync43(options.workspace, { mode: 448 });
177654
177894
  if (realpathSync14(options.workspace) !== options.workspace) throw new Error("destination changed");
177655
177895
  evidenceDir = join92(options.workspace, ".himi", "one-app");
177656
- mkdirSync42(evidenceDir, { recursive: true, mode: 448 });
177896
+ mkdirSync43(evidenceDir, { recursive: true, mode: 448 });
177657
177897
  } catch (error) {
177658
177898
  if (error.code === "EEXIST") {
177659
177899
  throw new OneAppError("output_exists", "The destination already exists. Choose a new --name or --dir.");
@@ -179789,7 +180029,7 @@ var init_customer_build = __esm({
179789
180029
  });
179790
180030
 
179791
180031
  // src/site-analyze/apply.ts
179792
- import { existsSync as existsSync85, readFileSync as readFileSync106, writeFileSync as writeFileSync42, copyFileSync as copyFileSync2, mkdirSync as mkdirSync43, realpathSync as realpathSync15, statSync as statSync22 } from "node:fs";
180032
+ import { existsSync as existsSync86, readFileSync as readFileSync106, writeFileSync as writeFileSync42, copyFileSync as copyFileSync2, mkdirSync as mkdirSync44, realpathSync as realpathSync15, statSync as statSync22 } from "node:fs";
179793
180033
  import { dirname as dirname50, isAbsolute as isAbsolute8, join as join93, resolve as resolve63, sep as sep20 } from "node:path";
179794
180034
  import { spawnSync as spawnSync4 } from "node:child_process";
179795
180035
  function unpairedRedirectNote(overlay) {
@@ -179805,7 +180045,7 @@ function committedShellProvisioning(path2) {
179805
180045
  function findRepoRoot(cwd) {
179806
180046
  let dir = cwd;
179807
180047
  for (let i2 = 0; i2 < 8; i2++) {
179808
- if (SHELL_NAMES2.some((name) => existsSync85(join93(dir, shellAppDir(name), "package.json")))) return dir;
180048
+ if (SHELL_NAMES2.some((name) => existsSync86(join93(dir, shellAppDir(name), "package.json")))) return dir;
179809
180049
  const next = dirname50(dir);
179810
180050
  if (next === dir) break;
179811
180051
  dir = next;
@@ -179909,7 +180149,7 @@ function sameKnownSite(previous, next) {
179909
180149
  function buildMergedContract(options) {
179910
180150
  const { appDir: appDir3, packageDir, overlay } = options;
179911
180151
  const committedPath = join93(appDir3, "provisioning.json");
179912
- if (!existsSync85(committedPath)) {
180152
+ if (!existsSync86(committedPath)) {
179913
180153
  throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
179914
180154
  }
179915
180155
  const committed = JSON.parse(readFileSync106(committedPath, "utf8"));
@@ -179925,7 +180165,7 @@ function buildMergedContract(options) {
179925
180165
  const stage = (fromRel, toRel) => {
179926
180166
  const from = contained(packageDir, fromRel);
179927
180167
  const to2 = contained(join93(appDir3, STAGED), toRel.slice(STAGED.length + 1));
179928
- if (!from || !to2 || !existsSync85(from)) return void 0;
180168
+ if (!from || !to2 || !existsSync86(from)) return void 0;
179929
180169
  let real;
179930
180170
  let realRoot;
179931
180171
  try {
@@ -179937,7 +180177,7 @@ function buildMergedContract(options) {
179937
180177
  if (!real.startsWith(realRoot + sep20)) return void 0;
179938
180178
  try {
179939
180179
  if (!statSync22(real).isFile()) return void 0;
179940
- mkdirSync43(dirname50(to2), { recursive: true });
180180
+ mkdirSync44(dirname50(to2), { recursive: true });
179941
180181
  copyFileSync2(real, to2);
179942
180182
  } catch {
179943
180183
  return void 0;
@@ -179948,7 +180188,7 @@ function buildMergedContract(options) {
179948
180188
  const icon = stage("media/icon.png", `${STAGED}/icon.png`);
179949
180189
  if (icon) branding.appIconPath = icon;
179950
180190
  const facesPath = join93(packageDir, "media/fonts/faces.json");
179951
- if (existsSync85(facesPath)) {
180191
+ if (existsSync86(facesPath)) {
179952
180192
  let faces = [];
179953
180193
  try {
179954
180194
  const parsed = JSON.parse(readFileSync106(facesPath, "utf8"));
@@ -179975,7 +180215,7 @@ function buildMergedContract(options) {
179975
180215
  const path2 = join93(packageDir, "provisioning.contract.json");
179976
180216
  writeFileSync42(path2, body);
179977
180217
  const localPath2 = join93(appDir3, LOCAL_CONTRACT_REL);
179978
- mkdirSync43(dirname50(localPath2), { recursive: true });
180218
+ mkdirSync44(dirname50(localPath2), { recursive: true });
179979
180219
  writeFileSync42(localPath2, body);
179980
180220
  staged.push(localPath2);
179981
180221
  return { path: path2, staged };
@@ -180010,7 +180250,7 @@ function staticFaqFor(overlay, overlayPath) {
180010
180250
  const own5 = overlay.faq;
180011
180251
  if (own5 !== void 0) return deriveStaticFaq(own5);
180012
180252
  const bookPath = join93(dirname50(resolve63(overlayPath)), "book.json");
180013
- if (!existsSync85(bookPath)) return void 0;
180253
+ if (!existsSync86(bookPath)) return void 0;
180014
180254
  try {
180015
180255
  const book = JSON.parse(readFileSync106(bookPath, "utf8"));
180016
180256
  const copy = book?.copy;
@@ -180027,7 +180267,7 @@ function staticGalleriesFor(overlay, overlayPath) {
180027
180267
  overlay.galleries.map((gallery) => ({ role: "gallery", title: gallery.title, galleryImageUrls: gallery.photos }))
180028
180268
  );
180029
180269
  const bookPath = join93(dirname50(resolve63(overlayPath)), "book.json");
180030
- if (!existsSync85(bookPath)) return void 0;
180270
+ if (!existsSync86(bookPath)) return void 0;
180031
180271
  try {
180032
180272
  const book = JSON.parse(readFileSync106(bookPath, "utf8"));
180033
180273
  if (!book.look || book.look.unavailable || !Array.isArray(book.look.pages)) return void 0;
@@ -180061,7 +180301,7 @@ async function applyOverlays(input) {
180061
180301
  }
180062
180302
  const appDir3 = join93(repoRoot2, shellAppDir(shell));
180063
180303
  const committedPath = join93(appDir3, "provisioning.json");
180064
- const committedSite = existsSync85(committedPath) ? JSON.parse(readFileSync106(committedPath, "utf8")).site : void 0;
180304
+ const committedSite = existsSync86(committedPath) ? JSON.parse(readFileSync106(committedPath, "utf8")).site : void 0;
180065
180305
  if (committedSite !== void 0 && overlay.site === void 0) {
180066
180306
  throw new Error(
180067
180307
  `shell "${shell}" is a site shell: its contract names the customer's website (a \`site\` block), and this overlay has none. Re-run \`himi site analyze --url <site> --shell ${shell}\` to derive the site's page map (edit \`site.pages\` in provisioning.overlay.json if needed), then --apply.`
@@ -180102,7 +180342,7 @@ async function applyOverlays(input) {
180102
180342
  };
180103
180343
  let packageFaq = faq;
180104
180344
  let packageGalleries = galleries;
180105
- if (existsSync85(pkgProv)) {
180345
+ if (existsSync86(pkgProv)) {
180106
180346
  const cur = JSON.parse(readFileSync106(pkgProv, "utf8"));
180107
180347
  if (galleries === void 0 && !sameKnownSite(cur, overlay)) overlay.galleries = [];
180108
180348
  const merged = deepMerge4(cur, overlay);
@@ -180120,7 +180360,7 @@ async function applyOverlays(input) {
180120
180360
  overlay.installedVerticals.push("galleries");
180121
180361
  }
180122
180362
  const pkgTokens = join93(cwd, "tokens.json");
180123
- if (existsSync85(pkgTokens) && (tokens2.colors || tokens2.typography)) {
180363
+ if (existsSync86(pkgTokens) && (tokens2.colors || tokens2.typography)) {
180124
180364
  const cur = JSON.parse(readFileSync106(pkgTokens, "utf8"));
180125
180365
  let tokensIn = tokens2;
180126
180366
  if (tokens2.typography) {
@@ -180147,7 +180387,7 @@ async function applyOverlays(input) {
180147
180387
  }
180148
180388
  const homeAction = homeRefreshActionId(shell);
180149
180389
  const homeSrc = join93(cwd, "dev/index.ts");
180150
- if (homeAction && existsSync85(homeSrc)) {
180390
+ if (homeAction && existsSync86(homeSrc)) {
180151
180391
  const prev = readFileSync106(homeSrc, "utf8");
180152
180392
  const patched = patchBrandParams(prev, overlay, homeAction);
180153
180393
  let next = patched.src;
@@ -180183,13 +180423,13 @@ async function applyOverlays(input) {
180183
180423
  notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
180184
180424
  }
180185
180425
  }
180186
- if (!input.iconPath || !existsSync85(input.iconPath)) {
180426
+ if (!input.iconPath || !existsSync86(input.iconPath)) {
180187
180427
  const book = input.iconPath ? dirname50(dirname50(resolve63(input.iconPath))) : void 0;
180188
180428
  notes.push(
180189
180429
  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"
180190
180430
  );
180191
180431
  }
180192
- if (input.iconPath && existsSync85(input.iconPath)) {
180432
+ if (input.iconPath && existsSync86(input.iconPath)) {
180193
180433
  try {
180194
180434
  const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
180195
180435
  wrote.push(...installed.wrote);
@@ -181148,7 +181388,7 @@ __export(cli_exports3, {
181148
181388
  runSiteAnalyze: () => runSiteAnalyze,
181149
181389
  runSiteFunctionCli: () => runSiteFunctionCli
181150
181390
  });
181151
- import { existsSync as existsSync86, readFileSync as readFileSync107 } from "node:fs";
181391
+ import { existsSync as existsSync87, readFileSync as readFileSync107 } from "node:fs";
181152
181392
  import { resolve as resolve64 } from "node:path";
181153
181393
  function applyNeedsClient(shell) {
181154
181394
  if (shell === void 0 || !SHELL_NAMES2.includes(shell)) return true;
@@ -181216,7 +181456,7 @@ async function runSiteAnalyze(opts) {
181216
181456
  if (book?.skipped) result.warnings = [...result.warnings ?? [], book.skipped];
181217
181457
  const derived = deriveSiteShell({ siteUrl: result.book.input.siteUrl, look: result.book.look, kind, routes });
181218
181458
  const prevOverlayPath = resolve64(outDir, "provisioning.overlay.json");
181219
- const prevSite = existsSync86(prevOverlayPath) ? (() => {
181459
+ const prevSite = existsSync87(prevOverlayPath) ? (() => {
181220
181460
  try {
181221
181461
  return JSON.parse(readFileSync107(prevOverlayPath, "utf8")).site;
181222
181462
  } catch {
@@ -181237,7 +181477,7 @@ async function runSiteAnalyze(opts) {
181237
181477
  }
181238
181478
  const previousOverlay = resolve64(outDir, "provisioning.overlay.json");
181239
181479
  carryOverGoals(
181240
- existsSync86(previousOverlay) ? readFileSync107(previousOverlay, "utf8") : void 0,
181480
+ existsSync87(previousOverlay) ? readFileSync107(previousOverlay, "utf8") : void 0,
181241
181481
  result.provisioningOverlay
181242
181482
  );
181243
181483
  const ownerCall = ownerAuth ? ownerTransportFrom(fetchImpl, ownerAuth) : void 0;
@@ -181323,7 +181563,7 @@ async function runSiteFunctionCli(opts) {
181323
181563
  });
181324
181564
  }
181325
181565
  function base44BookRoutes(bookPath, siteUrl) {
181326
- if (!existsSync86(bookPath)) return void 0;
181566
+ if (!existsSync87(bookPath)) return void 0;
181327
181567
  try {
181328
181568
  const book = JSON.parse(readFileSync107(bookPath, "utf8"));
181329
181569
  if (book.kind !== "base44-app-book" || !Array.isArray(book.routes)) return void 0;
@@ -181580,7 +181820,7 @@ __export(site_create_exports, {
181580
181820
  runSiteList: () => runSiteList,
181581
181821
  writeProvisioningBinding: () => writeProvisioningBinding
181582
181822
  });
181583
- import { existsSync as existsSync87, readFileSync as readFileSync108, writeFileSync as writeFileSync43 } from "node:fs";
181823
+ import { existsSync as existsSync88, readFileSync as readFileSync108, writeFileSync as writeFileSync43 } from "node:fs";
181584
181824
  import { resolve as resolvePath2 } from "node:path";
181585
181825
  function oauthClientName(projectName) {
181586
181826
  return `${projectName} client`;
@@ -181729,7 +181969,7 @@ async function runSiteCreate(opts) {
181729
181969
  if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
181730
181970
  return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
181731
181971
  }
181732
- function writeProvisioningBinding(target, binding2, fs2 = { existsSync: existsSync87, readFileSync: readFileSync108, writeFileSync: writeFileSync43 }) {
181972
+ function writeProvisioningBinding(target, binding2, fs2 = { existsSync: existsSync88, readFileSync: readFileSync108, writeFileSync: writeFileSync43 }) {
181733
181973
  const msid = binding2.siteId;
181734
181974
  const path2 = resolvePath2(target);
181735
181975
  const committed = committedShellProvisioning(path2);
@@ -182426,13 +182666,13 @@ var init_context = __esm({
182426
182666
  });
182427
182667
 
182428
182668
  // src/cli.ts
182429
- import { mkdtempSync as mkdtempSync6, readFileSync as readFileSync109, mkdirSync as mkdirSync44, writeFileSync as writeFileSync44, existsSync as existsSync88, rmSync as rmSync24, readdirSync as readdirSync36, statSync as statSync23, lstatSync as lstatSync23, accessSync, constants as constants5, renameSync as renameSync13, cpSync as cpSync3 } from "node:fs";
182669
+ import { mkdtempSync as mkdtempSync6, readFileSync as readFileSync109, mkdirSync as mkdirSync45, writeFileSync as writeFileSync44, existsSync as existsSync89, rmSync as rmSync24, readdirSync as readdirSync36, statSync as statSync23, lstatSync as lstatSync23, accessSync, constants as constants5, renameSync as renameSync13, cpSync as cpSync3 } from "node:fs";
182430
182670
  import { execFile as execFile2, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn7 } from "node:child_process";
182431
182671
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
182432
182672
  import { createHash as createHash46, randomUUID as randomUUID11 } from "node:crypto";
182433
- import { tmpdir as tmpdir7, homedir as homedir14, hostname as hostname2 } from "node:os";
182673
+ import { tmpdir as tmpdir7, homedir as homedir15, hostname as hostname2 } from "node:os";
182434
182674
  import { join as join94, resolve as resolve65, relative as relative16, basename as basename21, dirname as dirname51 } from "node:path";
182435
- import { fileURLToPath as fileURLToPath29 } from "node:url";
182675
+ import { fileURLToPath as fileURLToPath30 } from "node:url";
182436
182676
 
182437
182677
  // ../serve-cli/src/client.ts
182438
182678
  import { gzipSync } from "node:zlib";
@@ -185491,7 +185731,7 @@ function createScopedRegistryResolver(exec = execNpmConfig) {
185491
185731
  const configured = async (key3) => {
185492
185732
  const timeout = deadline - Date.now();
185493
185733
  if (timeout <= 0) throw new Error("npm config: out of budget");
185494
- const raw = String(await exec("npm", ["config", "get", key3], { cwd: homedir14(), timeout })).trim();
185734
+ const raw = String(await exec("npm", ["config", "get", key3], { cwd: homedir15(), timeout })).trim();
185495
185735
  return raw && raw !== "undefined" ? raw : void 0;
185496
185736
  };
185497
185737
  const effective = normalizeRegistry(await configured("@wix:registry") ?? await configured("registry"));
@@ -185644,7 +185884,7 @@ var UPDATE_RETRY_AFTER_FAILURE_MS = 60 * 60 * 1e3;
185644
185884
  var UPDATE_SNOOZE_MS = 24 * 60 * 60 * 1e3;
185645
185885
  var UPDATE_REEXEC_ENV = "HIMI_UPDATED_ONCE";
185646
185886
  function updateCachePath(env = process.env) {
185647
- return env.HIMI_UPDATE_CACHE_FILE ?? join94(homedir14(), ".himalaya", "update-check.json");
185887
+ return env.HIMI_UPDATE_CACHE_FILE ?? join94(homedir15(), ".himalaya", "update-check.json");
185648
185888
  }
185649
185889
  function readUpdateCache(path2) {
185650
185890
  try {
@@ -185656,7 +185896,7 @@ function readUpdateCache(path2) {
185656
185896
  }
185657
185897
  function writeUpdateCache(path2, cache) {
185658
185898
  try {
185659
- mkdirSync44(dirname51(path2), { recursive: true, mode: 448 });
185899
+ mkdirSync45(dirname51(path2), { recursive: true, mode: 448 });
185660
185900
  writeFileSync44(path2, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
185661
185901
  } catch {
185662
185902
  }
@@ -185710,7 +185950,7 @@ function createUpdateRunner(spawn8 = spawnSync5) {
185710
185950
  // parse — the agent case this whole feature exists for (#2985 review). And no stdin: an
185711
185951
  // install needs none, and must not consume input piped to the command we are about to re-run.
185712
185952
  stdio: ["ignore", 2, 2],
185713
- cwd: homedir14()
185953
+ cwd: homedir15()
185714
185954
  });
185715
185955
  if (result.error) return { ok: false, detail: result.error.message };
185716
185956
  return result.status === 0 ? { ok: true } : { ok: false, detail: `npm exited ${result.status}` };
@@ -185722,7 +185962,7 @@ function createUpdateRunner(spawn8 = spawnSync5) {
185722
185962
  reexec: (argv) => {
185723
185963
  const root = globalNodeModulesRoot();
185724
185964
  const entry = root ? join94(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
185725
- if (!entry || !existsSync88(entry)) return void 0;
185965
+ if (!entry || !existsSync89(entry)) return void 0;
185726
185966
  const result = spawnSync5(process.execPath, [entry, ...argv], {
185727
185967
  // inherit keeps PIPED STDIN working — commands that read stdin must survive a re-exec.
185728
185968
  stdio: "inherit",
@@ -185813,7 +186053,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
185813
186053
  };
185814
186054
  const release2 = () => removeIfMine(lockPath);
185815
186055
  try {
185816
- mkdirSync44(dirname51(lockPath), { recursive: true, mode: 448 });
186056
+ mkdirSync45(dirname51(lockPath), { recursive: true, mode: 448 });
185817
186057
  } catch {
185818
186058
  return () => {
185819
186059
  };
@@ -185880,10 +186120,10 @@ function supersededInCache(current, latest, now) {
185880
186120
  function createUpdateRefreshSpawner(spawnFn = spawn7, execArgv = process.execArgv) {
185881
186121
  return () => {
185882
186122
  try {
185883
- const child = spawnFn(process.execPath, [...loaderArgs(execArgv), fileURLToPath29(import.meta.url), UPDATE_REFRESH_COMMAND], {
186123
+ const child = spawnFn(process.execPath, [...loaderArgs(execArgv), fileURLToPath30(import.meta.url), UPDATE_REFRESH_COMMAND], {
185884
186124
  detached: true,
185885
186125
  stdio: "ignore",
185886
- cwd: homedir14(),
186126
+ cwd: homedir15(),
185887
186127
  env: process.env
185888
186128
  });
185889
186129
  child.on("error", () => {
@@ -185935,7 +186175,7 @@ function createTrimValidator(deps = {}, spawnFn = spawn7) {
185935
186175
  }
185936
186176
  const { code, stdout, stderr } = await new Promise((done) => {
185937
186177
  const chunks = { out: [], err: [] };
185938
- const child = spawnFn(process.execPath, [...loaderArgs(process.execArgv), fileURLToPath29(import.meta.url), ...argv], {
186178
+ const child = spawnFn(process.execPath, [...loaderArgs(process.execArgv), fileURLToPath30(import.meta.url), ...argv], {
185939
186179
  cwd: process.cwd(),
185940
186180
  env: process.env,
185941
186181
  stdio: ["ignore", "pipe", "pipe"]
@@ -186493,7 +186733,7 @@ async function nativeConfigAdvisories(app, configSource) {
186493
186733
  const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths2(), paths_exports));
186494
186734
  const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
186495
186735
  const iosYmlPath = iosProjectYml2(app);
186496
- const iosYml = existsSync88(iosYmlPath) ? readFileSync109(iosYmlPath, "utf8") : "";
186736
+ const iosYml = existsSync89(iosYmlPath) ? readFileSync109(iosYmlPath, "utf8") : "";
186497
186737
  let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
186498
186738
  if (!optedIn) {
186499
186739
  const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
@@ -186513,7 +186753,7 @@ function readConfigSource(dir) {
186513
186753
  }
186514
186754
  }
186515
186755
  function writePngFile(path2, base64) {
186516
- mkdirSync44(dirname51(path2), { recursive: true });
186756
+ mkdirSync45(dirname51(path2), { recursive: true });
186517
186757
  writeFileSync44(path2, Buffer.from(base64, "base64"));
186518
186758
  return path2;
186519
186759
  }
@@ -186561,7 +186801,7 @@ var NoBase44SlotError = class extends Error {
186561
186801
  };
186562
186802
  async function initFromRemoteTemplate(name, parentDir, template, c2, opts = {}) {
186563
186803
  const dir = resolve65(parentDir, name);
186564
- if (existsSync88(join94(dir, "himalaya.content.json"))) {
186804
+ if (existsSync89(join94(dir, "himalaya.content.json"))) {
186565
186805
  throw new Error(`content package already exists at ${dir}`);
186566
186806
  }
186567
186807
  const r2 = await c2.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
@@ -186607,7 +186847,7 @@ function symlinkDestinationIssue(dest) {
186607
186847
  function restoreDestinationIssue(dest, force) {
186608
186848
  const link = symlinkDestinationIssue(dest);
186609
186849
  if (link) return link;
186610
- if (!existsSync88(dest)) return null;
186850
+ if (!existsSync89(dest)) return null;
186611
186851
  if (!statSync23(dest).isDirectory()) {
186612
186852
  return { error: `${dest} exists and is not a directory`, hint: "pass --out/--name to land somewhere else, or remove the file" };
186613
186853
  }
@@ -186622,7 +186862,7 @@ function restoreDestinationIssue(dest, force) {
186622
186862
  function isHimalayaMonorepoCheckout(start) {
186623
186863
  let dir = resolve65(start);
186624
186864
  for (; ; ) {
186625
- if (existsSync88(join94(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync88(join94(dir, "core", "serve", "src", "server.ts"))) return true;
186865
+ if (existsSync89(join94(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync89(join94(dir, "core", "serve", "src", "server.ts"))) return true;
186626
186866
  const parent = dirname51(dir);
186627
186867
  if (parent === dir) return false;
186628
186868
  dir = parent;
@@ -186682,7 +186922,7 @@ function materializeForPreview(appDir3, slug, displayName3) {
186682
186922
  const forBuild = Object.fromEntries(
186683
186923
  Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
186684
186924
  );
186685
- const repoRoot2 = resolve65(fileURLToPath29(new URL("../../..", import.meta.url)));
186925
+ const repoRoot2 = resolve65(fileURLToPath30(new URL("../../..", import.meta.url)));
186686
186926
  const root = join94(repoRoot2, "node_modules", ".cache", "himi-template-preview");
186687
186927
  const stillRunning = (pid) => {
186688
186928
  try {
@@ -186704,7 +186944,7 @@ function materializeForPreview(appDir3, slug, displayName3) {
186704
186944
  }
186705
186945
  const dest = join94(root, `${slug}-${process.pid}`);
186706
186946
  rmSync24(dest, { recursive: true, force: true });
186707
- mkdirSync44(dest, { recursive: true });
186947
+ mkdirSync45(dest, { recursive: true });
186708
186948
  try {
186709
186949
  materializeSource(forBuild, displayName3, dest, slug);
186710
186950
  } catch (e2) {
@@ -187017,7 +187257,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
187017
187257
  ...res.removed.length ? { removed: res.removed, note: "older copies at the app root, moved to .himi/legacy-agent-files/ (a backup, in case one became app code) \u2014 the current ones live in .agents/skills/himalaya/" } : {},
187018
187258
  // In a git repo the refresh moves the diff identity an earlier `himi test` attested (that
187019
187259
  // hash is shared with the repo gates and deliberately exempts nothing but its own metadata).
187020
- ...existsSync88(join94(dir, ".himi", "attestations", "latest.json")) ? { next: "if `himi push` then refuses the attestation as stale, re-run `himi test` \u2014 in a git checkout this refresh changed the tree it covered" } : {},
187260
+ ...existsSync89(join94(dir, ".himi", "attestations", "latest.json")) ? { next: "if `himi push` then refuses the attestation as stale, re-run `himi test` \u2014 in a git checkout this refresh changed the tree it covered" } : {},
187021
187261
  ...res.skipped.length ? { skipped: res.skipped } : {},
187022
187262
  portalUrl: idx.portalUrl
187023
187263
  });
@@ -187028,8 +187268,6 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
187028
187268
  return 2;
187029
187269
  }
187030
187270
  }
187031
- var AuthoringUnavailable = class extends Error {
187032
- };
187033
187271
  function resolutionFlag(flags) {
187034
187272
  if (flags.binary === true) return "node_modules";
187035
187273
  if (flags.source === true) return "source";
@@ -187150,16 +187388,17 @@ function uxHandoverOverride(uxEvidence, ctx) {
187150
187388
  return { uxEvidence, uxEvidenceNote: uxHandoverNote(uxEvidence, ctx) };
187151
187389
  }
187152
187390
  async function loadAuthoring() {
187391
+ const { AuthoringUnavailable: AuthoringUnavailable2, namedAuthoringImport: namedAuthoringImport2 } = await Promise.resolve().then(() => (init_authoring_unavailable(), authoring_unavailable_exports));
187153
187392
  try {
187154
187393
  const [b2, rb, crawl, vd, cov, wml, nf2, rd] = await Promise.all([
187155
- Promise.resolve().then(() => (init_build(), build_exports)),
187156
- Promise.resolve().then(() => (init_build3(), build_exports2)),
187157
- Promise.resolve().then(() => (init_screen_crawl(), screen_crawl_exports)),
187158
- Promise.resolve().then(() => (init_validate_descriptor(), validate_descriptor_exports)),
187159
- Promise.resolve().then(() => (init_vm_coverage(), vm_coverage_exports)),
187160
- Promise.resolve().then(() => (init_wix_member_login(), wix_member_login_exports)),
187161
- Promise.resolve().then(() => (init_net_freeze(), net_freeze_exports)),
187162
- Promise.resolve().then(() => (init_render_descriptor(), render_descriptor_exports))
187394
+ namedAuthoringImport2("./build.js", Promise.resolve().then(() => (init_build(), build_exports))),
187395
+ namedAuthoringImport2("../../release-build/build.js", Promise.resolve().then(() => (init_build3(), build_exports2))),
187396
+ namedAuthoringImport2("../../../core/dev-server/src/screen-crawl.js", Promise.resolve().then(() => (init_screen_crawl(), screen_crawl_exports))),
187397
+ namedAuthoringImport2("../../../core/dev-server/src/validate-descriptor.js", Promise.resolve().then(() => (init_validate_descriptor(), validate_descriptor_exports))),
187398
+ namedAuthoringImport2("../../../core/dev-server/src/vm-coverage.js", Promise.resolve().then(() => (init_vm_coverage(), vm_coverage_exports))),
187399
+ namedAuthoringImport2("../../../core/dev-server/src/wix-member-login.js", Promise.resolve().then(() => (init_wix_member_login(), wix_member_login_exports))),
187400
+ namedAuthoringImport2("../../../core/dev-server/src/net-freeze.js", Promise.resolve().then(() => (init_net_freeze(), net_freeze_exports))),
187401
+ namedAuthoringImport2("../../../core/dev-server/src/render-descriptor.js", Promise.resolve().then(() => (init_render_descriptor(), render_descriptor_exports)))
187163
187402
  ]);
187164
187403
  return {
187165
187404
  buildContentBundles: b2.buildContentBundles,
@@ -187189,8 +187428,9 @@ async function loadAuthoring() {
187189
187428
  readBuiltBundle: vd.readBuiltBundle,
187190
187429
  crawlBlockingPasses: vd.CRAWL_BLOCKING_PASSES
187191
187430
  };
187192
- } catch {
187193
- throw new AuthoringUnavailable();
187431
+ } catch (cause) {
187432
+ if (cause instanceof AuthoringUnavailable2) throw cause;
187433
+ throw new AuthoringUnavailable2({ cause });
187194
187434
  }
187195
187435
  }
187196
187436
  async function producedWidgetFamilies(dir) {
@@ -187250,7 +187490,7 @@ async function producedWidgetFamilies(dir) {
187250
187490
  }
187251
187491
  return { families, source: "dist/bundles" };
187252
187492
  }
187253
- var boardOpen = (dir) => existsSync88(join94(dir, ".himi", "studio", "index.html"));
187493
+ var boardOpen = (dir) => existsSync89(join94(dir, ".himi", "studio", "index.html"));
187254
187494
  var BOARD_REFRESHERS = /* @__PURE__ */ new Set(["render", "test", "validate", "build", "push", "icon", "site", "ux", "progress"]);
187255
187495
  async function leaveForBoard(dir, record2, value) {
187256
187496
  if (!boardOpen(dir)) return;
@@ -187628,7 +187868,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
187628
187868
  const owed = openApprovals2(readApprovals2(dir).events).length;
187629
187869
  next.push(`carried the planning journal into the app (${carried.join(", ")}${owed ? `; ${owed} approval${owed === 1 ? "" : "s"} still owed` : ""}) \u2014 \`himi progress --brief\` there shows it`);
187630
187870
  }
187631
- const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f2) => existsSync88(join94(parentDir, f2)));
187871
+ const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f2) => existsSync89(join94(parentDir, f2)));
187632
187872
  if (planInParent.length) {
187633
187873
  next.push(`${planInParent.join(" and ")} in ${parentDir} ${planInParent.length > 1 ? "are" : "is"} not the app's \u2014 if that is the approved plan, move it over the template's boilerplate in ${dir}`);
187634
187874
  }
@@ -187639,12 +187879,12 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
187639
187879
  const board = await openBoardForSession2(dir);
187640
187880
  const home = homeScreenIdOf2(dir);
187641
187881
  recordInitSource2(dir, { template: template ?? null, source });
187642
- const firstLook = flags["no-first-look"] === true ? { skipped: "--no-first-look" } : await firstLookAtInit2(dir, { source, home, entry: fileURLToPath29(import.meta.url), loader: loaderArgs(process.execArgv) });
187882
+ const firstLook = flags["no-first-look"] === true ? { skipped: "--no-first-look" } : await firstLookAtInit2(dir, { source, home, entry: fileURLToPath30(import.meta.url), loader: loaderArgs(process.execArgv) });
187643
187883
  const pictured = "image" in firstLook;
187644
187884
  const watch2 = await startWatchAtInit2(dir, {
187645
187885
  source,
187646
187886
  app: await appId(dir),
187647
- entry: fileURLToPath29(import.meta.url),
187887
+ entry: fileURLToPath30(import.meta.url),
187648
187888
  loader: loaderArgs(process.execArgv),
187649
187889
  noWatch: flags["no-watch"] === true
187650
187890
  });
@@ -187918,7 +188158,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
187918
188158
  const result = { ...outcome.result, ...fromSpec };
187919
188159
  const adoptDir = contentDir(flags);
187920
188160
  const kept = flags["dry-run"] !== true && (outcome.code === 0 || outcome.result.forcedKeep === true);
187921
- if (kept && existsSync88(join94(adoptDir, adoptBits.ADOPT_FILE))) {
188161
+ if (kept && existsSync89(join94(adoptDir, adoptBits.ADOPT_FILE))) {
187922
188162
  try {
187923
188163
  const inv = adoptBits.inspectApp(adoptDir);
187924
188164
  adoptBits.writeInventory(adoptDir, inv, { companions: "if-missing" });
@@ -188331,7 +188571,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
188331
188571
  const homePicture = await homePictureAtValidate2(dir, {
188332
188572
  ok: !hasErrors,
188333
188573
  home: outcome.homeScreenId,
188334
- entry: fileURLToPath29(import.meta.url),
188574
+ entry: fileURLToPath30(import.meta.url),
188335
188575
  loader: loaderArgs(process.execArgv)
188336
188576
  });
188337
188577
  const { postcard: picturePostcard, ...picture } = homePicture;
@@ -188476,7 +188716,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
188476
188716
  const dir2 = resolve65(out2);
188477
188717
  const files2 = himiStudioPluginFiles2();
188478
188718
  for (const f2 of files2) {
188479
- mkdirSync44(dirname51(join94(dir2, f2.path)), { recursive: true });
188719
+ mkdirSync45(dirname51(join94(dir2, f2.path)), { recursive: true });
188480
188720
  writeFileSync44(join94(dir2, f2.path), f2.text);
188481
188721
  }
188482
188722
  print({ ok: true, dir: dir2, files: files2.map((f2) => f2.path), next: [`claude plugin validate ${dir2}`, `claude --plugin-dir ${dir2}`] });
@@ -188492,7 +188732,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
188492
188732
  const dir = resolve65(out2);
188493
188733
  const files = himiPluginFiles2(skills.skillMd);
188494
188734
  for (const f2 of files) {
188495
- mkdirSync44(dirname51(join94(dir, f2.path)), { recursive: true });
188735
+ mkdirSync45(dirname51(join94(dir, f2.path)), { recursive: true });
188496
188736
  writeFileSync44(join94(dir, f2.path), f2.text);
188497
188737
  }
188498
188738
  print({ ok: true, dir, files: files.map((f2) => f2.path), next: [`claude plugin validate ${dir}`, `claude --plugin-dir ${dir}`] });
@@ -188510,7 +188750,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
188510
188750
  case "studio": {
188511
188751
  const { openStudio: openStudio2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
188512
188752
  const dir = contentDir(flags);
188513
- if (!existsSync88(join94(dir, "himalaya.content.json"))) {
188753
+ if (!existsSync89(join94(dir, "himalaya.content.json"))) {
188514
188754
  io2.error(JSON.stringify({ ok: false, error: "not_a_content_package", dir, hint: "run from the app directory (or pass --content <dir>) \u2014 the board reads that package's .himi/" }));
188515
188755
  return 2;
188516
188756
  }
@@ -188518,7 +188758,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
188518
188758
  const { buildReel: buildReel2 } = await Promise.resolve().then(() => (init_studio_reel(), studio_reel_exports));
188519
188759
  const out2 = resolve65(str10(flags.out) ?? join94(dir, ".himi", "making-of.html"));
188520
188760
  const { html, plan } = buildReel2(dir);
188521
- mkdirSync44(dirname51(out2), { recursive: true });
188761
+ mkdirSync45(dirname51(out2), { recursive: true });
188522
188762
  writeFileSync44(out2, html);
188523
188763
  const { pathToFileURL: pathToFileURL9 } = await import("node:url");
188524
188764
  const url2 = pathToFileURL9(out2).href;
@@ -188588,7 +188828,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
188588
188828
  } = await Promise.resolve().then(() => (init_progress(), progress_exports));
188589
188829
  const dir = contentDir(flags);
188590
188830
  const journal2 = journalPath2(dir);
188591
- const isContentPackage = existsSync88(join94(dir, "himalaya.content.json"));
188831
+ const isContentPackage = existsSync89(join94(dir, "himalaya.content.json"));
188592
188832
  const hint = isContentPackage ? {} : { hint: "no himalaya.content.json here \u2014 run from the app directory (or pass --content <dir>) so the build board finds this journal" };
188593
188833
  const message = pos.slice(1).join(" ").trim();
188594
188834
  const approvalFlags = ["approve", "done", "drop"].filter((f2) => flags[f2] !== void 0);
@@ -188740,7 +188980,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
188740
188980
  case "test": {
188741
188981
  const dir = contentDir(flags);
188742
188982
  const structuredOutput = flags.json === true || io2.isTTY !== true;
188743
- if (existsSync88(join94(dir, "functions"))) {
188983
+ if (existsSync89(join94(dir, "functions"))) {
188744
188984
  const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
188745
188985
  const loaded = await loadFunctionsApp2(dir);
188746
188986
  const results = [];
@@ -188877,8 +189117,8 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
188877
189117
  io2.error(JSON.stringify({ error: `no worker source found at tier5-src/${screen.bundleName} \u2014 the browser loop compiles SOURCE, not the built bundle` }));
188878
189118
  return 2;
188879
189119
  }
188880
- const { fileURLToPath: fileURLToPath30 } = await import("node:url");
188881
- const sdk = collectSdkModules2(sources.files, sdkSubpathReader2((s2) => fileURLToPath30(import.meta.resolve(s2))));
189120
+ const { fileURLToPath: fileURLToPath31 } = await import("node:url");
189121
+ const sdk = collectSdkModules2(sources.files, sdkSubpathReader2((s2) => fileURLToPath31(import.meta.resolve(s2))));
188882
189122
  if (sdk.unsupported.length) {
188883
189123
  io2.error(JSON.stringify({
188884
189124
  error: `this worker imports ${sdk.unsupported.map((u2) => `@himalaya/${u2.sub}`).join(", ")}, which the browser loop cannot build: ${sdk.unsupported.map((u2) => `${u2.sub} needs ${u2.builtin}`).join("; ")}. The page compiles in a tab with no node builtins. Run \`himi test\` without --browser for this screen.`,
@@ -189020,21 +189260,20 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
189020
189260
  io2.error(JSON.stringify({ error: e2.message }));
189021
189261
  return 2;
189022
189262
  }
189263
+ const release2 = await loadReleaseFromDir(app, out2);
189023
189264
  if (nativeAvailabilities.length > 0) {
189024
- const { runAndroidNativeDecode: runAndroidNativeDecode2, runNativeDecode: runNativeDecode2, mergeNativeDecode: mergeNativeDecode2 } = await Promise.resolve().then(() => (init_native_decode(), native_decode_exports));
189265
+ const { runAndroidNativeDecode: runAndroidNativeDecode2, runNativeDecode: runNativeDecode2, mergeNativeDecode: mergeNativeDecode2, markNativeSkipped: markNativeSkipped2 } = await Promise.resolve().then(() => (init_native_decode(), native_decode_exports));
189025
189266
  const descriptors = scopeDescriptors2(outcome.descriptors ?? [], pos.slice(1), invalidScreens);
189267
+ const tokensJson = release2.tokens;
189026
189268
  for (const availability of nativeAvailabilities) {
189027
189269
  if (!availability.available) {
189028
- result.nativeDecode = {
189029
- ...result.nativeDecode,
189030
- [availability.platform]: { unavailable: true, reason: availability.reason },
189031
- wallMs: result.nativeDecode?.wallMs ?? 0
189032
- };
189270
+ result = markNativeSkipped2(result, availability);
189271
+ io2.error(`[native ${availability.platform}] SKIPPED \u2014 not checked: ${availability.reason}`);
189033
189272
  continue;
189034
189273
  }
189035
189274
  try {
189036
189275
  const progress = (message) => io2.error(`[native ${availability.platform} ${(/* @__PURE__ */ new Date()).toISOString()}] ${message}`);
189037
- const nativeRun = availability.platform === "ios" ? runNativeDecode2({ descriptors, packageDir: availability.packageDir, progress }) : runAndroidNativeDecode2({ descriptors, harnessDir: availability.harnessDir, gradlew: availability.gradlew, progress });
189276
+ const nativeRun = availability.platform === "ios" ? runNativeDecode2({ descriptors, tokensJson, packageDir: availability.packageDir, progress }) : runAndroidNativeDecode2({ descriptors, tokensJson, harnessDir: availability.harnessDir, gradlew: availability.gradlew, sdkDir: availability.sdkDir, progress });
189038
189277
  result = mergeNativeDecode2(result, nativeRun);
189039
189278
  } catch (error) {
189040
189279
  io2.error(JSON.stringify({ error: error.message }));
@@ -189078,7 +189317,6 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
189078
189317
  const trend = trendAndStore2(dir, ledger, suppressedNativeKeys2(nativeOracle));
189079
189318
  const delta = diffAndStoreObservations2(dir, result.observations ?? {});
189080
189319
  const legacy = { ...result, ledger, ...trend ? { trend } : {}, ...delta ? { delta } : {}, ...recorded ? { recorded } : {} };
189081
- const release2 = await loadReleaseFromDir(app, out2);
189082
189320
  const gitDiffHash = currentGitDiffHash(dir);
189083
189321
  const crawledScreens = new Set((result.crawled ?? []).map((screen) => screen.screen));
189084
189322
  const attestedDescriptors = Object.fromEntries(
@@ -189675,7 +189913,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
189675
189913
  io2.error(JSON.stringify(linked));
189676
189914
  return 1;
189677
189915
  }
189678
- if (existsSync88(dest)) {
189916
+ if (existsSync89(dest)) {
189679
189917
  if (!statSync23(dest).isDirectory()) {
189680
189918
  io2.error(JSON.stringify({
189681
189919
  error: `${dest} exists and is not a directory`,
@@ -189688,7 +189926,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
189688
189926
  io2.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" }));
189689
189927
  return 1;
189690
189928
  }
189691
- if (replace && occupied && !existsSync88(join94(dest, "himalaya.content.json"))) {
189929
+ if (replace && occupied && !existsSync89(join94(dest, "himalaya.content.json"))) {
189692
189930
  io2.error(JSON.stringify({
189693
189931
  error: `${dest} is not a content package \u2014 refusing to --replace it`,
189694
189932
  hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
@@ -190642,7 +190880,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
190642
190880
  // ---- himi run — serve a package on localhost and open it in a browser ----
190643
190881
  // Blocks until interrupted, like any dev server.
190644
190882
  case "run": {
190645
- const { runPackage: runPackage2, lanFlagConflict: lanFlagConflict2 } = await Promise.resolve().then(() => (init_run(), run_exports));
190883
+ const { runPackage: runPackage2, lanFlagConflict: lanFlagConflict2, RUN_CONTENT_BUILD: RUN_CONTENT_BUILD2 } = await Promise.resolve().then(() => (init_run(), run_exports));
190646
190884
  const spaFlag = flags.spa;
190647
190885
  const lanConflict = lanFlagConflict2({ lan: flags.lan === true, browser: flags.browser === true, spa: typeof spaFlag === "string" || Array.isArray(spaFlag) ? String(spaFlag) : void 0 });
190648
190886
  if (lanConflict) {
@@ -190713,7 +190951,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
190713
190951
  const bres = await buildContentBundles2(dir2, { resolution: resolutionFlag(flags) });
190714
190952
  temp = mkdtempSync6(join94(tmpdir7(), "himi-run-build-"));
190715
190953
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
190716
- const initial = await buildReleaseFromContent2(dir2, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir2) } : {} });
190954
+ const initial = await buildReleaseFromContent2(dir2, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir2) } : {}, ...RUN_CONTENT_BUILD2 });
190717
190955
  servedMissing = initial.missingBundles;
190718
190956
  source = join94(temp, app);
190719
190957
  }
@@ -190841,7 +191079,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
190841
191079
  return;
190842
191080
  }
190843
191081
  const hasWorkers = bres.built.length > 0;
190844
- const outcome = await buildReleaseFromContent2(dir, next, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {}, freshModule: true });
191082
+ const outcome = await buildReleaseFromContent2(dir, next, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {}, freshModule: true, ...RUN_CONTENT_BUILD2 });
190845
191083
  const blocker = watchKit.rebuildBlocker(outcome, servedMissing);
190846
191084
  if (blocker) {
190847
191085
  await failed3(blocker);
@@ -191484,7 +191722,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
191484
191722
  io2.error(JSON.stringify({ error: `patch ${kind} needs --file`, usage: PATCH_USAGE }));
191485
191723
  return 2;
191486
191724
  }
191487
- if (!existsSync88(file2)) {
191725
+ if (!existsSync89(file2)) {
191488
191726
  io2.error(JSON.stringify({ error: `no such file: ${file2}` }));
191489
191727
  return 2;
191490
191728
  }
@@ -192038,7 +192276,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
192038
192276
  const rememberLastDist = async (jobs2) => {
192039
192277
  try {
192040
192278
  const dir = contentDir(flags);
192041
- if (!existsSync88(join94(dir, "himalaya.content.json"))) return;
192279
+ if (!existsSync89(join94(dir, "himalaya.content.json"))) return;
192042
192280
  const { lastDistFromJob: lastDistFromJob2, writeLastDist: writeLastDist2 } = await Promise.resolve().then(() => (init_capabilities(), capabilities_exports));
192043
192281
  const own5 = await appId(dir);
192044
192282
  for (const job of jobs2) {
@@ -192278,7 +192516,7 @@ ${label3}`);
192278
192516
  const platform = str10(flags.platform)?.split(",").map((p2) => p2.trim()).filter(Boolean);
192279
192517
  {
192280
192518
  const distDir = contentDir(flags);
192281
- if (existsSync88(join94(distDir, "himalaya.content.json"))) {
192519
+ if (existsSync89(join94(distDir, "himalaya.content.json"))) {
192282
192520
  const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
192283
192521
  const errors = issues.filter((i2) => i2.severity === "error");
192284
192522
  for (const i2 of issues.filter((i3) => i3.severity === "warning")) {
@@ -193329,7 +193567,7 @@ ${report3.ok ? "OK \u2014 data + serve plane reachable." : typeof report3.hint =
193329
193567
  return 1;
193330
193568
  };
193331
193569
  const gen = await Promise.resolve().then(() => (init_generate(), generate_exports));
193332
- const missing = gen.ENGINE_FILES.filter((f2) => !existsSync88(join94(dir, f2)));
193570
+ const missing = gen.ENGINE_FILES.filter((f2) => !existsSync89(join94(dir, f2)));
193333
193571
  if (missing.length) {
193334
193572
  return fail6("content_dir_not_base44_starter", `${dir} is not a base44-starter content package: the generated screens import a shared engine it does not have (${missing.join(", ")})`, { missing, hint: "scaffold one with `himi init <name> --template base44-starter --base44-app-id <id>`" });
193335
193573
  }
@@ -193415,7 +193653,7 @@ ${report3.ok ? "OK \u2014 data + serve plane reachable." : typeof report3.hint =
193415
193653
  if (!provisioning || str10(flags.content) !== void 0 || !slug) return contentDir(flags);
193416
193654
  if (!/^[a-z0-9][a-z0-9-]*$/.test(slug)) return void 0;
193417
193655
  const dir = resolve65("apps", slug);
193418
- return existsSync88(join94(dir, "config.ts")) || existsSync88(join94(dir, "config.mjs")) ? dir : void 0;
193656
+ return existsSync89(join94(dir, "config.ts")) || existsSync89(join94(dir, "config.mjs")) ? dir : void 0;
193419
193657
  };
193420
193658
  if (sub === "entities" || sub === "functions") {
193421
193659
  if (sub === "entities" && !["query", "create", "seed"].includes(pos[2] ?? "")) {
@@ -193804,13 +194042,13 @@ Code: ${userCode}`);
193804
194042
  return 2;
193805
194043
  }
193806
194044
  } catch (err) {
193807
- if (err instanceof AuthoringUnavailable) {
193808
- io2.error(JSON.stringify(pushFailure2("authoring_unavailable", {
193809
- error: `the himi authoring runtime failed to load (himi v${cliVersion()}). Off-repo this almost always means an out-of-date CLI, NOT a platform limitation \u2014 upgrade: \`npm i -g @wix/himalaya-cli@latest\`. If you meant to run in-repo, run from a monorepo checkout.`,
194045
+ if (err instanceof Error && err.name === "AuthoringUnavailable") {
194046
+ const { authoringUnavailableFields: authoringUnavailableFields2, isSourceCheckout: isSourceCheckout2 } = await Promise.resolve().then(() => (init_authoring_unavailable(), authoring_unavailable_exports));
194047
+ io2.error(JSON.stringify(pushFailure2("authoring_unavailable", authoringUnavailableFields2(err, {
193810
194048
  version: cliVersion(),
193811
- upgrade: "npm i -g @wix/himalaya-cli@latest",
193812
- portal: DEVELOPER_PORTAL_URL
193813
- })));
194049
+ portal: DEVELOPER_PORTAL_URL,
194050
+ sourceCheckout: isSourceCheckout2()
194051
+ }))));
193814
194052
  return 1;
193815
194053
  }
193816
194054
  io2.error(JSON.stringify(pushFailure2("push_failed", { error: err.message })));