@wix/himalaya-cli 0.1114.0 → 0.1115.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -1456,7 +1456,7 @@ function sentinelizeIdentity(body, identity) {
1456
1456
  }
1457
1457
  if (identity.name) {
1458
1458
  const re = new RegExp(`\\b(${NAME_FIELDS.join("|")})(["']?\\s*[:=]\\s*)(["'])${escapeRe(identity.name)}\\3`, "g");
1459
- out2 = out2.replace(re, (_m, key2, sep17, q) => `${key2}${sep17}${q}__HIMI_APP_NAME__${q}`);
1459
+ out2 = out2.replace(re, (_m, key2, sep18, q) => `${key2}${sep18}${q}__HIMI_APP_NAME__${q}`);
1460
1460
  }
1461
1461
  return out2;
1462
1462
  }
@@ -2513,14 +2513,14 @@ function commitChange(repo, base, branch, rel, body) {
2513
2513
  function runSelfTest() {
2514
2514
  let failed2 = 0;
2515
2515
  for (const testCase of SELF_TEST_CASES) {
2516
- let ok = false;
2516
+ let ok2 = false;
2517
2517
  let thrown = null;
2518
2518
  try {
2519
- ok = testCase.run() === true;
2519
+ ok2 = testCase.run() === true;
2520
2520
  } catch (error) {
2521
2521
  thrown = error?.message || String(error);
2522
2522
  }
2523
- if (ok) {
2523
+ if (ok2) {
2524
2524
  process.stdout.write(` \u2713 ${testCase.name}
2525
2525
  `);
2526
2526
  continue;
@@ -3742,7 +3742,7 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
3742
3742
  tokenCache.set(cacheKey, fromEnv);
3743
3743
  return fromEnv;
3744
3744
  }
3745
- const token = await new Promise((resolve53, reject) => {
3745
+ const token = await new Promise((resolve54, reject) => {
3746
3746
  let child;
3747
3747
  try {
3748
3748
  child = spawnImpl("wix", [...args]);
@@ -3771,12 +3771,12 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
3771
3771
  child.stdout?.on("data", (d) => {
3772
3772
  out2 += String(d);
3773
3773
  const m = out2.match(TOKEN_RE);
3774
- if (m) done(() => resolve53(m[0]));
3774
+ if (m) done(() => resolve54(m[0]));
3775
3775
  });
3776
3776
  child.stderr?.on("data", (d) => {
3777
3777
  out2 += String(d);
3778
3778
  const m = out2.match(TOKEN_RE);
3779
- if (m) done(() => resolve53(m[0]));
3779
+ if (m) done(() => resolve54(m[0]));
3780
3780
  });
3781
3781
  child.on("error", (e) => done(() => reject(new Error(mintHelp(label2, e.message)))));
3782
3782
  child.on("exit", (code) => done(() => reject(new Error(
@@ -3965,8 +3965,8 @@ function committedProvisioningPath(name) {
3965
3965
  function committedShellFor(path2) {
3966
3966
  const normalized = path2.replace(/\\/g, "/");
3967
3967
  return SHELL_NAMES2.find((name) => {
3968
- const relative14 = committedProvisioningPath(name);
3969
- return normalized === relative14 || normalized.endsWith(`/${relative14}`);
3968
+ const relative15 = committedProvisioningPath(name);
3969
+ return normalized === relative15 || normalized.endsWith(`/${relative15}`);
3970
3970
  });
3971
3971
  }
3972
3972
  function isBrandable(repoRoot2, name) {
@@ -4486,7 +4486,7 @@ function confinementPlugin(contentRoot) {
4486
4486
  }
4487
4487
  function assertConfinedTsconfig(entry, contentRoot, allows) {
4488
4488
  const seen = /* @__PURE__ */ new Set();
4489
- const refuse5 = (p, why) => {
4489
+ const refuse6 = (p, why) => {
4490
4490
  throw new Error(
4491
4491
  `refused to read ${p}: ${why}. A tsconfig may extend a file from its own package or an installed dependency \u2014 nothing else.`
4492
4492
  );
@@ -4552,7 +4552,7 @@ function assertConfinedTsconfig(entry, contentRoot, allows) {
4552
4552
  try {
4553
4553
  manifest = JSON.parse(stripJsonc(readFileSync10(pj, "utf8")));
4554
4554
  } catch {
4555
- refuse5(pj, "its package.json could not be parsed, so its `tsconfig` field cannot be checked");
4555
+ refuse6(pj, "its package.json could not be parsed, so its `tsconfig` field cannot be checked");
4556
4556
  }
4557
4557
  const field = manifest?.tsconfig;
4558
4558
  if (typeof field === "string" && field) {
@@ -4568,7 +4568,7 @@ function assertConfinedTsconfig(entry, contentRoot, allows) {
4568
4568
  const real = realpathOrSelf(file);
4569
4569
  if (seen.has(real)) return;
4570
4570
  seen.add(real);
4571
- if (!allows(real)) refuse5(file, "it is outside this content package");
4571
+ if (!allows(real)) refuse6(file, "it is outside this content package");
4572
4572
  let raw;
4573
4573
  try {
4574
4574
  raw = readFileSync10(real, "utf8");
@@ -4579,7 +4579,7 @@ function assertConfinedTsconfig(entry, contentRoot, allows) {
4579
4579
  try {
4580
4580
  parsed = JSON.parse(stripJsonc(raw));
4581
4581
  } catch {
4582
- refuse5(file, "its tsconfig could not be parsed, so its `extends` cannot be checked");
4582
+ refuse6(file, "its tsconfig could not be parsed, so its `extends` cannot be checked");
4583
4583
  }
4584
4584
  const ext = parsed?.extends;
4585
4585
  for (const one of Array.isArray(ext) ? ext : ext ? [ext] : []) {
@@ -8472,8 +8472,8 @@ function textOf(node) {
8472
8472
  function plainText(node) {
8473
8473
  if (typeOf(node) === "TEXT") return str(at(node, "textData", "text"));
8474
8474
  const children = kids(node).filter(isObj);
8475
- const sep17 = children.every((c) => typeOf(c) === "TEXT") ? "" : "\n";
8476
- return children.map(plainText).join(sep17);
8475
+ const sep18 = children.every((c) => typeOf(c) === "TEXT") ? "" : "\n";
8476
+ return children.map(plainText).join(sep18);
8477
8477
  }
8478
8478
  function alignOf(v) {
8479
8479
  switch (v) {
@@ -13140,6 +13140,7 @@ function resolveIdiom(tokens, ctx = {}) {
13140
13140
  var IDIOM_CONTEXTS, UNSAFE_KEYS;
13141
13141
  var init_idiom = __esm({
13142
13142
  "../../core/ts/src/idiom.ts"() {
13143
+ "use strict";
13143
13144
  IDIOM_CONTEXTS = {
13144
13145
  ios: { native: ["ios"] },
13145
13146
  android: { native: ["material"] },
@@ -14806,8 +14807,8 @@ function matchWeightCss(available, desired) {
14806
14807
  const upFrom = (n) => sorted2.find((w) => w >= n);
14807
14808
  const downFrom = (n) => [...sorted2].reverse().find((w) => w <= n);
14808
14809
  if (desired >= 400 && desired <= 500) {
14809
- const within = sorted2.find((w) => w >= desired && w <= 500);
14810
- return within ?? downFrom(desired) ?? upFrom(desired);
14810
+ const within2 = sorted2.find((w) => w >= desired && w <= 500);
14811
+ return within2 ?? downFrom(desired) ?? upFrom(desired);
14811
14812
  }
14812
14813
  if (desired < 400) return downFrom(desired) ?? upFrom(desired);
14813
14814
  return upFrom(desired) ?? downFrom(desired);
@@ -15930,29 +15931,29 @@ function matchRuleEx(rules, method, path2, ctx = {}) {
15930
15931
  }
15931
15932
  if (m.query) {
15932
15933
  const q = ctx.query ?? {};
15933
- let ok = true;
15934
+ let ok2 = true;
15934
15935
  for (const [k, v] of Object.entries(m.query)) {
15935
15936
  if (q[k] !== v) {
15936
- ok = false;
15937
+ ok2 = false;
15937
15938
  break;
15938
15939
  }
15939
15940
  captures[`query.${k}`] = q[k];
15940
15941
  }
15941
- if (!ok) continue;
15942
+ if (!ok2) continue;
15942
15943
  for (const [k, v] of Object.entries(q)) captures[`query.${k}`] = v;
15943
15944
  } else if (ctx.query) {
15944
15945
  for (const [k, v] of Object.entries(ctx.query)) captures[`query.${k}`] = v;
15945
15946
  }
15946
15947
  if (m.headers) {
15947
15948
  const hh = lc(ctx.headers);
15948
- let ok = true;
15949
+ let ok2 = true;
15949
15950
  for (const [k, v] of Object.entries(m.headers)) {
15950
15951
  if (hh[k.toLowerCase()] !== v) {
15951
- ok = false;
15952
+ ok2 = false;
15952
15953
  break;
15953
15954
  }
15954
15955
  }
15955
- if (!ok) continue;
15956
+ if (!ok2) continue;
15956
15957
  }
15957
15958
  if (m.bodyContains && !(ctx.body ?? "").includes(m.bodyContains)) continue;
15958
15959
  return { rule: r, captures };
@@ -18574,11 +18575,11 @@ function appleScriptString(s) {
18574
18575
  function runNotifier(cmd, args) {
18575
18576
  return new Promise((done) => {
18576
18577
  let settled = false;
18577
- const finish2 = (ok) => {
18578
+ const finish2 = (ok2) => {
18578
18579
  if (!settled) {
18579
18580
  settled = true;
18580
18581
  clearTimeout(timer);
18581
- done(ok);
18582
+ done(ok2);
18582
18583
  }
18583
18584
  };
18584
18585
  const child = spawn3(cmd, args, { stdio: "ignore" });
@@ -19465,10 +19466,10 @@ var init_preview = __esm({
19465
19466
  }
19466
19467
  },
19467
19468
  kill: (pid, signal) => process.kill(pid, signal),
19468
- portFree: (port) => new Promise((resolve53) => {
19469
+ portFree: (port) => new Promise((resolve54) => {
19469
19470
  const s = createServer2();
19470
- s.once("error", () => resolve53(false));
19471
- s.listen(port, "127.0.0.1", () => s.close(() => resolve53(true)));
19471
+ s.once("error", () => resolve54(false));
19472
+ s.listen(port, "127.0.0.1", () => s.close(() => resolve54(true)));
19472
19473
  }),
19473
19474
  sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
19474
19475
  servingIdentity: async (origin) => {
@@ -20612,7 +20613,7 @@ async function injectRequest(listener, request) {
20612
20613
  req.headers.host ??= url.host;
20613
20614
  if (body && body.length > 0) req.push(body);
20614
20615
  req.push(null);
20615
- return await new Promise((resolve53, reject) => {
20616
+ return await new Promise((resolve54, reject) => {
20616
20617
  const streamed = () => {
20617
20618
  queueMicrotask(() => {
20618
20619
  req.emit("close");
@@ -20628,7 +20629,7 @@ async function injectRequest(listener, request) {
20628
20629
  else headers2.set(name, value);
20629
20630
  }
20630
20631
  const bodyless = out2.status === 204 || out2.status === 304 || request.method === "HEAD";
20631
- resolve53(new Response(bodyless ? null : out2.body, { status: out2.status, headers: headers2 }));
20632
+ resolve54(new Response(bodyless ? null : out2.body, { status: out2.status, headers: headers2 }));
20632
20633
  }, streamed);
20633
20634
  res.on("inject-error", reject);
20634
20635
  try {
@@ -21334,7 +21335,7 @@ function redactBodyString(body) {
21334
21335
  } catch {
21335
21336
  }
21336
21337
  }
21337
- return body.replace(FORM_ASSIGNMENT_RE, (m, name) => isSensitiveBodyName(name) ? `${name}=${REDACTED}` : m).replace(JSON_FIELD_RE, (m, name, sep17) => isSensitiveBodyName(name) ? `"${name}"${sep17}"${REDACTED}"` : m).replace(JSON_FIELD_UNTERMINATED_RE, (m, name, sep17) => isSensitiveBodyName(name) ? `"${name}"${sep17}"${REDACTED}` : m).replace(BEARER_RE, (_m, s) => `${s} ${REDACTED}`);
21338
+ return body.replace(FORM_ASSIGNMENT_RE, (m, name) => isSensitiveBodyName(name) ? `${name}=${REDACTED}` : m).replace(JSON_FIELD_RE, (m, name, sep18) => isSensitiveBodyName(name) ? `"${name}"${sep18}"${REDACTED}"` : m).replace(JSON_FIELD_UNTERMINATED_RE, (m, name, sep18) => isSensitiveBodyName(name) ? `"${name}"${sep18}"${REDACTED}` : m).replace(BEARER_RE, (_m, s) => `${s} ${REDACTED}`);
21338
21339
  }
21339
21340
  function createWixGatewayState() {
21340
21341
  return { mode: "record", rules: [], traffic: [], clients: /* @__PURE__ */ new Set(), seq: 0, ruleSeq: 0 };
@@ -23080,10 +23081,10 @@ function recordDeviceLayout(payload) {
23080
23081
  }
23081
23082
  async function handleDeviceLayoutReport(res, payload) {
23082
23083
  const screenId = recordDeviceLayout(payload);
23083
- const ok = screenId !== null;
23084
- res.statusCode = ok ? 200 : 400;
23084
+ const ok2 = screenId !== null;
23085
+ res.statusCode = ok2 ? 200 : 400;
23085
23086
  res.setHeader("content-type", "application/json");
23086
- res.end(JSON.stringify(ok ? { status: "ok", screenId } : { error: "invalid_layout" }));
23087
+ res.end(JSON.stringify(ok2 ? { status: "ok", screenId } : { error: "invalid_layout" }));
23087
23088
  return screenId;
23088
23089
  }
23089
23090
  async function handlePreviewHitTest(res, payload) {
@@ -23162,12 +23163,12 @@ function finalizeRecording(key2, rec) {
23162
23163
  if (rec.finalize) return rec.finalize;
23163
23164
  rec.finalize = (async () => {
23164
23165
  clearTimeout(rec.autoStop);
23165
- await new Promise((resolve53) => {
23166
+ await new Promise((resolve54) => {
23166
23167
  let done = false;
23167
23168
  const finish2 = () => {
23168
23169
  if (!done) {
23169
23170
  done = true;
23170
- resolve53();
23171
+ resolve54();
23171
23172
  }
23172
23173
  };
23173
23174
  rec.child.once("close", finish2);
@@ -23278,7 +23279,7 @@ var init_preview2 = __esm({
23278
23279
  DEVICE_LIST_TIMEOUT_MS = 5e3;
23279
23280
  defaultRunner2 = {
23280
23281
  capture(cmd, args, timeoutMs = DEFAULT_CAPTURE_TIMEOUT_MS) {
23281
- return new Promise((resolve53, reject) => {
23282
+ return new Promise((resolve54, reject) => {
23282
23283
  const child = spawn4(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
23283
23284
  const out2 = [];
23284
23285
  const err = [];
@@ -23300,7 +23301,7 @@ var init_preview2 = __esm({
23300
23301
  child.stderr.on("data", (b) => err.push(b));
23301
23302
  child.on("error", (e) => settle(reject, e));
23302
23303
  child.on("close", (code) => {
23303
- if (code === 0) settle(resolve53, Buffer.concat(out2));
23304
+ if (code === 0) settle(resolve54, Buffer.concat(out2));
23304
23305
  else settle(reject, new Error(`${cmd} exited ${code}: ${Buffer.concat(err).toString("utf8")}`));
23305
23306
  });
23306
23307
  });
@@ -24632,13 +24633,13 @@ function validate(rule, rawValue) {
24632
24633
  return { rule: "type", type: rule.type };
24633
24634
  }
24634
24635
  if (rule.regex) {
24635
- let ok;
24636
+ let ok2;
24636
24637
  try {
24637
- ok = new RegExp(`^(?:${rule.regex})$`).test(value);
24638
+ ok2 = new RegExp(`^(?:${rule.regex})$`).test(value);
24638
24639
  } catch {
24639
- ok = true;
24640
+ ok2 = true;
24640
24641
  }
24641
- if (!ok) return { rule: "regex" };
24642
+ if (!ok2) return { rule: "regex" };
24642
24643
  }
24643
24644
  if (typeof rule.minLength === "number" && rule.minLength > 0 && value.length < rule.minLength) {
24644
24645
  return { rule: "minLength", limit: rule.minLength };
@@ -24718,6 +24719,7 @@ function shouldRevealError(args) {
24718
24719
  var EMAIL_RE, URL_HOST_RE, INTEGER_RE, NUMBER_RE;
24719
24720
  var init_validation = __esm({
24720
24721
  "../../core/ts/src/validation.ts"() {
24722
+ "use strict";
24721
24723
  EMAIL_RE = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,}$/;
24722
24724
  URL_HOST_RE = /^[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(:[0-9]+)?$/;
24723
24725
  INTEGER_RE = /^[+-]?[0-9]+$/;
@@ -27552,12 +27554,12 @@ function createRicosHostSession(o) {
27552
27554
  flush() {
27553
27555
  if (!state.ready || state.unavailable || disposed) return Promise.resolve(null);
27554
27556
  const requestId2 = newId();
27555
- return new Promise((resolve53) => {
27557
+ return new Promise((resolve54) => {
27556
27558
  const timer = t.setTimeout(() => {
27557
27559
  flushes.delete(requestId2);
27558
- resolve53(null);
27560
+ resolve54(null);
27559
27561
  }, flushMs);
27560
- flushes.set(requestId2, { resolve: resolve53, timer });
27562
+ flushes.set(requestId2, { resolve: resolve54, timer });
27561
27563
  o.send({ v: 1, type: "requestContent", requestId: requestId2 });
27562
27564
  });
27563
27565
  },
@@ -27610,7 +27612,7 @@ async function runRicosImageUpload(o) {
27610
27612
  };
27611
27613
  session.insertMediaPlaceholder(requestId2);
27612
27614
  try {
27613
- const entry = await new Promise((resolve53) => {
27615
+ const entry = await new Promise((resolve54) => {
27614
27616
  let done = false;
27615
27617
  let unsub = () => {
27616
27618
  };
@@ -27619,7 +27621,7 @@ async function runRicosImageUpload(o) {
27619
27621
  done = true;
27620
27622
  t.clearTimeout(timer);
27621
27623
  queueMicrotask(() => unsub());
27622
- resolve53(v);
27624
+ resolve54(v);
27623
27625
  };
27624
27626
  const timer = t.setTimeout(() => finish2(null), o.timeoutMs ?? RICOS_UPLOAD_TIMEOUT_MS);
27625
27627
  unsub = deps.subscribe(`${svc}.uploads.${requestId2}`, (v) => {
@@ -27638,10 +27640,10 @@ async function runRicosImageUpload(o) {
27638
27640
  } catch {
27639
27641
  return fail2("read");
27640
27642
  }
27641
- const sep17 = entry.uploadUrl.includes("?") ? "&" : "?";
27643
+ const sep18 = entry.uploadUrl.includes("?") ? "&" : "?";
27642
27644
  let res;
27643
27645
  try {
27644
- res = await deps.fetch(`${entry.uploadUrl}${sep17}filename=${encodeURIComponent(file.fileName)}`, { method: "PUT", headers: { "Content-Type": file.mimeType }, body });
27646
+ res = await deps.fetch(`${entry.uploadUrl}${sep18}filename=${encodeURIComponent(file.fileName)}`, { method: "PUT", headers: { "Content-Type": file.mimeType }, body });
27645
27647
  } catch {
27646
27648
  return fail2("put");
27647
27649
  }
@@ -27656,14 +27658,14 @@ async function runRicosImageUpload(o) {
27656
27658
  const d = root.file && typeof root.file === "object" ? root.file : root;
27657
27659
  const id = typeof d.id === "string" ? d.id : "";
27658
27660
  if (!id) return fail2("bad_descriptor");
27659
- const ok = session.resolveMedia(requestId2, {
27661
+ const ok2 = session.resolveMedia(requestId2, {
27660
27662
  id,
27661
27663
  url: typeof d.url === "string" ? d.url : "",
27662
27664
  ...typeof d.width === "number" ? { width: d.width } : {},
27663
27665
  ...typeof d.height === "number" ? { height: d.height } : {},
27664
27666
  mimeType: file.mimeType
27665
27667
  });
27666
- return ok ? { ok: true, mediaId: id } : { ok: false, reason: "bad_descriptor" };
27668
+ return ok2 ? { ok: true, mediaId: id } : { ok: false, reason: "bad_descriptor" };
27667
27669
  } finally {
27668
27670
  deps.dispatch({ actionId: `tier5.${svc}.clearUpload`, args: { requestId: requestId2 } });
27669
27671
  }
@@ -29118,6 +29120,7 @@ function validateWorkerSubtree(raw, slotId, policy, actionCatalog) {
29118
29120
  var WORKER_SUBTREE_CEILINGS, ID_PART, ACTION_ID;
29119
29121
  var init_worker_subtree = __esm({
29120
29122
  "../../core/ts/src/worker-subtree.ts"() {
29123
+ "use strict";
29121
29124
  init_worker_subtree_safe_types_generated();
29122
29125
  WORKER_SUBTREE_CEILINGS = Object.freeze({
29123
29126
  maxEncodedBytes: 65536,
@@ -29550,8 +29553,8 @@ function ensureCountUpRuntime() {
29550
29553
  const neg = fixed.startsWith("-");
29551
29554
  const body = neg ? fixed.slice(1) : fixed;
29552
29555
  const [int2, frac] = body.split(".");
29553
- const sep17 = int2.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
29554
- return (neg ? "-" : "") + sep17 + (frac ? "." + frac : "");
29556
+ const sep18 = int2.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
29557
+ return (neg ? "-" : "") + sep18 + (frac ? "." + frac : "");
29555
29558
  };
29556
29559
  const animateEl = (el) => {
29557
29560
  const node = el;
@@ -30372,24 +30375,24 @@ function usesSchematicRoute(props) {
30372
30375
  const hasRouteFeed = typeof props.routePath === "string" && props.routePath !== "";
30373
30376
  return hasFeed && !hasRoute && !hasRouteFeed;
30374
30377
  }
30375
- function longitudeAt(x, z2) {
30376
- return x / (TILE_PX * Math.pow(2, z2)) * 360 - 180;
30378
+ function longitudeAt(x, z3) {
30379
+ return x / (TILE_PX * Math.pow(2, z3)) * 360 - 180;
30377
30380
  }
30378
- function latitudeAt(y, z2) {
30379
- const n = Math.PI - 2 * Math.PI * y / (TILE_PX * Math.pow(2, z2));
30381
+ function latitudeAt(y, z3) {
30382
+ const n = Math.PI - 2 * Math.PI * y / (TILE_PX * Math.pow(2, z3));
30380
30383
  return 180 / Math.PI * Math.atan(Math.sinh(n));
30381
30384
  }
30382
- function regionArgs(centerLat, centerLng, z2, w, h) {
30383
- const cx = mercatorX(centerLng, z2);
30384
- const cy = mercatorY(centerLat, z2);
30385
+ function regionArgs(centerLat, centerLng, z3, w, h) {
30386
+ const cx = mercatorX(centerLng, z3);
30387
+ const cy = mercatorY(centerLat, z3);
30385
30388
  return {
30386
30389
  latitude: centerLat,
30387
30390
  longitude: centerLng,
30388
- zoom: z2,
30389
- north: latitudeAt(cy - h / 2, z2),
30390
- south: latitudeAt(cy + h / 2, z2),
30391
- east: longitudeAt(cx + w / 2, z2),
30392
- west: longitudeAt(cx - w / 2, z2)
30391
+ zoom: z3,
30392
+ north: latitudeAt(cy - h / 2, z3),
30393
+ south: latitudeAt(cy + h / 2, z3),
30394
+ east: longitudeAt(cx + w / 2, z3),
30395
+ west: longitudeAt(cx - w / 2, z3)
30393
30396
  };
30394
30397
  }
30395
30398
  function decodeCamera(v) {
@@ -30419,9 +30422,9 @@ function resolveTileSource(source) {
30419
30422
  const maxZoom = typeof s.maxZoom === "number" && s.maxZoom > 0 ? s.maxZoom : DEFAULT_TILE_MAX_ZOOM;
30420
30423
  return { urlTemplate, attribution, maxZoom };
30421
30424
  }
30422
- function tileUrl(source, z2, x, y) {
30423
- if (!source) return `https://tile.openstreetmap.org/${z2}/${x}/${y}.png`;
30424
- return source.urlTemplate.replace("{z}", String(z2)).replace("{x}", String(x)).replace("{y}", String(y));
30425
+ function tileUrl(source, z3, x, y) {
30426
+ if (!source) return `https://tile.openstreetmap.org/${z3}/${x}/${y}.png`;
30427
+ return source.urlTemplate.replace("{z}", String(z3)).replace("{x}", String(x)).replace("{y}", String(y));
30425
30428
  }
30426
30429
  function parseShapeKind(raw) {
30427
30430
  const k = typeof raw === "string" ? raw.toLowerCase() : "";
@@ -30438,12 +30441,12 @@ function circleRing(centreLat, centreLng, radiusM, segments = CIRCLE_SEGMENTS) {
30438
30441
  return { latitude: centreLat + dLat * Math.sin(theta), longitude: centreLng + dLng * Math.cos(theta) };
30439
30442
  });
30440
30443
  }
30441
- function distanceToPolylinePx(px, py, points, z2, originX, originY) {
30444
+ function distanceToPolylinePx(px, py, points, z3, originX, originY) {
30442
30445
  if (points.length < 2) return null;
30443
30446
  let best = Infinity;
30444
30447
  for (let i = 0; i < points.length - 1; i++) {
30445
- const ax = mercatorX(points[i].longitude, z2) - originX, ay = mercatorY(points[i].latitude, z2) - originY;
30446
- const bx = mercatorX(points[i + 1].longitude, z2) - originX, by = mercatorY(points[i + 1].latitude, z2) - originY;
30448
+ const ax = mercatorX(points[i].longitude, z3) - originX, ay = mercatorY(points[i].latitude, z3) - originY;
30449
+ const bx = mercatorX(points[i + 1].longitude, z3) - originX, by = mercatorY(points[i + 1].latitude, z3) - originY;
30447
30450
  const dx = bx - ax, dy = by - ay;
30448
30451
  const lenSq = dx * dx + dy * dy;
30449
30452
  const t = lenSq === 0 ? 0 : ((px - ax) * dx + (py - ay) * dy) / lenSq;
@@ -30453,22 +30456,22 @@ function distanceToPolylinePx(px, py, points, z2, originX, originY) {
30453
30456
  }
30454
30457
  return best;
30455
30458
  }
30456
- function polygonContainsPx(px, py, points, z2, originX, originY) {
30459
+ function polygonContainsPx(px, py, points, z3, originX, originY) {
30457
30460
  if (points.length < 3) return false;
30458
30461
  let inside2 = false;
30459
30462
  for (let i = 0, j = points.length - 1; i < points.length; j = i++) {
30460
- const xi = mercatorX(points[i].longitude, z2) - originX, yi = mercatorY(points[i].latitude, z2) - originY;
30461
- const xj = mercatorX(points[j].longitude, z2) - originX, yj = mercatorY(points[j].latitude, z2) - originY;
30463
+ const xi = mercatorX(points[i].longitude, z3) - originX, yi = mercatorY(points[i].latitude, z3) - originY;
30464
+ const xj = mercatorX(points[j].longitude, z3) - originX, yj = mercatorY(points[j].latitude, z3) - originY;
30462
30465
  if (yi > py !== yj > py && px < (xj - xi) * (py - yi) / (yj - yi) + xi) inside2 = !inside2;
30463
30466
  }
30464
30467
  return inside2;
30465
30468
  }
30466
- function markerHit(px, py, markers, z2, originX, originY) {
30469
+ function markerHit(px, py, markers, z3, originX, originY) {
30467
30470
  let best = null;
30468
30471
  let bestDistance = MARKER_HIT_RADIUS;
30469
30472
  markers.forEach((m, i) => {
30470
- const dx = mercatorX(m.longitude, z2) - originX - px;
30471
- const dy = mercatorY(m.latitude, z2) - originY - py;
30473
+ const dx = mercatorX(m.longitude, z3) - originX - px;
30474
+ const dy = mercatorY(m.latitude, z3) - originY - py;
30472
30475
  const d = Math.sqrt(dx * dx + dy * dy);
30473
30476
  if (d <= bestDistance) {
30474
30477
  bestDistance = d;
@@ -30477,22 +30480,22 @@ function markerHit(px, py, markers, z2, originX, originY) {
30477
30480
  });
30478
30481
  return best;
30479
30482
  }
30480
- function mercatorX(lng, z2) {
30481
- return (lng + 180) / 360 * TILE_PX * Math.pow(2, z2);
30483
+ function mercatorX(lng, z3) {
30484
+ return (lng + 180) / 360 * TILE_PX * Math.pow(2, z3);
30482
30485
  }
30483
- function mercatorY(lat, z2) {
30486
+ function mercatorY(lat, z3) {
30484
30487
  const s = Math.max(-85.05112878, Math.min(85.05112878, lat)) * Math.PI / 180;
30485
- return (1 - Math.log(Math.tan(s) + 1 / Math.cos(s)) / Math.PI) / 2 * TILE_PX * Math.pow(2, z2);
30488
+ return (1 - Math.log(Math.tan(s) + 1 / Math.cos(s)) / Math.PI) / 2 * TILE_PX * Math.pow(2, z3);
30486
30489
  }
30487
30490
  function fitZoom(pts, w, h, fallback) {
30488
30491
  if (pts.length < 2 || w <= 0 || h <= 0) return fallback;
30489
30492
  const lats = pts.map((p) => p.latitude), lngs = pts.map((p) => p.longitude);
30490
30493
  const minLa = Math.min(...lats), maxLa = Math.max(...lats);
30491
30494
  const minLo = Math.min(...lngs), maxLo = Math.max(...lngs);
30492
- for (let z2 = 19; z2 >= 1; z2--) {
30493
- const dx = Math.abs(mercatorX(maxLo, z2) - mercatorX(minLo, z2));
30494
- const dy = Math.abs(mercatorY(maxLa, z2) - mercatorY(minLa, z2));
30495
- if (dx <= w && dy <= h) return z2;
30495
+ for (let z3 = 19; z3 >= 1; z3--) {
30496
+ const dx = Math.abs(mercatorX(maxLo, z3) - mercatorX(minLo, z3));
30497
+ const dy = Math.abs(mercatorY(maxLa, z3) - mercatorY(minLa, z3));
30498
+ if (dx <= w && dy <= h) return z3;
30496
30499
  }
30497
30500
  return 1;
30498
30501
  }
@@ -34611,20 +34614,20 @@ var init_renderNode = __esm({
34611
34614
  const fitted = shouldFit ? fitZoom(all, W - 48, H - 48, declared) : declared;
34612
34615
  const baseLat = all.length && shouldFit ? (Math.min(...all.map((p) => p.latitude)) + Math.max(...all.map((p) => p.latitude))) / 2 : typeof props.latitude === "number" ? props.latitude : 37.7749;
34613
34616
  const baseLng = all.length && shouldFit ? (Math.min(...all.map((p) => p.longitude)) + Math.max(...all.map((p) => p.longitude))) / 2 : typeof props.longitude === "number" ? props.longitude : -122.4194;
34614
- const z2 = userCam?.z ?? fitted;
34617
+ const z3 = userCam?.z ?? fitted;
34615
34618
  const cLat = userCam?.lat ?? baseLat;
34616
34619
  const cLng = userCam?.lng ?? baseLng;
34617
34620
  React7.useEffect(() => {
34618
- const resolved2 = resolveCamera(commandedCamera, cLat, cLng, z2);
34621
+ const resolved2 = resolveCamera(commandedCamera, cLat, cLng, z3);
34619
34622
  if (!resolved2) return;
34620
34623
  setUserCam({
34621
34624
  lat: Math.max(-MAX_MERCATOR_LAT, Math.min(MAX_MERCATOR_LAT, resolved2.latitude)),
34622
34625
  lng: resolved2.longitude,
34623
- z: Math.max(1, Math.min(19, resolved2.zoom ?? z2))
34626
+ z: Math.max(1, Math.min(19, resolved2.zoom ?? z3))
34624
34627
  });
34625
34628
  }, [commandedCamera]);
34626
- const originX = mercatorX(cLng, z2) - W / 2;
34627
- const originY = mercatorY(cLat, z2) - H / 2;
34629
+ const originX = mercatorX(cLng, z3) - W / 2;
34630
+ const originY = mercatorY(cLat, z3) - H / 2;
34628
34631
  const interactive = pinsOnly ? props.interactive === true : props.interactive !== false;
34629
34632
  const resolvedTileSource = resolveTileSource(props.tileSource);
34630
34633
  const fireMapEvent = (action, payload) => {
@@ -34642,7 +34645,7 @@ var init_renderNode = __esm({
34642
34645
  const { kx, ky } = layoutScale(el);
34643
34646
  const px = (e.clientX - r.left) * kx - el.clientLeft;
34644
34647
  const py = (e.clientY - r.top) * ky - el.clientTop;
34645
- const hit = markerHit(px, py, markers, z2, originX, originY);
34648
+ const hit = markerHit(px, py, markers, z3, originX, originY);
34646
34649
  if (hit !== null) {
34647
34650
  const m = markers[hit];
34648
34651
  const payload = { index: hit, latitude: m.latitude, longitude: m.longitude };
@@ -34653,10 +34656,10 @@ var init_renderNode = __esm({
34653
34656
  const shapeIndex = shapes.findIndex((sh) => {
34654
34657
  if (sh.kind === "unknown" || sh.points.length < 2) return false;
34655
34658
  if (sh.kind === "line") {
34656
- const d2 = distanceToPolylinePx(px, py, sh.points, z2, originX, originY);
34659
+ const d2 = distanceToPolylinePx(px, py, sh.points, z3, originX, originY);
34657
34660
  return d2 !== null && d2 <= SHAPE_HIT_RADIUS;
34658
34661
  }
34659
- return polygonContainsPx(px, py, sh.points, z2, originX, originY);
34662
+ return polygonContainsPx(px, py, sh.points, z3, originX, originY);
34660
34663
  });
34661
34664
  if (shapeIndex >= 0 && props.onShapeTap) {
34662
34665
  const sh = shapes[shapeIndex];
@@ -34665,15 +34668,15 @@ var init_renderNode = __esm({
34665
34668
  fireMapEvent(props.onShapeTap, payload);
34666
34669
  } else {
34667
34670
  fireMapEvent(props.onMapTap, {
34668
- latitude: latitudeAt(originY + py, z2),
34669
- longitude: longitudeAt(originX + px, z2)
34671
+ latitude: latitudeAt(originY + py, z3),
34672
+ longitude: longitudeAt(originX + px, z3)
34670
34673
  });
34671
34674
  }
34672
34675
  }
34673
34676
  };
34674
34677
  const onPointerDown = (e) => {
34675
34678
  if (!interactive) return;
34676
- dragRef.current = { x: e.clientX, y: e.clientY, lat: cLat, lng: cLng, z: z2, ...layoutScale(e.currentTarget) };
34679
+ dragRef.current = { x: e.clientX, y: e.clientY, lat: cLat, lng: cLng, z: z3, ...layoutScale(e.currentTarget) };
34677
34680
  dragMovedRef.current = false;
34678
34681
  };
34679
34682
  const onPointerMove = (e) => {
@@ -34697,8 +34700,8 @@ var init_renderNode = __esm({
34697
34700
  const onWheel = (e) => {
34698
34701
  if (!interactive) return;
34699
34702
  e.preventDefault();
34700
- const next = Math.max(1, Math.min(19, z2 + (e.deltaY < 0 ? 1 : -1)));
34701
- if (next !== z2) setUserCam({ lat: cLat, lng: cLng, z: next });
34703
+ const next = Math.max(1, Math.min(19, z3 + (e.deltaY < 0 ? 1 : -1)));
34704
+ if (next !== z3) setUserCam({ lat: cLat, lng: cLng, z: next });
34702
34705
  };
34703
34706
  React7.useEffect(() => {
34704
34707
  const action = props.onRegionChange;
@@ -34709,22 +34712,22 @@ var init_renderNode = __esm({
34709
34712
  regionReportedRef.current = true;
34710
34713
  return;
34711
34714
  }
34712
- fire({ ...action, args: { ...action.args ?? {}, ...regionArgs(cLat, cLng, z2, W, H) } });
34715
+ fire({ ...action, args: { ...action.args ?? {}, ...regionArgs(cLat, cLng, z3, W, H) } });
34713
34716
  }, 250);
34714
34717
  return () => clearTimeout(t);
34715
- }, [cLat, cLng, z2, W, H, props.onRegionChange]);
34716
- const sx = (p) => mercatorX(p.longitude, z2) - originX;
34717
- const sy = (p) => mercatorY(p.latitude, z2) - originY;
34718
+ }, [cLat, cLng, z3, W, H, props.onRegionChange]);
34719
+ const sx = (p) => mercatorX(p.longitude, z3) - originX;
34720
+ const sy = (p) => mercatorY(p.latitude, z3) - originY;
34718
34721
  const accent = C("accentPrimary", "#116DFF");
34719
- const n = Math.pow(2, z2);
34722
+ const n = Math.pow(2, z3);
34720
34723
  const tiles = [];
34721
34724
  for (let tx = Math.floor(originX / TILE_PX); tx <= Math.floor((originX + W) / TILE_PX); tx++) {
34722
34725
  for (let ty = Math.floor(originY / TILE_PX); ty <= Math.floor((originY + H) / TILE_PX); ty++) {
34723
34726
  if (ty < 0 || ty >= n) continue;
34724
34727
  const wrapX = (tx % n + n) % n;
34725
34728
  tiles.push({
34726
- key: `${z2}/${wrapX}/${ty}`,
34727
- src: tileUrl(resolvedTileSource, z2, wrapX, ty),
34729
+ key: `${z3}/${wrapX}/${ty}`,
34730
+ src: tileUrl(resolvedTileSource, z3, wrapX, ty),
34728
34731
  left: tx * TILE_PX - originX,
34729
34732
  top: ty * TILE_PX - originY
34730
34733
  });
@@ -34736,7 +34739,7 @@ var init_renderNode = __esm({
34736
34739
  ref: attachBox,
34737
34740
  "data-map-mode": "tile",
34738
34741
  "data-route-points": route.length,
34739
- "data-map-zoom": z2,
34742
+ "data-map-zoom": z3,
34740
34743
  onClick: onSurfaceClick,
34741
34744
  onPointerDown,
34742
34745
  onPointerMove,
@@ -35902,7 +35905,7 @@ async function stabilizePngPage(page, scheme) {
35902
35905
  const browser = globalThis;
35903
35906
  browser.document.documentElement.style.colorScheme = selected;
35904
35907
  await browser.document.fonts?.ready;
35905
- await new Promise((resolve53) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve53())));
35908
+ await new Promise((resolve54) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve54())));
35906
35909
  }, scheme);
35907
35910
  }
35908
35911
  async function renderPngBatch(items) {
@@ -39543,7 +39546,7 @@ async function handleWebWix(req, res, state) {
39543
39546
  }
39544
39547
  if (match) {
39545
39548
  const mocked = match.rule.response;
39546
- if (mocked.delayMs) await new Promise((resolve53) => setTimeout(resolve53, mocked.delayMs));
39549
+ if (mocked.delayMs) await new Promise((resolve54) => setTimeout(resolve54, mocked.delayMs));
39547
39550
  const responseBody = mocked.template ? renderTemplate(mocked.body, match.captures) : mocked.body;
39548
39551
  record2("mock", mocked.status, responseBody, match.rule.id, mocked.headers);
39549
39552
  return reply(200, { status: mocked.status, body: responseBody ?? "" });
@@ -40537,8 +40540,8 @@ async function handleActionHandlerBundleGet(res, app) {
40537
40540
  }
40538
40541
  async function serveStatic(req, res, root, prefix) {
40539
40542
  const requested = decodeURIComponent((req.url ?? "").split("?")[0]);
40540
- const relative14 = requested.replace(prefix, "").replace(/^\//, "");
40541
- const safe = normalize3(relative14).replace(/^(\.\.[\/\\])+/, "");
40543
+ const relative15 = requested.replace(prefix, "").replace(/^\//, "");
40544
+ const safe = normalize3(relative15).replace(/^(\.\.[\/\\])+/, "");
40542
40545
  const fullPath = resolve33(root, safe);
40543
40546
  if (!fullPath.startsWith(root)) {
40544
40547
  return send(res, 403, "forbidden");
@@ -41269,8 +41272,8 @@ function sha256hex(b) {
41269
41272
  function stableStringify(value) {
41270
41273
  if (value === null || typeof value !== "object") return JSON.stringify(value);
41271
41274
  if (Array.isArray(value)) return "[" + value.map(stableStringify).join(",") + "]";
41272
- const object2 = value;
41273
- return "{" + Object.keys(object2).sort().map((key2) => JSON.stringify(key2) + ":" + stableStringify(object2[key2])).join(",") + "}";
41275
+ const object3 = value;
41276
+ return "{" + Object.keys(object3).sort().map((key2) => JSON.stringify(key2) + ":" + stableStringify(object3[key2])).join(",") + "}";
41274
41277
  }
41275
41278
  function manifestContent(m) {
41276
41279
  const {
@@ -41642,12 +41645,12 @@ var init_query = __esm({
41642
41645
  });
41643
41646
 
41644
41647
  // ../../core/dev-server/src/crawl-input.ts
41645
- function resolved(v, resolve53) {
41646
- if (typeof v === "string") return v.startsWith("$service:") ? resolve53(v) : v;
41648
+ function resolved(v, resolve54) {
41649
+ if (typeof v === "string") return v.startsWith("$service:") ? resolve54(v) : v;
41647
41650
  if (Array.isArray(v)) {
41648
41651
  const out2 = v.flatMap((el) => {
41649
41652
  if (typeof el !== "string" || !el.startsWith("$service:")) return [el];
41650
- const r = resolve53(el);
41653
+ const r = resolve54(el);
41651
41654
  return Array.isArray(r) ? r : [r];
41652
41655
  });
41653
41656
  return out2;
@@ -41661,9 +41664,9 @@ function hasRowBinding(props) {
41661
41664
  return itemToken(v) || Array.isArray(v) && v.some(itemToken);
41662
41665
  });
41663
41666
  }
41664
- function declaredOptionIds(props, resolve53) {
41667
+ function declaredOptionIds(props, resolve54) {
41665
41668
  const literal = props.options ?? props.tabs ?? props.chips;
41666
- const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath, resolve53) : void 0;
41669
+ const bound = props.optionsPath !== void 0 ? resolved(props.optionsPath, resolve54) : void 0;
41667
41670
  const raw = Array.isArray(bound) ? bound : literal;
41668
41671
  if (!Array.isArray(raw)) return [];
41669
41672
  const out2 = [];
@@ -41706,24 +41709,24 @@ function seedTokens(state, limit = 48) {
41706
41709
  walk2(state, 0);
41707
41710
  return out2;
41708
41711
  }
41709
- function synthesizeInput(control, resolve53, tokens) {
41712
+ function synthesizeInput(control, resolve54, tokens) {
41710
41713
  const id = `${control.type}.${control.callback}`;
41711
41714
  const row = SYNTHESIZED_CONTROLS[id];
41712
41715
  if (!row) return null;
41713
41716
  const props = control.props;
41714
41717
  if (hasRowBinding(props)) return null;
41715
41718
  if (row.from === "declared-options") {
41716
- const ids = declaredOptionIds(props, resolve53);
41719
+ const ids = declaredOptionIds(props, resolve54);
41717
41720
  if (!ids.length) return null;
41718
41721
  if (row.encoding === "string-array") {
41719
- const currentRaw2 = resolved(props.selectedIds, resolve53);
41722
+ const currentRaw2 = resolved(props.selectedIds, resolve54);
41720
41723
  const current3 = (Array.isArray(currentRaw2) ? currentRaw2 : []).filter((x) => typeof x === "string");
41721
41724
  const pick4 = ids.find((o) => !current3.includes(o));
41722
41725
  if (pick4 === void 0) return null;
41723
41726
  const value = props.multiSelect === true ? [...current3, pick4] : [pick4];
41724
41727
  return { key: row.key, value, from: row.from, current: current3, control: id };
41725
41728
  }
41726
- const currentRaw = resolved(props.selectedId, resolve53);
41729
+ const currentRaw = resolved(props.selectedId, resolve54);
41727
41730
  const current2 = typeof currentRaw === "string" ? currentRaw : void 0;
41728
41731
  const pick3 = ids.find((o) => o !== current2);
41729
41732
  if (pick3 === void 0) return null;
@@ -41731,7 +41734,7 @@ function synthesizeInput(control, resolve53, tokens) {
41731
41734
  }
41732
41735
  if (!acceptsWords(props) || !acceptsWords(control.wrapper ?? {})) return null;
41733
41736
  const binding2 = typeof props.valuePath === "string" ? props.valuePath : typeof props.value === "string" && props.value.startsWith("$service:") ? props.value : void 0;
41734
- const bound = binding2 === void 0 ? void 0 : resolve53(binding2);
41737
+ const bound = binding2 === void 0 ? void 0 : resolve54(binding2);
41735
41738
  const literal = typeof props.value === "string" && !props.value.startsWith("$") ? props.value : void 0;
41736
41739
  const current = typeof bound === "string" ? bound : typeof bound === "number" ? String(bound) : literal ?? "";
41737
41740
  const max = typeof props.maxLength === "number" && props.maxLength > 0 ? props.maxLength : void 0;
@@ -43216,8 +43219,8 @@ async function crawlScreenInner(opts) {
43216
43219
  if (linkable.has(target)) return true;
43217
43220
  for (const base of linkable) {
43218
43221
  if (target.length > base.length + 1 && target.startsWith(base)) {
43219
- const sep17 = target[base.length];
43220
- if (sep17 === "_" || sep17 === "/") return true;
43222
+ const sep18 = target[base.length];
43223
+ if (sep18 === "_" || sep18 === "/") return true;
43221
43224
  }
43222
43225
  }
43223
43226
  return false;
@@ -46244,7 +46247,7 @@ var init_studio_timeline = __esm({
46244
46247
  isStr = (x) => typeof x === "string";
46245
46248
  isObj2 = (x) => typeof x === "object" && x !== null && !Array.isArray(x);
46246
46249
  strs = (x) => Array.isArray(x) && x.every(isStr);
46247
- nullOr = (x, ok) => x === null || isObj2(x) && ok(x);
46250
+ nullOr = (x, ok2) => x === null || isObj2(x) && ok2(x);
46248
46251
  accentOf = (palette2) => {
46249
46252
  for (const p of palette2 ?? []) {
46250
46253
  const [name, hex2] = Array.isArray(p) ? p : [p.name, p.hex];
@@ -47194,16 +47197,16 @@ function pushSetupBodyBytes(body) {
47194
47197
  return Buffer.byteLength(JSON.stringify(body), "utf8");
47195
47198
  }
47196
47199
  async function pushSetupRequest(options) {
47197
- const refuse5 = (error) => ({ ok: false, status: 0, body: null, error });
47198
- if (!options.target.controlToken) return refuse5("control_token_required");
47199
- if (!options.wixToken) return refuse5("wix_account_token_required");
47200
- if (credentialHostRefusal(options.target.control)) return refuse5("insecure_target");
47201
- if (options.previewTag !== void 0 && !PREVIEW_TAG.test(options.previewTag)) return refuse5("invalid_preview_tag");
47200
+ const refuse6 = (error) => ({ ok: false, status: 0, body: null, error });
47201
+ if (!options.target.controlToken) return refuse6("control_token_required");
47202
+ if (!options.wixToken) return refuse6("wix_account_token_required");
47203
+ if (credentialHostRefusal(options.target.control)) return refuse6("insecure_target");
47204
+ if (options.previewTag !== void 0 && !PREVIEW_TAG.test(options.previewTag)) return refuse6("invalid_preview_tag");
47202
47205
  const setup = options.operation === "setup";
47203
- if (setup && !options.body) return refuse5("push_setup_body_required");
47204
- if (!setup && (!options.query?.app || !options.query?.site)) return refuse5("push_setup_query_required");
47206
+ if (setup && !options.body) return refuse6("push_setup_body_required");
47207
+ if (!setup && (!options.query?.app || !options.query?.site)) return refuse6("push_setup_query_required");
47205
47208
  if (setup && pushSetupBodyBytes(options.body) > MAX_PUSH_SETUP_BODY_BYTES) {
47206
- return refuse5("push_setup_body_too_large");
47209
+ return refuse6("push_setup_body_too_large");
47207
47210
  }
47208
47211
  const base = options.target.control.replace(/\/+$/, "");
47209
47212
  let path2 = "/v1/admin/push/setup";
@@ -51021,8 +51024,8 @@ function baseOf(target, linkable, known) {
51021
51024
  let best = null;
51022
51025
  for (const base of linkable ?? []) {
51023
51026
  if (!known.has(base) || target.length <= base.length + 1 || !target.startsWith(base)) continue;
51024
- const sep17 = target[base.length];
51025
- if ((sep17 === "_" || sep17 === "/") && (!best || base.length > best.length)) best = base;
51027
+ const sep18 = target[base.length];
51028
+ if ((sep18 === "_" || sep18 === "/") && (!best || base.length > best.length)) best = base;
51026
51029
  }
51027
51030
  return best;
51028
51031
  }
@@ -52263,7 +52266,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
52263
52266
  const headers2 = Object.fromEntries(new Headers(init.headers).entries());
52264
52267
  const request = url.protocol === "https:" ? httpsRequest : httpRequest;
52265
52268
  const hostname2 = url.hostname.replace(/^\[|\]$/g, "");
52266
- return await new Promise((resolve53, reject) => {
52269
+ return await new Promise((resolve54, reject) => {
52267
52270
  let settled = false;
52268
52271
  const finish2 = (fn) => {
52269
52272
  if (settled) return;
@@ -52300,7 +52303,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
52300
52303
  }
52301
52304
  const responseHeaders = new Headers();
52302
52305
  for (const [key2, value] of Object.entries(response.headers)) if (value !== void 0) responseHeaders.set(key2, Array.isArray(value) ? value.join(", ") : value);
52303
- resolve53(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
52306
+ resolve54(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
52304
52307
  }));
52305
52308
  });
52306
52309
  req.once("error", (error) => finish2(() => reject(error)));
@@ -52600,7 +52603,7 @@ function createLocalTestSandbox() {
52600
52603
  }
52601
52604
  })();
52602
52605
  `;
52603
- return await new Promise((resolve53, reject) => {
52606
+ return await new Promise((resolve54, reject) => {
52604
52607
  const { port1, port2 } = new MessageChannel();
52605
52608
  const serializableContext = {
52606
52609
  auth: context.auth,
@@ -52676,7 +52679,7 @@ function createLocalTestSandbox() {
52676
52679
  timer = setTimeout(() => finish2(() => reject(new SandboxError("timeout", `execution exceeded ${limits.timeoutMs}ms`))), Math.max(1, limits.timeoutMs));
52677
52680
  return;
52678
52681
  }
52679
- if (message.ok) finish2(() => resolve53({ value: message.value, durationMs: Date.now() - started }));
52682
+ if (message.ok) finish2(() => resolve54({ value: message.value, durationMs: Date.now() - started }));
52680
52683
  else finish2(() => reject(new SandboxError("execution_failed", message.message ?? "handler failed")));
52681
52684
  });
52682
52685
  worker.once("error", (error) => finish2(() => reject(new SandboxError("execution_failed", error.message))));
@@ -53853,9 +53856,187 @@ var init_cli_bridge = __esm({
53853
53856
  }
53854
53857
  });
53855
53858
 
53856
- // src/mcp/tools.ts
53859
+ // src/mcp/file-tools.ts
53860
+ import { lstatSync as lstatSync12, mkdirSync as mkdirSync26, readdirSync as readdirSync27, readFileSync as readFileSync59, realpathSync as realpathSync7, rmSync as rmSync12, statSync as statSync13, writeFileSync as writeFileSync21, existsSync as existsSync54 } from "node:fs";
53861
+ import { dirname as dirname30, isAbsolute as isAbsolute5, join as join53, relative as relative11, resolve as resolve45, sep as sep14 } from "node:path";
53857
53862
  import * as z from "zod";
53858
- import { resolve as resolve45 } from "node:path";
53863
+ function within(root, p) {
53864
+ return p === root || p.startsWith(root.endsWith(sep14) ? root : root + sep14);
53865
+ }
53866
+ function realish(p) {
53867
+ let cur = p;
53868
+ const tail = [];
53869
+ while (!existsSync54(cur)) {
53870
+ const up = dirname30(cur);
53871
+ if (up === cur) break;
53872
+ tail.unshift(cur.slice(up.length + (up.endsWith(sep14) ? 0 : 1)));
53873
+ cur = up;
53874
+ }
53875
+ return join53(realpathSync7(cur), ...tail);
53876
+ }
53877
+ async function confinedAppDir(args, deps) {
53878
+ const root = resolve45(await deps.defaultDir());
53879
+ const dir = typeof args.dir === "string" && args.dir ? resolve45(root, args.dir) : root;
53880
+ if (!existsSync54(root)) return refuse4("no_workspace", `the workspace folder ${root} does not exist`);
53881
+ if (!within(realpathSync7(root), realish(dir))) return refuse4("outside_workspace", `"${String(args.dir)}" is outside the workspace folder`);
53882
+ return dir;
53883
+ }
53884
+ function confinedPath(appDir3, rel) {
53885
+ if (typeof rel !== "string" || !rel.trim()) return { error: "a path is required" };
53886
+ if (rel.includes("\0")) return { error: "a path may not contain NUL" };
53887
+ if (isAbsolute5(rel)) return { error: `"${rel}" is absolute \u2014 give a path inside the app folder` };
53888
+ const abs = resolve45(appDir3, rel);
53889
+ const real = realish(abs);
53890
+ const base = existsSync54(appDir3) ? realpathSync7(appDir3) : realish(appDir3);
53891
+ if (!within(base, real) || real === base) return { error: `"${rel}" is outside the app folder` };
53892
+ const first = relative11(base, real).split(sep14)[0];
53893
+ if (RESERVED.has(first)) return { error: `"${rel}" is inside ${first}/, which this tool does not touch` };
53894
+ return abs;
53895
+ }
53896
+ function listFiles(appDir3) {
53897
+ const files = [];
53898
+ const walk2 = (d) => {
53899
+ for (const e of readdirSync27(d, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
53900
+ if (RESERVED.has(e.name)) continue;
53901
+ if (e.isSymbolicLink()) continue;
53902
+ const p = join53(d, e.name);
53903
+ if (e.isDirectory()) {
53904
+ if (!walk2(p)) return false;
53905
+ } else if (e.isFile()) {
53906
+ if (files.length >= MAX_LISTED) return false;
53907
+ files.push({ path: relative11(appDir3, p).split(sep14).join("/"), bytes: statSync13(p).size });
53908
+ }
53909
+ }
53910
+ return true;
53911
+ };
53912
+ const complete = walk2(appDir3);
53913
+ return { files, truncated: !complete };
53914
+ }
53915
+ function fileTools() {
53916
+ return [
53917
+ {
53918
+ name: "himi_list_apps",
53919
+ title: "List apps in the workspace",
53920
+ description: "The apps (content packages) in the workspace folder: the folder itself if it is one, and each sub-folder that is. Pass an app's `dir` to the other tools.",
53921
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
53922
+ inputSchema: z.object({}),
53923
+ handler: async (_a, d) => {
53924
+ const root = resolve45(await d.defaultDir());
53925
+ if (!existsSync54(root)) return ok({ ok: true, workspace: root, apps: [] });
53926
+ const apps = [];
53927
+ if (existsSync54(join53(root, CONTENT_MARKER))) apps.push(".");
53928
+ for (const e of readdirSync27(root, { withFileTypes: true })) {
53929
+ if (e.isDirectory() && !e.name.startsWith(".") && existsSync54(join53(root, e.name, CONTENT_MARKER))) apps.push(e.name);
53930
+ }
53931
+ return ok({ ok: true, workspace: root, apps: apps.sort() });
53932
+ }
53933
+ },
53934
+ {
53935
+ name: "himi_list_files",
53936
+ title: "List app files",
53937
+ description: `Every file in an app folder with its size (skips ${[...RESERVED].join(", ")}; at most ${MAX_LISTED}).`,
53938
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
53939
+ inputSchema: z.object({ dir: DIR }),
53940
+ handler: async (a, d) => {
53941
+ const app = await confinedAppDir(a, d);
53942
+ if (typeof app !== "string") return app;
53943
+ if (!existsSync54(app) || !statSync13(app).isDirectory()) return refuse4("no_app", `no folder at ${app}`);
53944
+ return ok({ ok: true, dir: app, ...listFiles(app) });
53945
+ }
53946
+ },
53947
+ {
53948
+ name: "himi_read_file",
53949
+ title: "Read an app file",
53950
+ description: `One file of an app folder, as UTF-8 text (at most ${MAX_FILE_BYTES / 1024} KiB).`,
53951
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
53952
+ inputSchema: z.object({ dir: DIR, path: z.string().min(1).describe('Path inside the app folder, e.g. "screens/home.ts".') }),
53953
+ handler: async (a, d) => {
53954
+ const app = await confinedAppDir(a, d);
53955
+ if (typeof app !== "string") return app;
53956
+ const p = confinedPath(app, a.path);
53957
+ if (typeof p !== "string") return refuse4("bad_path", p.error);
53958
+ if (!existsSync54(p) || !lstatSync12(p).isFile()) return refuse4("not_found", `no file "${String(a.path)}"`);
53959
+ const size = statSync13(p).size;
53960
+ if (size > MAX_FILE_BYTES) return refuse4("too_large", `"${String(a.path)}" is ${size} bytes \u2014 over the ${MAX_FILE_BYTES}-byte read limit`);
53961
+ return ok({ ok: true, path: a.path, bytes: size, content: readFileSync59(p, "utf8") });
53962
+ }
53963
+ },
53964
+ {
53965
+ name: "himi_write_files",
53966
+ title: "Write app files",
53967
+ description: `Create or REPLACE files in an app folder (parent folders are created). At most ${MAX_FILES_PER_WRITE} files and ${MAX_FILE_BYTES / 1024} KiB each per call. Nothing is written if any path is refused.`,
53968
+ annotations: WRITE_ANN,
53969
+ inputSchema: z.object({
53970
+ dir: DIR,
53971
+ files: z.array(z.object({ path: z.string().min(1), content: z.string() })).min(1).max(MAX_FILES_PER_WRITE)
53972
+ }),
53973
+ handler: async (a, d) => {
53974
+ const app = await confinedAppDir(a, d);
53975
+ if (typeof app !== "string") return app;
53976
+ const files = Array.isArray(a.files) ? a.files : [];
53977
+ if (!files.length || files.length > MAX_FILES_PER_WRITE) return refuse4("bad_request", `between 1 and ${MAX_FILES_PER_WRITE} files per call`);
53978
+ const planned = [];
53979
+ const refused2 = [];
53980
+ for (const f of files) {
53981
+ const p = confinedPath(app, f.path);
53982
+ if (typeof p !== "string") refused2.push({ path: f.path, error: p.error });
53983
+ else if (typeof f.content !== "string") refused2.push({ path: f.path, error: "content must be text" });
53984
+ else if (Buffer.byteLength(f.content) > MAX_FILE_BYTES) refused2.push({ path: f.path, error: `over the ${MAX_FILE_BYTES}-byte limit` });
53985
+ else if (existsSync54(p) && !lstatSync12(p).isFile()) refused2.push({ path: f.path, error: "not a regular file" });
53986
+ else planned.push({ abs: p, rel: String(f.path), content: f.content });
53987
+ }
53988
+ if (refused2.length) return { ...ok({ ok: false, error: "refused", written: [], refused: refused2 }), isError: true };
53989
+ for (const f of planned) {
53990
+ mkdirSync26(dirname30(f.abs), { recursive: true });
53991
+ writeFileSync21(f.abs, f.content);
53992
+ }
53993
+ return ok({ ok: true, dir: app, written: planned.map((f) => f.rel) });
53994
+ }
53995
+ },
53996
+ {
53997
+ name: "himi_delete_files",
53998
+ title: "Delete app files",
53999
+ description: "Delete files (not folders) from an app folder. Nothing is deleted if any path is refused.",
54000
+ annotations: { ...WRITE_ANN, idempotentHint: false },
54001
+ inputSchema: z.object({ dir: DIR, paths: z.array(z.string().min(1)).min(1).max(MAX_FILES_PER_WRITE) }),
54002
+ handler: async (a, d) => {
54003
+ const app = await confinedAppDir(a, d);
54004
+ if (typeof app !== "string") return app;
54005
+ const paths = Array.isArray(a.paths) ? a.paths : [];
54006
+ const planned = [];
54007
+ const refused2 = [];
54008
+ for (const rel of paths) {
54009
+ const p = confinedPath(app, rel);
54010
+ if (typeof p !== "string") refused2.push({ path: rel, error: p.error });
54011
+ else if (!existsSync54(p)) refused2.push({ path: rel, error: "no such file" });
54012
+ else if (!lstatSync12(p).isFile()) refused2.push({ path: rel, error: "not a regular file" });
54013
+ else planned.push(p);
54014
+ }
54015
+ if (refused2.length) return { ...ok({ ok: false, error: "refused", deleted: [], refused: refused2 }), isError: true };
54016
+ for (const p of planned) rmSync12(p);
54017
+ return ok({ ok: true, dir: app, deleted: paths });
54018
+ }
54019
+ }
54020
+ ];
54021
+ }
54022
+ var MAX_FILE_BYTES, MAX_FILES_PER_WRITE, MAX_LISTED, RESERVED, CONTENT_MARKER, ok, refuse4, DIR, WRITE_ANN;
54023
+ var init_file_tools = __esm({
54024
+ "src/mcp/file-tools.ts"() {
54025
+ MAX_FILE_BYTES = 1024 * 1024;
54026
+ MAX_FILES_PER_WRITE = 100;
54027
+ MAX_LISTED = 2e3;
54028
+ RESERVED = /* @__PURE__ */ new Set([".git", "node_modules", "dist"]);
54029
+ CONTENT_MARKER = "himalaya.content.json";
54030
+ ok = (o) => ({ content: [{ type: "text", text: JSON.stringify(o, null, 2) }] });
54031
+ refuse4 = (error, message) => ({ content: [{ type: "text", text: JSON.stringify({ ok: false, error, message }, null, 2) }], isError: true });
54032
+ DIR = z.string().optional().describe("The app folder, relative to the workspace folder. Default: the workspace folder itself.");
54033
+ WRITE_ANN = { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false };
54034
+ }
54035
+ });
54036
+
54037
+ // src/mcp/tools.ts
54038
+ import * as z2 from "zod";
54039
+ import { resolve as resolve46 } from "node:path";
53859
54040
  function fromCli(r, extra = []) {
53860
54041
  const body = r.json !== void 0 ? JSON.stringify(r.json, null, 2) : r.text.trim();
53861
54042
  const content = [];
@@ -53867,7 +54048,7 @@ ${r.stderr.trim()}`) });
53867
54048
  }
53868
54049
  async function appDir2(args, deps) {
53869
54050
  const base = await deps.defaultDir();
53870
- return typeof args.dir === "string" && args.dir ? resolve45(base, args.dir) : base;
54051
+ return typeof args.dir === "string" && args.dir ? resolve46(base, args.dir) : base;
53871
54052
  }
53872
54053
  function loginResult(s) {
53873
54054
  switch (s.state) {
@@ -53906,8 +54087,8 @@ function guarded(h) {
53906
54087
  return h(args, deps);
53907
54088
  };
53908
54089
  }
53909
- function himiTools() {
53910
- return rawTools().map((t) => ({ ...t, handler: guarded(t.handler) }));
54090
+ function himiTools(opts = {}) {
54091
+ return [...rawTools(), ...opts.withFiles ? fileTools() : []].map((t) => ({ ...t, handler: guarded(t.handler) }));
53911
54092
  }
53912
54093
  function rawTools() {
53913
54094
  return [
@@ -53916,7 +54097,7 @@ function rawTools() {
53916
54097
  title: "Read a himi authoring guide",
53917
54098
  description: "List the Himalaya authoring guides, or read one by topic id. Offline \u2014 the guides ship with this CLI. Start here before authoring.",
53918
54099
  annotations: LEARN,
53919
- inputSchema: z.object({ topic: z.string().optional().describe("Guide id (e.g. `headless-loop`). Omit to list every guide.") }),
54100
+ inputSchema: z2.object({ topic: z2.string().optional().describe("Guide id (e.g. `headless-loop`). Omit to list every guide.") }),
53920
54101
  handler: async (a, d) => fromCli(await d.runCli(["docs", ...typeof a.topic === "string" && a.topic ? [a.topic] : [], "--json"]))
53921
54102
  },
53922
54103
  {
@@ -53924,7 +54105,7 @@ function rawTools() {
53924
54105
  title: "SDUI component vocabulary",
53925
54106
  description: "The SDUI component vocabulary and props a descriptor may use; a name returns that one component. Offline.",
53926
54107
  annotations: LEARN,
53927
- inputSchema: z.object({ name: z.string().optional().describe("One component, e.g. `Button`. Omit for all.") }),
54108
+ inputSchema: z2.object({ name: z2.string().optional().describe("One component, e.g. `Button`. Omit for all.") }),
53928
54109
  handler: async (a, d) => fromCli(await d.runCli(["components", ...typeof a.name === "string" && a.name ? [a.name] : [], "--json"]))
53929
54110
  },
53930
54111
  {
@@ -53932,7 +54113,7 @@ function rawTools() {
53932
54113
  title: "Importable @himalaya SDKs",
53933
54114
  description: "The @himalaya/* SDKs a Tier-5 worker may import; a name returns that SDK's typed API. Offline.",
53934
54115
  annotations: LEARN,
53935
- inputSchema: z.object({ name: z.string().optional().describe("One SDK, e.g. `state`. Omit for the list.") }),
54116
+ inputSchema: z2.object({ name: z2.string().optional().describe("One SDK, e.g. `state`. Omit for the list.") }),
53936
54117
  handler: async (a, d) => fromCli(await d.runCli(["sdk", ...typeof a.name === "string" && a.name ? [a.name] : [], "--json"]))
53937
54118
  },
53938
54119
  {
@@ -53940,7 +54121,7 @@ function rawTools() {
53940
54121
  title: "Icon name vocabulary",
53941
54122
  description: "The valid Icon.name values. An unknown name renders a fallback glyph and `himi_validate` warns. Offline.",
53942
54123
  annotations: LEARN,
53943
- inputSchema: z.object({}),
54124
+ inputSchema: z2.object({}),
53944
54125
  handler: async (_a, d) => fromCli(await d.runCli(["icons", "--json"]))
53945
54126
  },
53946
54127
  {
@@ -53948,14 +54129,14 @@ function rawTools() {
53948
54129
  title: "Create a new himi app",
53949
54130
  description: "Scaffold a new content package `<parentDir>/<name>` (optionally from a reference template), with its agent files and this MCP server already configured for Claude Code, Cursor, Codex and VS Code. Refuses a directory that already exists.",
53950
54131
  annotations: LOCAL_WRITE,
53951
- inputSchema: z.object({
53952
- name: z.string().min(1).describe("The app name \u2014 also its folder name."),
53953
- parentDir: z.string().optional().describe("Where to create the folder. Default: the workspace root."),
53954
- template: z.string().optional().describe("A reference template id (see `himi init --templates` in a terminal).")
54132
+ inputSchema: z2.object({
54133
+ name: z2.string().min(1).describe("The app name \u2014 also its folder name."),
54134
+ parentDir: z2.string().optional().describe("Where to create the folder. Default: the workspace root."),
54135
+ template: z2.string().optional().describe("A reference template id (see `himi init --templates` in a terminal).")
53955
54136
  }),
53956
54137
  handler: async (a, d) => {
53957
54138
  const base = await d.defaultDir();
53958
- const parent = typeof a.parentDir === "string" && a.parentDir ? resolve45(base, a.parentDir) : base;
54139
+ const parent = typeof a.parentDir === "string" && a.parentDir ? resolve46(base, a.parentDir) : base;
53959
54140
  return fromCli(await d.runCli(["init", String(a.name), "--dir", parent, ...opt("--template", a.template)]));
53960
54141
  }
53961
54142
  },
@@ -53964,7 +54145,7 @@ function rawTools() {
53964
54145
  title: "Build the app's worker bundles",
53965
54146
  description: "Compile every tier5-src/<name>/index.ts to dist/bundles/<name>.bundle.js with esbuild. Writes dist/ only.",
53966
54147
  annotations: LOCAL_WRITE,
53967
- inputSchema: z.object({ dir: DIR }),
54148
+ inputSchema: z2.object({ dir: DIR2 }),
53968
54149
  handler: async (a, d) => fromCli(await d.runCli(["build", "--content", await appDir2(a, d)]))
53969
54150
  },
53970
54151
  {
@@ -53972,7 +54153,7 @@ function rawTools() {
53972
54153
  title: "Validate the app",
53973
54154
  description: "Lint the content package without publishing: worker type-checking, schema/proto, token refs, the component allowlist, $service bindings. Run before every preview or push.",
53974
54155
  annotations: CHECK,
53975
- inputSchema: z.object({ dir: DIR, strict: z.boolean().optional().describe("Promote warnings to errors (what a push should pass).") }),
54156
+ inputSchema: z2.object({ dir: DIR2, strict: z2.boolean().optional().describe("Promote warnings to errors (what a push should pass).") }),
53976
54157
  handler: async (a, d) => fromCli(await d.runCli(["validate", "--content", await appDir2(a, d), ...sw("--strict", a.strict)]))
53977
54158
  },
53978
54159
  {
@@ -53980,10 +54161,10 @@ function rawTools() {
53980
54161
  title: "Behavioral crawl",
53981
54162
  description: "The derived behavioral crawl: boots each screen's real worker and dispatches every action its descriptor declares, against the app's mocked network (dev/net-mocks.json). Hermetic \u2014 never reaches live Wix. Catches the wrong-reducer class validate and render pass clean.",
53982
54163
  annotations: CHECK,
53983
- inputSchema: z.object({
53984
- dir: DIR,
53985
- screens: z.array(z.string()).optional().describe("Only these screen ids. Omit for all."),
53986
- deep: z.boolean().optional().describe("Also follow navigation into the screens actions open.")
54164
+ inputSchema: z2.object({
54165
+ dir: DIR2,
54166
+ screens: z2.array(z2.string()).optional().describe("Only these screen ids. Omit for all."),
54167
+ deep: z2.boolean().optional().describe("Also follow navigation into the screens actions open.")
53987
54168
  }),
53988
54169
  handler: async (a, d) => {
53989
54170
  const screens = Array.isArray(a.screens) ? a.screens.filter((s) => typeof s === "string") : [];
@@ -53995,13 +54176,13 @@ function rawTools() {
53995
54176
  title: "Render a screen to PNG",
53996
54177
  description: "Headless-render one screen with the web renderer and return the PNG plus the render diagnostics. The PNG is also written to .himi/shots/<screen>.png, which the build board shows. Needs Playwright's Chromium; without it the result says how to install it and still returns the diagnostics.",
53997
54178
  annotations: CHECK,
53998
- inputSchema: z.object({
53999
- screen: z.string().min(1).describe("The screen id."),
54000
- dir: DIR,
54001
- scheme: z.enum(["light", "dark"]).optional(),
54002
- width: z.number().int().positive().optional().describe("Viewport width in px."),
54003
- device: z.string().optional().describe("A named device (overrides width)."),
54004
- rtl: z.boolean().optional()
54179
+ inputSchema: z2.object({
54180
+ screen: z2.string().min(1).describe("The screen id."),
54181
+ dir: DIR2,
54182
+ scheme: z2.enum(["light", "dark"]).optional(),
54183
+ width: z2.number().int().positive().optional().describe("Viewport width in px."),
54184
+ device: z2.string().optional().describe("A named device (overrides width)."),
54185
+ rtl: z2.boolean().optional()
54005
54186
  }),
54006
54187
  handler: async (a, d) => {
54007
54188
  const r = await d.runCli([
@@ -54031,12 +54212,12 @@ function rawTools() {
54031
54212
  title: "Build journal",
54032
54213
  description: "Read or append the owner-facing build journal (.himi/progress.jsonl). With `message`, append one postcard for a journey step; without, print the journal \u2014 `brief` gives the short session-start summary (current step, open approvals).",
54033
54214
  annotations: { ...LOCAL_WRITE, idempotentHint: false },
54034
- inputSchema: z.object({
54035
- dir: DIR,
54036
- message: z.string().optional().describe("What changed, one or two lines, for the owner."),
54037
- step: z.string().optional().describe("Journey step 1-8 or its name (discover, classify, plan, implement, brand, validate, review, download)."),
54038
- noImage: z.boolean().optional().describe("Send a text-only postcard. By default the home screen's current shot is attached (never a stale one)."),
54039
- brief: z.boolean().optional()
54215
+ inputSchema: z2.object({
54216
+ dir: DIR2,
54217
+ message: z2.string().optional().describe("What changed, one or two lines, for the owner."),
54218
+ step: z2.string().optional().describe("Journey step 1-8 or its name (discover, classify, plan, implement, brand, validate, review, download)."),
54219
+ noImage: z2.boolean().optional().describe("Send a text-only postcard. By default the home screen's current shot is attached (never a stale one)."),
54220
+ brief: z2.boolean().optional()
54040
54221
  }),
54041
54222
  handler: async (a, d) => {
54042
54223
  const dir = await appDir2(a, d);
@@ -54049,7 +54230,7 @@ function rawTools() {
54049
54230
  title: "Start the live preview",
54050
54231
  description: "Serve the app on localhost and keep it live (`himi run --watch`): every save rebuilds and repaints the open tab. Returns the URL. Reuses a preview that is already running for this app. " + PREVIEW_HINT,
54051
54232
  annotations: LOCAL_WRITE,
54052
- inputSchema: z.object({ dir: DIR }),
54233
+ inputSchema: z2.object({ dir: DIR2 }),
54053
54234
  handler: async (a, d) => {
54054
54235
  try {
54055
54236
  return json3({ ...await d.preview.start(await appDir2(a, d)), hint: PREVIEW_HINT });
@@ -54066,7 +54247,7 @@ ${log}` : ""}`, true);
54066
54247
  title: "Live preview status",
54067
54248
  description: "Whether this app's live preview is running, and its URL and last build result.",
54068
54249
  annotations: CHECK,
54069
- inputSchema: z.object({ dir: DIR }),
54250
+ inputSchema: z2.object({ dir: DIR2 }),
54070
54251
  handler: async (a, d) => json3(await d.preview.status(await appDir2(a, d)))
54071
54252
  },
54072
54253
  {
@@ -54074,7 +54255,7 @@ ${log}` : ""}`, true);
54074
54255
  title: "Stop the live preview",
54075
54256
  description: "Stop this app's live preview (the `himi run --watch` a `himi_preview_start` started).",
54076
54257
  annotations: { ...LOCAL_WRITE, destructiveHint: false },
54077
- inputSchema: z.object({ dir: DIR }),
54258
+ inputSchema: z2.object({ dir: DIR2 }),
54078
54259
  handler: async (a, d) => json3(await d.preview.stop(await appDir2(a, d)))
54079
54260
  },
54080
54261
  {
@@ -54082,7 +54263,7 @@ ${log}` : ""}`, true);
54082
54263
  title: "Signed-in identity",
54083
54264
  description: "The identity the stored serve-plane credential carries (account, scope, expiry). Local \u2014 decodes the stored token, no network.",
54084
54265
  annotations: LEARN,
54085
- inputSchema: z.object({ target: z.string().optional().describe("Serve target. Default: the CLI's default.") }),
54266
+ inputSchema: z2.object({ target: z2.string().optional().describe("Serve target. Default: the CLI's default.") }),
54086
54267
  handler: async (a, d) => fromCli(await d.runCli(["whoami", ...opt("--target", a.target ?? d.login.target())]))
54087
54268
  },
54088
54269
  {
@@ -54090,9 +54271,9 @@ ${log}` : ""}`, true);
54090
54271
  title: "Sign in to Wix",
54091
54272
  description: "Open a browser window where the USER signs in to Wix, so himi_push and himi_share can publish. Returns at once with the sign-in link; call again to see whether the sign-in finished. Already signed in: says who, and opens nothing unless `switchAccount` is true. This server never sees the credential \u2014 the sign-in stores a scoped token on this machine.",
54092
54273
  annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
54093
- inputSchema: z.object({
54094
- target: z.string().optional().describe("Serve target. Default: the CLI's default."),
54095
- switchAccount: z.boolean().optional().describe("Sign in again even though a credential is stored (e.g. to use another Wix account).")
54274
+ inputSchema: z2.object({
54275
+ target: z2.string().optional().describe("Serve target. Default: the CLI's default."),
54276
+ switchAccount: z2.boolean().optional().describe("Sign in again even though a credential is stored (e.g. to use another Wix account).")
54096
54277
  }),
54097
54278
  handler: async (a, d) => {
54098
54279
  const s = d.login.status();
@@ -54112,10 +54293,10 @@ ${log}` : ""}`, true);
54112
54293
  title: "Publish a draft",
54113
54294
  description: "Lint, build and publish the app as a DRAFT release: owner-private, servable by preview link and in Himi Player, NOT live. Returns the preview links and the universal link that opens it in Himi Player. Never promotes \u2014 going live is a human command. Refuses on any validation error. Needs a sign-in first (himi_login).",
54114
54295
  annotations: PUBLISH,
54115
- inputSchema: z.object({
54116
- dir: DIR,
54117
- label: z.string().optional().describe("A short label for this draft."),
54118
- notes: z.string().optional().describe("Release notes for this draft.")
54296
+ inputSchema: z2.object({
54297
+ dir: DIR2,
54298
+ label: z2.string().optional().describe("A short label for this draft."),
54299
+ notes: z2.string().optional().describe("Release notes for this draft.")
54119
54300
  }),
54120
54301
  handler: async (a, d) => {
54121
54302
  const gate = await requireLogin(d);
@@ -54128,14 +54309,14 @@ ${log}` : ""}`, true);
54128
54309
  title: "Share a .himi package link",
54129
54310
  description: "Publish a content-addressed share link for a validated `.himi` package of an already-published release. Needs a sign-in first (himi_login).",
54130
54311
  annotations: PUBLISH,
54131
- inputSchema: z.object({
54132
- file: z.string().min(1).describe("Path to the .himi package (see `himi pack`)."),
54133
- expiresAt: z.string().optional().describe("ISO timestamp the link stops working.")
54312
+ inputSchema: z2.object({
54313
+ file: z2.string().min(1).describe("Path to the .himi package (see `himi pack`)."),
54314
+ expiresAt: z2.string().optional().describe("ISO timestamp the link stops working.")
54134
54315
  }),
54135
54316
  handler: async (a, d) => {
54136
54317
  const gate = await requireLogin(d);
54137
54318
  if (gate) return gate;
54138
- return fromCli(await d.runCli(["share", "--file", resolve45(await d.defaultDir(), String(a.file)), ...opt("--expires-at", a.expiresAt), ...opt("--target", d.login.target())]));
54319
+ return fromCli(await d.runCli(["share", "--file", resolve46(await d.defaultDir(), String(a.file)), ...opt("--expires-at", a.expiresAt), ...opt("--target", d.login.target())]));
54139
54320
  }
54140
54321
  },
54141
54322
  {
@@ -54145,19 +54326,20 @@ ${log}` : ""}`, true);
54145
54326
  // Not idempotent: with credentials, each `himi preview` mints a fresh single-use handover —
54146
54327
  // the same reason the hosted connector's tool of this name says false (RFC 0064 §5).
54147
54328
  annotations: { ...PUBLISH, readOnlyHint: true, idempotentHint: false },
54148
- inputSchema: z.object({
54149
- app: z.string().min(1),
54150
- release: z.string().min(1),
54151
- screen: z.string().optional(),
54152
- surface: z.string().optional()
54329
+ inputSchema: z2.object({
54330
+ app: z2.string().min(1),
54331
+ release: z2.string().min(1),
54332
+ screen: z2.string().optional(),
54333
+ surface: z2.string().optional()
54153
54334
  }),
54154
54335
  handler: async (a, d) => fromCli(await d.runCli(["preview", "--app", String(a.app), "--release", String(a.release), ...opt("--screen", a.screen), ...opt("--surface", a.surface), ...opt("--target", d.login.target())]))
54155
54336
  }
54156
54337
  ];
54157
54338
  }
54158
- var MAX_TEXT2, clip, text6, json3, opt, sw, DIR, LEARN, CHECK, LOCAL_WRITE, PUBLISH, PREVIEW_HINT, LOGIN_HINT;
54339
+ var MAX_TEXT2, clip, text6, json3, opt, sw, DIR2, LEARN, CHECK, LOCAL_WRITE, PUBLISH, PREVIEW_HINT, LOGIN_HINT;
54159
54340
  var init_tools = __esm({
54160
54341
  "src/mcp/tools.ts"() {
54342
+ init_file_tools();
54161
54343
  MAX_TEXT2 = 8e4;
54162
54344
  clip = (s) => s.length <= MAX_TEXT2 ? s : `${s.slice(0, MAX_TEXT2)}
54163
54345
  \u2026 [truncated ${s.length - MAX_TEXT2} chars \u2014 re-run the command in a terminal for the full output]`;
@@ -54165,7 +54347,7 @@ var init_tools = __esm({
54165
54347
  json3 = (o) => text6(JSON.stringify(o, null, 2));
54166
54348
  opt = (flag, v) => typeof v === "string" && v ? [flag, v] : typeof v === "number" ? [flag, String(v)] : [];
54167
54349
  sw = (flag, v) => v === true ? [flag] : [];
54168
- DIR = z.string().optional().describe("The app (content package) directory. Default: the workspace root the host opened, else the server's working directory.");
54350
+ DIR2 = z2.string().optional().describe("The app (content package) directory. Default: the workspace root the host opened, else the server's working directory.");
54169
54351
  LEARN = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
54170
54352
  CHECK = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
54171
54353
  LOCAL_WRITE = { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false };
@@ -54194,12 +54376,12 @@ function createLoginSession(deps) {
54194
54376
  current = pending;
54195
54377
  const out2 = [];
54196
54378
  const err = [];
54197
- return new Promise((resolve53) => {
54379
+ return new Promise((resolve54) => {
54198
54380
  let answered = false;
54199
54381
  const answer = () => {
54200
54382
  if (answered) return;
54201
54383
  answered = true;
54202
- resolve53(current);
54384
+ resolve54(current);
54203
54385
  };
54204
54386
  let child;
54205
54387
  try {
@@ -54258,7 +54440,7 @@ __export(server_exports, {
54258
54440
  protectStdout: () => protectStdout,
54259
54441
  startMcpServer: () => startMcpServer
54260
54442
  });
54261
- import { readFileSync as readFileSync59 } from "node:fs";
54443
+ import { readFileSync as readFileSync60 } from "node:fs";
54262
54444
  import { fileURLToPath as fileURLToPath21 } from "node:url";
54263
54445
  import { McpServer } from "@modelcontextprotocol/server";
54264
54446
  import { serveStdio, StdioServerTransport } from "@modelcontextprotocol/server/stdio";
@@ -54268,9 +54450,9 @@ function protectStdout() {
54268
54450
  console.info = toErr;
54269
54451
  console.debug = toErr;
54270
54452
  }
54271
- function buildServer(deps, version2) {
54453
+ function buildServer(deps, version2, tools = {}) {
54272
54454
  const server = new McpServer({ name: "himi", version: version2 }, { capabilities: { tools: {} }, instructions: SERVER_INSTRUCTIONS });
54273
- for (const tool of himiTools()) {
54455
+ for (const tool of himiTools(tools)) {
54274
54456
  server.registerTool(
54275
54457
  tool.name,
54276
54458
  { title: tool.title, description: tool.description, inputSchema: tool.inputSchema, annotations: { title: tool.title, ...tool.annotations } },
@@ -54304,23 +54486,23 @@ async function startMcpServer(opts) {
54304
54486
  // next call rather than pinning every later tool to the server's cwd (often $HOME for a GUI host).
54305
54487
  defaultDir: async () => {
54306
54488
  if (!rootDir && pinned) rootDir = await firstRoot(pinned);
54307
- return rootDir || process.cwd();
54489
+ return rootDir || opts.workspace || process.cwd();
54308
54490
  },
54309
54491
  preview: {
54310
54492
  start: (dir) => startPreview(dir, { port: previewPortForDir(dir) }, previewDeps),
54311
54493
  status: (dir) => previewStatus(dir, previewDeps),
54312
54494
  stop: (dir) => stopPreview(dir, previewDeps)
54313
54495
  },
54314
- readFile: (p) => readFileSync59(p),
54496
+ readFile: (p) => readFileSync60(p),
54315
54497
  login: createLoginSession({ ...defaultLoginDeps, selfCommand: previewDeps.selfCommand, ...opts.login })
54316
54498
  };
54317
- const closed = new Promise((resolve53) => {
54318
- stdin.once("end", resolve53);
54319
- stdin.once("close", resolve53);
54499
+ const closed = new Promise((resolve54) => {
54500
+ stdin.once("end", resolve54);
54501
+ stdin.once("close", resolve54);
54320
54502
  });
54321
54503
  const handle = serveStdio(
54322
54504
  () => {
54323
- pinned = buildServer(deps, opts.version);
54505
+ pinned = buildServer(deps, opts.version, { withFiles: opts.withFiles });
54324
54506
  return pinned;
54325
54507
  },
54326
54508
  { transport: new StdioServerTransport(stdin, stdout), onerror: (e) => console.error(`[himi mcp] ${e.message}`) }
@@ -54354,9 +54536,9 @@ __export(native_decode_exports, {
54354
54536
  runNativeDecode: () => runNativeDecode
54355
54537
  });
54356
54538
  import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
54357
- import { existsSync as existsSync54, mkdtempSync as mkdtempSync2, readFileSync as readFileSync60, rmSync as rmSync12, writeFileSync as writeFileSync21 } from "node:fs";
54539
+ import { existsSync as existsSync55, mkdtempSync as mkdtempSync2, readFileSync as readFileSync61, rmSync as rmSync13, writeFileSync as writeFileSync22 } from "node:fs";
54358
54540
  import { tmpdir as tmpdir3 } from "node:os";
54359
- import { join as join53 } from "node:path";
54541
+ import { join as join54 } from "node:path";
54360
54542
  import { fileURLToPath as fileURLToPath22 } from "node:url";
54361
54543
  function nativeDecodePackageDir() {
54362
54544
  return fileURLToPath22(new URL("../../../core/runtime/ios/HimalayaCore/", import.meta.url));
@@ -54366,8 +54548,8 @@ function nativeDecodeAndroidHarnessDir() {
54366
54548
  }
54367
54549
  function nativeOracleShipped() {
54368
54550
  return {
54369
- ios: existsSync54(join53(nativeDecodePackageDir(), "Package.swift")),
54370
- android: existsSync54(join53(nativeDecodeAndroidHarnessDir(), "gradlew"))
54551
+ ios: existsSync55(join54(nativeDecodePackageDir(), "Package.swift")),
54552
+ android: existsSync55(join54(nativeDecodeAndroidHarnessDir(), "gradlew"))
54371
54553
  };
54372
54554
  }
54373
54555
  function detectNativeDecode(options = {}) {
@@ -54378,7 +54560,7 @@ function detectNativeDecode(options = {}) {
54378
54560
  return { platform: "ios", available: false, reason: `the iOS decoder oracle requires macOS (darwin); this host is ${hostPlatform}` };
54379
54561
  }
54380
54562
  if (!swiftAvailable) return { platform: "ios", available: false, reason: "swift is not on PATH" };
54381
- const packageAvailable = options.packageAvailable ?? existsSync54(join53(packageDir, "Package.swift"));
54563
+ const packageAvailable = options.packageAvailable ?? existsSync55(join54(packageDir, "Package.swift"));
54382
54564
  if (!packageAvailable) {
54383
54565
  return {
54384
54566
  platform: "ios",
@@ -54390,7 +54572,7 @@ function detectNativeDecode(options = {}) {
54390
54572
  }
54391
54573
  function localPropertiesSdk(harnessDir) {
54392
54574
  try {
54393
- const match = readFileSync60(join53(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
54575
+ const match = readFileSync61(join54(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
54394
54576
  return match?.[1]?.trim().replace(/\\([ :\\])/g, "$1") ?? null;
54395
54577
  } catch {
54396
54578
  return null;
@@ -54398,8 +54580,8 @@ function localPropertiesSdk(harnessDir) {
54398
54580
  }
54399
54581
  function detectAndroidNativeDecode(options = {}) {
54400
54582
  const harnessDir = options.harnessDir ?? nativeDecodeAndroidHarnessDir();
54401
- const gradlew = join53(harnessDir, "gradlew");
54402
- const gradlewAvailable = options.gradlewAvailable ?? existsSync54(gradlew);
54583
+ const gradlew = join54(harnessDir, "gradlew");
54584
+ const gradlewAvailable = options.gradlewAvailable ?? existsSync55(gradlew);
54403
54585
  if (!gradlewAvailable) {
54404
54586
  return {
54405
54587
  platform: "android",
@@ -54409,7 +54591,7 @@ function detectAndroidNativeDecode(options = {}) {
54409
54591
  }
54410
54592
  const androidHome = options.androidHome ?? process.env.ANDROID_HOME ?? "";
54411
54593
  const sdk = androidHome.trim() || (options.localPropertiesSdk !== void 0 ? options.localPropertiesSdk : localPropertiesSdk(harnessDir));
54412
- const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync54(sdk));
54594
+ const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync55(sdk));
54413
54595
  if (!sdkAvailable) {
54414
54596
  return {
54415
54597
  platform: "android",
@@ -54481,14 +54663,14 @@ function parseNativeDecodeOutput(stdout, expectedScreenIds, platform = "ios") {
54481
54663
  return verdicts;
54482
54664
  }
54483
54665
  function runNativeDecode(options) {
54484
- const descriptorDir = mkdtempSync2(join53(tmpdir3(), "himi-native-decode-"));
54666
+ const descriptorDir = mkdtempSync2(join54(tmpdir3(), "himi-native-decode-"));
54485
54667
  const startedAt = Date.now();
54486
54668
  try {
54487
54669
  for (const descriptor of options.descriptors) {
54488
54670
  if (typeof descriptor.descriptorJson !== "string") {
54489
54671
  throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
54490
54672
  }
54491
- writeFileSync21(join53(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
54673
+ writeFileSync22(join54(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
54492
54674
  }
54493
54675
  options.progress?.("building cached Swift oracle");
54494
54676
  execFileSync5("swift", ["build", "--package-path", options.packageDir, "--product", "himi-decode-oracle"], {
@@ -54500,7 +54682,7 @@ function runNativeDecode(options) {
54500
54682
  encoding: "utf8"
54501
54683
  }).trim();
54502
54684
  options.progress?.(`running real Swift decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
54503
- const stdout = execFileSync5(join53(binPath, "himi-decode-oracle"), ["--dir", descriptorDir], {
54685
+ const stdout = execFileSync5(join54(binPath, "himi-decode-oracle"), ["--dir", descriptorDir], {
54504
54686
  stdio: ["ignore", "pipe", "pipe"],
54505
54687
  encoding: "utf8"
54506
54688
  });
@@ -54514,19 +54696,19 @@ function runNativeDecode(options) {
54514
54696
  const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
54515
54697
  throw new Error(`iOS decoder oracle failed: ${failure.message}${stderr}`);
54516
54698
  } finally {
54517
- rmSync12(descriptorDir, { recursive: true, force: true });
54699
+ rmSync13(descriptorDir, { recursive: true, force: true });
54518
54700
  }
54519
54701
  }
54520
54702
  function runAndroidNativeDecode(options) {
54521
- const descriptorDir = mkdtempSync2(join53(tmpdir3(), "himi-native-decode-android-"));
54522
- const outputPath = join53(descriptorDir, "verdicts.ndjson");
54703
+ const descriptorDir = mkdtempSync2(join54(tmpdir3(), "himi-native-decode-android-"));
54704
+ const outputPath = join54(descriptorDir, "verdicts.ndjson");
54523
54705
  const startedAt = Date.now();
54524
54706
  try {
54525
54707
  for (const descriptor of options.descriptors) {
54526
54708
  if (typeof descriptor.descriptorJson !== "string") {
54527
54709
  throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
54528
54710
  }
54529
- writeFileSync21(join53(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
54711
+ writeFileSync22(join54(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
54530
54712
  }
54531
54713
  options.progress?.(`running real Kotlin decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
54532
54714
  execFileSync5(options.gradlew, [
@@ -54541,7 +54723,7 @@ function runAndroidNativeDecode(options) {
54541
54723
  stdio: ["ignore", "ignore", "pipe"],
54542
54724
  encoding: "utf8"
54543
54725
  });
54544
- const stdout = readFileSync60(outputPath, "utf8");
54726
+ const stdout = readFileSync61(outputPath, "utf8");
54545
54727
  return {
54546
54728
  platform: "android",
54547
54729
  verdicts: parseNativeDecodeOutput(stdout, options.descriptors.map((descriptor) => descriptor.screenId), "android"),
@@ -54552,7 +54734,7 @@ function runAndroidNativeDecode(options) {
54552
54734
  const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
54553
54735
  throw new Error(`Android decoder oracle failed: ${failure.message}${stderr}`);
54554
54736
  } finally {
54555
- rmSync12(descriptorDir, { recursive: true, force: true });
54737
+ rmSync13(descriptorDir, { recursive: true, force: true });
54556
54738
  }
54557
54739
  }
54558
54740
  function fieldAt(path2) {
@@ -54611,30 +54793,30 @@ __export(browser_authoring_exports, {
54611
54793
  });
54612
54794
  import { createServer as createServer5 } from "node:http";
54613
54795
  import { createHash as createHash29, randomBytes as randomBytes4 } from "node:crypto";
54614
- import { existsSync as existsSync55, readdirSync as readdirSync27, readFileSync as readFileSync61, realpathSync as realpathSync7, statSync as statSync13 } from "node:fs";
54615
- import { join as join54, posix as posix2, relative as relative11, sep as sep14 } from "node:path";
54796
+ import { existsSync as existsSync56, readdirSync as readdirSync28, readFileSync as readFileSync62, realpathSync as realpathSync8, statSync as statSync14 } from "node:fs";
54797
+ import { join as join55, posix as posix2, relative as relative12, sep as sep15 } from "node:path";
54616
54798
  function humanMs(ms) {
54617
54799
  return ms < 1e3 ? `${ms}ms` : `${Math.round(ms / 1e3)}s`;
54618
54800
  }
54619
54801
  function collectWorkerSources(tier5SrcDir, bundleName) {
54620
- const root = join54(tier5SrcDir, bundleName);
54802
+ const root = join55(tier5SrcDir, bundleName);
54621
54803
  const files = {};
54622
54804
  const visitedDirs = /* @__PURE__ */ new Set();
54623
54805
  const walk2 = (abs, rel) => {
54624
- const real = realpathSync7(abs);
54806
+ const real = realpathSync8(abs);
54625
54807
  if (visitedDirs.has(real)) return;
54626
54808
  visitedDirs.add(real);
54627
- for (const name of readdirSync27(abs).sort()) {
54628
- const childAbs = join54(abs, name);
54809
+ for (const name of readdirSync28(abs).sort()) {
54810
+ const childAbs = join55(abs, name);
54629
54811
  const childRel = posix2.join(rel, name);
54630
- if (statSync13(childAbs).isDirectory()) {
54812
+ if (statSync14(childAbs).isDirectory()) {
54631
54813
  walk2(childAbs, childRel);
54632
54814
  } else if (/\.(ts|tsx|js|mjs|json)$/.test(name)) {
54633
- files[childRel] = readFileSync61(childAbs, "utf8");
54815
+ files[childRel] = readFileSync62(childAbs, "utf8");
54634
54816
  }
54635
54817
  }
54636
54818
  };
54637
- if (!existsSync55(root)) return null;
54819
+ if (!existsSync56(root)) return null;
54638
54820
  walk2(root, `/tier5-src/${bundleName}`);
54639
54821
  const entry = [`/tier5-src/${bundleName}/index.ts`, `/tier5-src/${bundleName}/index.js`].find((p) => p in files);
54640
54822
  if (!entry) return null;
@@ -54651,20 +54833,20 @@ function collectRelativeSiblings(files, tier5SrcDir) {
54651
54833
  const spec = m[1];
54652
54834
  const virtual = posix2.normalize(posix2.join(dir, spec));
54653
54835
  if (!virtual.startsWith("/tier5-src/")) continue;
54654
- const onDisk = join54(tier5SrcDir, virtual.slice("/tier5-src/".length));
54836
+ const onDisk = join55(tier5SrcDir, virtual.slice("/tier5-src/".length));
54655
54837
  const candidates = [
54656
54838
  onDisk,
54657
54839
  `${onDisk}.ts`,
54658
54840
  `${onDisk}.js`,
54659
54841
  onDisk.replace(/\.js$/, ".ts"),
54660
- join54(onDisk, "index.ts"),
54661
- join54(onDisk, "index.js")
54842
+ join55(onDisk, "index.ts"),
54843
+ join55(onDisk, "index.js")
54662
54844
  ];
54663
54845
  for (const abs of candidates) {
54664
- if (!existsSync55(abs) || statSync13(abs).isDirectory()) continue;
54665
- const key2 = `/tier5-src/${relative11(tier5SrcDir, abs).split(sep14).join(posix2.sep)}`;
54846
+ if (!existsSync56(abs) || statSync14(abs).isDirectory()) continue;
54847
+ const key2 = `/tier5-src/${relative12(tier5SrcDir, abs).split(sep15).join(posix2.sep)}`;
54666
54848
  if (key2 in files) break;
54667
- files[key2] = readFileSync61(abs, "utf8");
54849
+ files[key2] = readFileSync62(abs, "utf8");
54668
54850
  queue.push(key2);
54669
54851
  break;
54670
54852
  }
@@ -54696,10 +54878,10 @@ function collectSdkModules(files, resolveSubpath) {
54696
54878
  for (const source of Object.values(files)) visit(source);
54697
54879
  return { modules, unsupported };
54698
54880
  }
54699
- function sdkSubpathReader(resolve53) {
54881
+ function sdkSubpathReader(resolve54) {
54700
54882
  return (sub) => {
54701
54883
  try {
54702
- return readFileSync61(resolve53(`@wix/himalaya/${sub}`), "utf8");
54884
+ return readFileSync62(resolve54(`@wix/himalaya/${sub}`), "utf8");
54703
54885
  } catch {
54704
54886
  return null;
54705
54887
  }
@@ -54777,7 +54959,7 @@ async function runBrowserAuthoring(opts) {
54777
54959
  const token = mintToken2(payload);
54778
54960
  const unusable = await probeAuthoringPage(opts.authoringBase, opts.fetchImpl, opts.probeTimeoutMs);
54779
54961
  if (unusable) throw new Error(unusable);
54780
- return await new Promise((resolve53, reject) => {
54962
+ return await new Promise((resolve54, reject) => {
54781
54963
  let settled = false;
54782
54964
  let url = "";
54783
54965
  const server = createServer5();
@@ -54829,7 +55011,7 @@ async function runBrowserAuthoring(opts) {
54829
55011
  }
54830
55012
  res.writeHead(200, { "content-type": "text/plain" }).end("ok");
54831
55013
  const report3 = body.result;
54832
- finish2(() => resolve53({ report: report3, url }));
55014
+ finish2(() => resolve54({ report: report3, url }));
54833
55015
  })();
54834
55016
  });
54835
55017
  server.on("error", (e) => finish2(() => reject(e)));
@@ -54871,8 +55053,8 @@ __export(coverage_exports, {
54871
55053
  suppressedNativeKeys: () => suppressedNativeKeys,
54872
55054
  trendAndStore: () => trendAndStore
54873
55055
  });
54874
- import { existsSync as existsSync56, mkdirSync as mkdirSync26, readFileSync as readFileSync62, writeFileSync as writeFileSync22 } from "node:fs";
54875
- import { dirname as dirname30, join as join55 } from "node:path";
55056
+ import { existsSync as existsSync57, mkdirSync as mkdirSync27, readFileSync as readFileSync63, writeFileSync as writeFileSync23 } from "node:fs";
55057
+ import { dirname as dirname31, join as join56 } from "node:path";
54876
55058
  function suppressedNativeKeys(oracle) {
54877
55059
  return [...oracle.ios ? [] : ["native-decode|ios"], ...oracle.android ? [] : ["native-decode|android"]];
54878
55060
  }
@@ -55052,11 +55234,11 @@ function assembleLedger(r, options = {}) {
55052
55234
  return out2;
55053
55235
  }
55054
55236
  function trendAndStore(dir, entries, suppressed) {
55055
- const p = join55(dir, LEDGER_FILE);
55237
+ const p = join56(dir, LEDGER_FILE);
55056
55238
  let previous = null;
55057
55239
  try {
55058
- if (existsSync56(p)) {
55059
- const parsed = JSON.parse(readFileSync62(p, "utf8"));
55240
+ if (existsSync57(p)) {
55241
+ const parsed = JSON.parse(readFileSync63(p, "utf8"));
55060
55242
  if (Array.isArray(parsed.keys)) previous = parsed.keys.filter((k) => typeof k === "string");
55061
55243
  }
55062
55244
  } catch {
@@ -55064,8 +55246,8 @@ function trendAndStore(dir, entries, suppressed) {
55064
55246
  const current = entries.map((e) => e.key);
55065
55247
  const stored = [.../* @__PURE__ */ new Set([...current, ...(previous ?? []).filter((key2) => (suppressed ?? []).includes(key2))])];
55066
55248
  try {
55067
- mkdirSync26(dirname30(p), { recursive: true });
55068
- writeFileSync22(p, JSON.stringify({ keys: stored, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
55249
+ mkdirSync27(dirname31(p), { recursive: true });
55250
+ writeFileSync23(p, JSON.stringify({ keys: stored, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
55069
55251
  } catch {
55070
55252
  return null;
55071
55253
  }
@@ -55095,11 +55277,11 @@ function formatLedger(entries, trend) {
55095
55277
  return out2.join("\n");
55096
55278
  }
55097
55279
  function diffAndStoreObservations(dir, current) {
55098
- const p = join55(dir, OBS_FILE);
55280
+ const p = join56(dir, OBS_FILE);
55099
55281
  let previous = null;
55100
55282
  try {
55101
- if (existsSync56(p)) {
55102
- const parsed = JSON.parse(readFileSync62(p, "utf8"));
55283
+ if (existsSync57(p)) {
55284
+ const parsed = JSON.parse(readFileSync63(p, "utf8"));
55103
55285
  if (parsed.screens && typeof parsed.screens === "object" && !Array.isArray(parsed.screens) && Object.values(parsed.screens).every(
55104
55286
  (v) => Array.isArray(v) && v.every((l) => typeof l === "string")
55105
55287
  )) {
@@ -55109,8 +55291,8 @@ function diffAndStoreObservations(dir, current) {
55109
55291
  } catch {
55110
55292
  }
55111
55293
  try {
55112
- mkdirSync26(dirname30(p), { recursive: true });
55113
- writeFileSync22(p, JSON.stringify({ screens: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
55294
+ mkdirSync27(dirname31(p), { recursive: true });
55295
+ writeFileSync23(p, JSON.stringify({ screens: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
55114
55296
  } catch {
55115
55297
  return null;
55116
55298
  }
@@ -55148,8 +55330,8 @@ var LEDGER_FILE, OBS_FILE;
55148
55330
  var init_coverage = __esm({
55149
55331
  "src/coverage.ts"() {
55150
55332
  init_native_decode();
55151
- LEDGER_FILE = join55(".himi", "test-ledger.json");
55152
- OBS_FILE = join55(".himi", "test-observations.json");
55333
+ LEDGER_FILE = join56(".himi", "test-ledger.json");
55334
+ OBS_FILE = join56(".himi", "test-observations.json");
55153
55335
  }
55154
55336
  });
55155
55337
 
@@ -55160,16 +55342,16 @@ __export(design_kits_exports, {
55160
55342
  kitsDir: () => kitsDir,
55161
55343
  listKits: () => listKits2
55162
55344
  });
55163
- import { existsSync as existsSync57, readFileSync as readFileSync63, readdirSync as readdirSync28 } from "node:fs";
55164
- import { join as join56, basename as basename15 } from "node:path";
55345
+ import { existsSync as existsSync58, readFileSync as readFileSync64, readdirSync as readdirSync29 } from "node:fs";
55346
+ import { join as join57, basename as basename15 } from "node:path";
55165
55347
  import { fileURLToPath as fileURLToPath23 } from "node:url";
55166
55348
  function kitsDir() {
55167
- return KIT_DIR_CANDIDATES.find((p) => existsSync57(p));
55349
+ return KIT_DIR_CANDIDATES.find((p) => existsSync58(p));
55168
55350
  }
55169
55351
  function listKits2() {
55170
55352
  const dir = kitsDir();
55171
55353
  if (!dir) return [];
55172
- return readdirSync28(dir).filter((f) => f.endsWith(".json")).map((f) => basename15(f, ".json")).sort();
55354
+ return readdirSync29(dir).filter((f) => f.endsWith(".json")).map((f) => basename15(f, ".json")).sort();
55173
55355
  }
55174
55356
  function kitReport(name) {
55175
55357
  const dir = kitsDir();
@@ -55188,7 +55370,7 @@ In a published @wix/himalaya-cli this is a packaging bug \u2014 the kits should
55188
55370
  if (!kits.includes(name)) {
55189
55371
  return { ok: false, kit: name, kits, problems: [`no design kit named "${name}". Available: ${kits.join(", ")}`] };
55190
55372
  }
55191
- const raw = readFileSync63(join56(dir, `${name}.json`), "utf8");
55373
+ const raw = readFileSync64(join57(dir, `${name}.json`), "utf8");
55192
55374
  let parsed;
55193
55375
  try {
55194
55376
  parsed = JSON.parse(raw);
@@ -55212,9 +55394,9 @@ var init_design_kits = __esm({
55212
55394
  "src/design-kits.ts"() {
55213
55395
  KIT_DIR_CANDIDATES = [
55214
55396
  // in-repo: tools/himi-cli/src/design-kits.ts → <repo>/stdlib/design-kits/
55215
- join56(fileURLToPath23(new URL("../../..", import.meta.url)), "stdlib", "design-kits"),
55397
+ join57(fileURLToPath23(new URL("../../..", import.meta.url)), "stdlib", "design-kits"),
55216
55398
  // published CLI: <pkg>/dist/cli.mjs → <pkg>/stdlib/design-kits/
55217
- join56(fileURLToPath23(new URL("..", import.meta.url)), "stdlib", "design-kits")
55399
+ join57(fileURLToPath23(new URL("..", import.meta.url)), "stdlib", "design-kits")
55218
55400
  ];
55219
55401
  }
55220
55402
  });
@@ -55228,11 +55410,11 @@ __export(assets_exports, {
55228
55410
  removeAssetPayload: () => removeAssetPayload,
55229
55411
  verifyReport: () => verifyReport
55230
55412
  });
55231
- import { readFileSync as readFileSync64 } from "node:fs";
55413
+ import { readFileSync as readFileSync65 } from "node:fs";
55232
55414
  import { basename as basename16 } from "node:path";
55233
55415
  function declaredAssets(dir) {
55234
55416
  return collectAssets(dir).map((a) => {
55235
- const bytes2 = readFileSync64(a.path);
55417
+ const bytes2 = readFileSync65(a.path);
55236
55418
  return {
55237
55419
  name: a.name,
55238
55420
  sha256: assetSha256(bytes2),
@@ -55309,7 +55491,7 @@ function verifyReport(dir, app, manifest) {
55309
55491
  };
55310
55492
  }
55311
55493
  function addAssetPayload(manifest, filePath, opts) {
55312
- const bytes2 = readFileSync64(filePath);
55494
+ const bytes2 = readFileSync65(filePath);
55313
55495
  const name = opts.name ?? basename16(filePath);
55314
55496
  const sha2565 = assetSha256(bytes2);
55315
55497
  const record2 = {
@@ -57033,9 +57215,9 @@ __export(run_exports, {
57033
57215
  runPackage: () => runPackage,
57034
57216
  withoutProdServe: () => withoutProdServe
57035
57217
  });
57036
- import { cpSync as cpSync2, existsSync as existsSync58, mkdirSync as mkdirSync27, mkdtempSync as mkdtempSync3, readFileSync as readFileSync65, rmSync as rmSync13, statSync as statSync14 } from "node:fs";
57218
+ import { cpSync as cpSync2, existsSync as existsSync59, mkdirSync as mkdirSync28, mkdtempSync as mkdtempSync3, readFileSync as readFileSync66, rmSync as rmSync14, statSync as statSync15 } from "node:fs";
57037
57219
  import { networkInterfaces as osNetworkInterfaces, tmpdir as tmpdir4 } from "node:os";
57038
- import { dirname as dirname31, join as join57 } from "node:path";
57220
+ import { dirname as dirname32, join as join58 } from "node:path";
57039
57221
  import { fileURLToPath as fileURLToPath24 } from "node:url";
57040
57222
  function makePackageRunHandler(opts) {
57041
57223
  const store = new FileReleaseStore(opts.releaseRoot);
@@ -57063,9 +57245,9 @@ async function fetchBytes(url) {
57063
57245
  }
57064
57246
  async function resolvePackage(source, workDir) {
57065
57247
  const isUrl2 = /^https?:\/\//i.test(source);
57066
- if (!isUrl2 && existsSync58(source) && statSync14(source).isDirectory()) {
57067
- const appDirManifest = join57(source, "release-manifest.json");
57068
- if (existsSync58(appDirManifest)) {
57248
+ if (!isUrl2 && existsSync59(source) && statSync15(source).isDirectory()) {
57249
+ const appDirManifest = join58(source, "release-manifest.json");
57250
+ if (existsSync59(appDirManifest)) {
57069
57251
  const opened2 = openPackageDir(source);
57070
57252
  if (!opened2.validation.ok) {
57071
57253
  throw new Error(`package is not valid:
@@ -57074,11 +57256,11 @@ async function resolvePackage(source, workDir) {
57074
57256
  const app2 = opened2.header?.app ?? opened2.manifest?.app;
57075
57257
  if (!app2) throw new Error(`${source} has no app id (no himi-package.json and no manifest.app)`);
57076
57258
  if (!isSafeAppId(app2)) throw new Error(`${source} declares an unsafe app id ${JSON.stringify(app2)} \u2014 refusing to open it`);
57077
- const root2 = workDir ?? mkdtempSync3(join57(tmpdir4(), "himi-run-"));
57078
- const target = join57(root2, app2);
57079
- if (join57(source) !== target) {
57080
- mkdirSync27(root2, { recursive: true });
57081
- rmSync13(target, { recursive: true, force: true });
57259
+ const root2 = workDir ?? mkdtempSync3(join58(tmpdir4(), "himi-run-"));
57260
+ const target = join58(root2, app2);
57261
+ if (join58(source) !== target) {
57262
+ mkdirSync28(root2, { recursive: true });
57263
+ rmSync14(target, { recursive: true, force: true });
57082
57264
  cpSync2(source, target, { recursive: true });
57083
57265
  }
57084
57266
  return {
@@ -57093,12 +57275,12 @@ async function resolvePackage(source, workDir) {
57093
57275
  }
57094
57276
  throw new Error(`${source} is a directory but has no release-manifest.json \u2014 is it a package?`);
57095
57277
  }
57096
- const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync65(source);
57097
- const root = workDir ?? mkdtempSync3(join57(tmpdir4(), "himi-run-"));
57278
+ const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync66(source);
57279
+ const root = workDir ?? mkdtempSync3(join58(tmpdir4(), "himi-run-"));
57098
57280
  const { app, appDir: appDir3 } = unpackTo(bytes2, root);
57099
57281
  const opened = openPackageDir(appDir3);
57100
57282
  if (!opened.validation.ok) {
57101
- rmSync13(workDir ? appDir3 : root, { recursive: true, force: true });
57283
+ rmSync14(workDir ? appDir3 : root, { recursive: true, force: true });
57102
57284
  throw new Error(`package is not valid:
57103
57285
  ${opened.validation.errors.join("\n ")}`);
57104
57286
  }
@@ -57115,16 +57297,16 @@ async function resolvePackage(source, workDir) {
57115
57297
  async function loadPreviewAssets() {
57116
57298
  try {
57117
57299
  const mod = await Promise.resolve().then(() => (init_preview_assets_generated(), preview_assets_generated_exports));
57118
- const here = dirname31(fileURLToPath24(import.meta.url));
57300
+ const here = dirname32(fileURLToPath24(import.meta.url));
57119
57301
  const candidates = [
57120
- join57(here, "preview-assets.generated.bin"),
57302
+ join58(here, "preview-assets.generated.bin"),
57121
57303
  // published: copied next to the bundled CLI
57122
- join57(here, "../../../packages/serve/src/preview-assets.generated.bin")
57304
+ join58(here, "../../../packages/serve/src/preview-assets.generated.bin")
57123
57305
  // in-repo checkout
57124
57306
  ];
57125
57307
  for (const path2 of candidates) {
57126
- if (!existsSync58(path2)) continue;
57127
- const blob = readFileSync65(path2);
57308
+ if (!existsSync59(path2)) continue;
57309
+ const blob = readFileSync66(path2);
57128
57310
  return mod.assemblePreviewAssetsFromBlob(new Uint8Array(blob.buffer, blob.byteOffset, blob.byteLength));
57129
57311
  }
57130
57312
  return /* @__PURE__ */ new Map();
@@ -57172,7 +57354,7 @@ async function runPackage(source, opts = {}) {
57172
57354
  const resolved2 = await resolvePackage(source, opts.workDir);
57173
57355
  const assets = opts.assets ?? (opts.spa ? /* @__PURE__ */ new Map() : await loadPreviewAssets());
57174
57356
  if (!opts.spa && assets.size === 0) {
57175
- if (resolved2.temp) rmSync13(resolved2.temp, { recursive: true, force: true });
57357
+ if (resolved2.temp) rmSync14(resolved2.temp, { recursive: true, force: true });
57176
57358
  throw new Error(NO_SPA_MESSAGE);
57177
57359
  }
57178
57360
  const plane = makePackageRunHandler({
@@ -57210,7 +57392,7 @@ async function runPackage(source, opts = {}) {
57210
57392
  lanBound = (await listen(lanServer, port, lanHost)).address;
57211
57393
  } catch (e) {
57212
57394
  await closeServer(server);
57213
- if (resolved2.temp) rmSync13(resolved2.temp, { recursive: true, force: true });
57395
+ if (resolved2.temp) rmSync14(resolved2.temp, { recursive: true, force: true });
57214
57396
  throw new Error(`himi run --lan could not listen on ${lanHost}:${port} (${e.message}); drop --lan, or pass --port for a free one`);
57215
57397
  }
57216
57398
  bound.push(lanBound);
@@ -57232,7 +57414,7 @@ async function runPackage(source, opts = {}) {
57232
57414
  warnings: resolved2.warnings,
57233
57415
  close: async () => {
57234
57416
  await Promise.all(servers.map(closeServer));
57235
- if (resolved2.temp) rmSync13(resolved2.temp, { recursive: true, force: true });
57417
+ if (resolved2.temp) rmSync14(resolved2.temp, { recursive: true, force: true });
57236
57418
  }
57237
57419
  };
57238
57420
  }
@@ -57271,9 +57453,9 @@ __export(run_watch_exports, {
57271
57453
  watchedContentDir: () => watchedContentDir,
57272
57454
  writeRunRecord: () => writeRunRecord
57273
57455
  });
57274
- import { closeSync as closeSync4, constants, existsSync as existsSync59, fstatSync, lstatSync as lstatSync12, statSync as statSync15, mkdirSync as mkdirSync28, openSync as openSync3, readFileSync as readFileSync66, realpathSync as realpathSync8, renameSync as renameSync6, rmSync as rmSync14, writeFileSync as writeFileSync23, watch as fsWatch } from "node:fs";
57456
+ import { closeSync as closeSync4, constants, existsSync as existsSync60, fstatSync, lstatSync as lstatSync13, statSync as statSync16, mkdirSync as mkdirSync29, openSync as openSync3, readFileSync as readFileSync67, realpathSync as realpathSync9, renameSync as renameSync6, rmSync as rmSync15, writeFileSync as writeFileSync24, watch as fsWatch } from "node:fs";
57275
57457
  import { randomUUID as randomUUID4 } from "node:crypto";
57276
- import { extname as extname4, join as join58, resolve as resolve46, sep as sep15 } from "node:path";
57458
+ import { extname as extname4, join as join59, resolve as resolve47, sep as sep16 } from "node:path";
57277
57459
  function diffReleases(prev, next) {
57278
57460
  const bundles = Object.keys(next.bundles).filter((b) => prev.bundles[b]?.sha256 !== next.bundles[b].sha256).sort();
57279
57461
  const changedBundles = new Set(bundles);
@@ -57314,7 +57496,7 @@ function watchContent(dir, onChange, opts = {}) {
57314
57496
  let timer = null;
57315
57497
  const pending = /* @__PURE__ */ new Set();
57316
57498
  const watcher2 = watch2(dir, { recursive: true }, (_event, file) => {
57317
- if (!file || ignoredChange(file, (rel) => isDir(join58(dir, rel)))) return;
57499
+ if (!file || ignoredChange(file, (rel) => isDir(join59(dir, rel)))) return;
57318
57500
  pending.add(file);
57319
57501
  if (timer) clearTimeout(timer);
57320
57502
  timer = setTimeout(() => {
@@ -57333,9 +57515,9 @@ function watchContent(dir, onChange, opts = {}) {
57333
57515
  }
57334
57516
  function watchedContentDir(source) {
57335
57517
  if (!source || /^https?:\/\//i.test(source)) return null;
57336
- const dir = resolve46(source);
57518
+ const dir = resolve47(source);
57337
57519
  try {
57338
- return statSync15(dir).isDirectory() && existsSync59(join58(dir, "himalaya.content.json")) ? dir : null;
57520
+ return statSync16(dir).isDirectory() && existsSync60(join59(dir, "himalaya.content.json")) ? dir : null;
57339
57521
  } catch {
57340
57522
  return null;
57341
57523
  }
@@ -57392,33 +57574,33 @@ function serialize(task) {
57392
57574
  });
57393
57575
  }
57394
57576
  function himiDir(dir) {
57395
- const root = join58(dir, ".himi");
57577
+ const root = join59(dir, ".himi");
57396
57578
  try {
57397
- return lstatSync12(root).isDirectory() ? root : null;
57579
+ return lstatSync13(root).isDirectory() ? root : null;
57398
57580
  } catch (e) {
57399
57581
  if (e.code !== "ENOENT") return null;
57400
- mkdirSync28(root, { recursive: true });
57401
- return lstatSync12(root).isDirectory() ? root : null;
57582
+ mkdirSync29(root, { recursive: true });
57583
+ return lstatSync13(root).isDirectory() ? root : null;
57402
57584
  }
57403
57585
  }
57404
57586
  function writeRunRecord(dir, record2) {
57405
57587
  const root = himiDir(dir);
57406
57588
  if (!root) return false;
57407
- const tmp = join58(root, `.run.json.${process.pid}.${randomUUID4()}.tmp`);
57589
+ const tmp = join59(root, `.run.json.${process.pid}.${randomUUID4()}.tmp`);
57408
57590
  try {
57409
- writeFileSync23(tmp, `${JSON.stringify(record2, null, 2)}
57591
+ writeFileSync24(tmp, `${JSON.stringify(record2, null, 2)}
57410
57592
  `, { flag: "wx" });
57411
- renameSync6(tmp, join58(root, "run.json"));
57593
+ renameSync6(tmp, join59(root, "run.json"));
57412
57594
  } catch (e) {
57413
- rmSync14(tmp, { force: true });
57595
+ rmSync15(tmp, { force: true });
57414
57596
  throw e;
57415
57597
  }
57416
57598
  return true;
57417
57599
  }
57418
57600
  function removeRunRecord(dir, owner) {
57419
- const root = join58(dir, ".himi");
57601
+ const root = join59(dir, ".himi");
57420
57602
  try {
57421
- if (!lstatSync12(root).isDirectory()) return;
57603
+ if (!lstatSync13(root).isDirectory()) return;
57422
57604
  } catch {
57423
57605
  return;
57424
57606
  }
@@ -57431,22 +57613,22 @@ function removeRunRecord(dir, owner) {
57431
57613
  }
57432
57614
  if (typeof pid === "number" && pid !== owner) return;
57433
57615
  }
57434
- rmSync14(join58(root, "run.json"), { force: true });
57616
+ rmSync15(join59(root, "run.json"), { force: true });
57435
57617
  }
57436
57618
  function boardFile(dir, pathname) {
57437
57619
  if (pathname === RUN_IDENTITY_PATH) {
57438
57620
  return new Response(JSON.stringify(runIdentity(dir)), { status: 200, headers: { "content-type": "application/json", "cache-control": "no-store" } });
57439
57621
  }
57440
57622
  let rel = null;
57441
- if (pathname === "/__himi/studio/" || pathname === "/__himi/studio/index.html") rel = join58("studio", "index.html");
57442
- else if (pathname === "/__himi/studio/state.js") rel = join58("studio", "state.js");
57443
- else if (pathname === "/__himi/studio/timeline.js") rel = join58("studio", "timeline.js");
57623
+ if (pathname === "/__himi/studio/" || pathname === "/__himi/studio/index.html") rel = join59("studio", "index.html");
57624
+ else if (pathname === "/__himi/studio/state.js") rel = join59("studio", "state.js");
57625
+ else if (pathname === "/__himi/studio/timeline.js") rel = join59("studio", "timeline.js");
57444
57626
  else {
57445
57627
  const m = /^\/__himi\/history\/([0-9a-f]{64}\.(png|jpg|gif|webp))$/.exec(pathname);
57446
- if (m) rel = join58("history", m[1]);
57628
+ if (m) rel = join59("history", m[1]);
57447
57629
  }
57448
57630
  if (!rel) return null;
57449
- const bytes2 = readConfined(resolve46(dir, ".himi"), rel);
57631
+ const bytes2 = readConfined(resolve47(dir, ".himi"), rel);
57450
57632
  if (!bytes2) return new Response("not found", { status: 404 });
57451
57633
  return new Response(bytes2, {
57452
57634
  status: 200,
@@ -57455,20 +57637,20 @@ function boardFile(dir, pathname) {
57455
57637
  }
57456
57638
  function readConfined(root, rel) {
57457
57639
  try {
57458
- if (!lstatSync12(root).isDirectory()) return null;
57459
- const parts = rel.split(sep15);
57640
+ if (!lstatSync13(root).isDirectory()) return null;
57641
+ const parts = rel.split(sep16);
57460
57642
  let at2 = root;
57461
57643
  for (let i = 0; i < parts.length; i++) {
57462
- at2 = join58(at2, parts[i]);
57463
- const st = lstatSync12(at2);
57644
+ at2 = join59(at2, parts[i]);
57645
+ const st = lstatSync13(at2);
57464
57646
  if (st.isSymbolicLink() || !(i === parts.length - 1 ? st.isFile() : st.isDirectory())) return null;
57465
57647
  }
57466
- const canonicalRoot = realpathSync8(root);
57467
- if (!realpathSync8(at2).startsWith(canonicalRoot + sep15)) return null;
57648
+ const canonicalRoot = realpathSync9(root);
57649
+ if (!realpathSync9(at2).startsWith(canonicalRoot + sep16)) return null;
57468
57650
  const fd = openSync3(at2, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
57469
57651
  try {
57470
57652
  if (!fstatSync(fd).isFile()) return null;
57471
- return readFileSync66(fd);
57653
+ return readFileSync67(fd);
57472
57654
  } finally {
57473
57655
  closeSync4(fd);
57474
57656
  }
@@ -57497,7 +57679,7 @@ var init_run_watch = __esm({
57497
57679
  };
57498
57680
  isDir = (path2) => {
57499
57681
  try {
57500
- return statSync15(path2).isDirectory();
57682
+ return statSync16(path2).isDirectory();
57501
57683
  } catch {
57502
57684
  return false;
57503
57685
  }
@@ -57521,19 +57703,19 @@ __export(run_browser_exports, {
57521
57703
  runInBrowser: () => runInBrowser
57522
57704
  });
57523
57705
  import { createServer as createServer7 } from "node:http";
57524
- import { existsSync as existsSync60, readFileSync as readFileSync67 } from "node:fs";
57706
+ import { existsSync as existsSync61, readFileSync as readFileSync68 } from "node:fs";
57525
57707
  import { spawnSync as spawnSync3 } from "node:child_process";
57526
- import { dirname as dirname32, resolve as resolve47 } from "node:path";
57708
+ import { dirname as dirname33, resolve as resolve48 } from "node:path";
57527
57709
  import { fileURLToPath as fileURLToPath25 } from "node:url";
57528
57710
  function stagedDir() {
57529
- return process.env.HIMI_BROWSER_PLANE_OUT ? resolve47(process.env.HIMI_BROWSER_PLANE_OUT) : resolve47(REPO, "packages", "serve", "dist", "browser-plane");
57711
+ return process.env.HIMI_BROWSER_PLANE_OUT ? resolve48(process.env.HIMI_BROWSER_PLANE_OUT) : resolve48(REPO, "packages", "serve", "dist", "browser-plane");
57530
57712
  }
57531
57713
  function missingStaged() {
57532
- return [...SERVED].filter((f) => !existsSync60(resolve47(stagedDir(), f))).sort();
57714
+ return [...SERVED].filter((f) => !existsSync61(resolve48(stagedDir(), f))).sort();
57533
57715
  }
57534
57716
  function ensureBrowserPlaneStaged() {
57535
57717
  if (missingStaged().length === 0) return { ok: true, detail: "already staged" };
57536
- const r = spawnSync3(process.execPath, [resolve47(REPO, "core/serve/scripts/stage-browser-plane.mjs")], {
57718
+ const r = spawnSync3(process.execPath, [resolve48(REPO, "core/serve/scripts/stage-browser-plane.mjs")], {
57537
57719
  cwd: REPO,
57538
57720
  encoding: "utf8"
57539
57721
  });
@@ -57619,7 +57801,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
57619
57801
  }
57620
57802
  const name = path2 === "/" || path2 === "/index.html" ? "host.html" : path2.slice(1);
57621
57803
  if (SERVED.has(name)) {
57622
- if (!existsSync60(resolve47(stagedDir(), name))) {
57804
+ if (!existsSync61(resolve48(stagedDir(), name))) {
57623
57805
  const restaged = ensureBrowserPlaneStaged();
57624
57806
  if (!restaged.ok) {
57625
57807
  res.writeHead(503, { "content-type": "application/json" });
@@ -57629,7 +57811,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
57629
57811
  }
57630
57812
  let bytes2;
57631
57813
  try {
57632
- bytes2 = readFileSync67(resolve47(stagedDir(), name));
57814
+ bytes2 = readFileSync68(resolve48(stagedDir(), name));
57633
57815
  } catch (e) {
57634
57816
  res.writeHead(503, { "content-type": "application/json" });
57635
57817
  res.end(JSON.stringify({ error: "browser_plane_unstaged", file: name, detail: String(e) }));
@@ -57671,8 +57853,8 @@ var init_run_browser = __esm({
57671
57853
  init_open_url();
57672
57854
  init_file_store();
57673
57855
  init_wix_client_id();
57674
- HERE2 = dirname32(fileURLToPath25(import.meta.url));
57675
- REPO = resolve47(HERE2, "..", "..", "..");
57856
+ HERE2 = dirname33(fileURLToPath25(import.meta.url));
57857
+ REPO = resolve48(HERE2, "..", "..", "..");
57676
57858
  SERVED = /* @__PURE__ */ new Set(["host.html", "sw.js", "package-reader.js"]);
57677
57859
  }
57678
57860
  });
@@ -58091,11 +58273,11 @@ __export(preflight_exports, {
58091
58273
  parseStoreConfig: () => parseStoreConfig,
58092
58274
  requireEnv: () => requireEnv
58093
58275
  });
58094
- import { existsSync as existsSync61, readFileSync as readFileSync68 } from "node:fs";
58095
- import { isAbsolute as isAbsolute5, relative as relative12, resolve as resolve48 } from "node:path";
58276
+ import { existsSync as existsSync62, readFileSync as readFileSync69 } from "node:fs";
58277
+ import { isAbsolute as isAbsolute6, relative as relative13, resolve as resolve49 } from "node:path";
58096
58278
  function isInsideRepo(p) {
58097
- const rel = relative12(REPO_ROOT3, resolve48(p));
58098
- return rel !== "" && !rel.startsWith("..") && !isAbsolute5(rel);
58279
+ const rel = relative13(REPO_ROOT3, resolve49(p));
58280
+ return rel !== "" && !rel.startsWith("..") && !isAbsolute6(rel);
58099
58281
  }
58100
58282
  function assertCredentialOutsideRepo(label2, p) {
58101
58283
  if (isInsideRepo(p)) {
@@ -58148,10 +58330,10 @@ function parseStoreConfig(text8) {
58148
58330
  }
58149
58331
  function loadStoreConfig(app) {
58150
58332
  const p = storeConfigPath(app);
58151
- if (!existsSync61(p)) {
58333
+ if (!existsSync62(p)) {
58152
58334
  throw new Error(`No store config at ${p}. Create apps/${app}/store/store.config.yaml first (see /setup-store-signing).`);
58153
58335
  }
58154
- return parseStoreConfig(readFileSync68(p, "utf8"));
58336
+ return parseStoreConfig(readFileSync69(p, "utf8"));
58155
58337
  }
58156
58338
  var init_preflight = __esm({
58157
58339
  "../store-release/preflight.ts"() {
@@ -58170,19 +58352,19 @@ __export(credential_profile_exports, {
58170
58352
  profilePath: () => profilePath,
58171
58353
  resolveStoreCredentials: () => resolveStoreCredentials
58172
58354
  });
58173
- import { existsSync as existsSync62, readFileSync as readFileSync69 } from "node:fs";
58355
+ import { existsSync as existsSync63, readFileSync as readFileSync70 } from "node:fs";
58174
58356
  import { homedir as homedir5 } from "node:os";
58175
- import { join as join59 } from "node:path";
58357
+ import { join as join60 } from "node:path";
58176
58358
  function credentialsDir(home = homedir5()) {
58177
- return join59(home, ".himalaya", "store-credentials");
58359
+ return join60(home, ".himalaya", "store-credentials");
58178
58360
  }
58179
58361
  function profilePath(name, home = homedir5()) {
58180
58362
  if (!PROFILE_NAME.test(name)) {
58181
58363
  throw new Error(
58182
- `credential profile ${JSON.stringify(name)} is not a profile name \u2014 use letters, digits, ".", "_" or "-" starting with a letter or digit. It names ${join59(credentialsDir(home), "<name>.json")}; it is never a path.`
58364
+ `credential profile ${JSON.stringify(name)} is not a profile name \u2014 use letters, digits, ".", "_" or "-" starting with a letter or digit. It names ${join60(credentialsDir(home), "<name>.json")}; it is never a path.`
58183
58365
  );
58184
58366
  }
58185
- return join59(credentialsDir(home), `${name}.json`);
58367
+ return join60(credentialsDir(home), `${name}.json`);
58186
58368
  }
58187
58369
  function parseProfile(text8, label2) {
58188
58370
  let doc;
@@ -58213,8 +58395,8 @@ function resolveStoreCredentials(opts) {
58213
58395
  const { app, cfg } = opts;
58214
58396
  const env = opts.env ?? process.env;
58215
58397
  const home = opts.home ?? homedir5();
58216
- const read = opts.readProfile ?? ((p) => readFileSync69(p, "utf8"));
58217
- const exists = opts.profileExists ?? existsSync62;
58398
+ const read = opts.readProfile ?? ((p) => readFileSync70(p, "utf8"));
58399
+ const exists = opts.profileExists ?? existsSync63;
58218
58400
  const ios = cfg.ios ?? {};
58219
58401
  const flagName = opts.profileFlag?.trim();
58220
58402
  const named = namedProfile(cfg, opts.profileFlag);
@@ -58294,9 +58476,9 @@ __export(preflight_app_exports, {
58294
58476
  preflightApp: () => preflightApp,
58295
58477
  profileAccount: () => profileAccount
58296
58478
  });
58297
- import { readFileSync as readFileSync70, existsSync as existsSync63, readdirSync as readdirSync29, statSync as statSync16 } from "node:fs";
58479
+ import { readFileSync as readFileSync71, existsSync as existsSync64, readdirSync as readdirSync30, statSync as statSync17 } from "node:fs";
58298
58480
  import { createHash as createHash30 } from "node:crypto";
58299
- import { join as join60 } from "node:path";
58481
+ import { join as join61 } from "node:path";
58300
58482
  function analyze(projectYml, storeConfig, icon, account) {
58301
58483
  const f = [];
58302
58484
  const has = (re, s) => re.test(s);
@@ -58360,13 +58542,13 @@ function profileAccount(app, storeConfig, opts = {}) {
58360
58542
  }
58361
58543
  }
58362
58544
  async function preflightApp(app, opts = {}) {
58363
- const projectYml = existsSync63(iosProjectYml(app)) ? readFileSync70(iosProjectYml(app), "utf8") : "";
58364
- const storeConfig = existsSync63(storeConfigPath(app)) ? readFileSync70(storeConfigPath(app), "utf8") : "";
58545
+ const projectYml = existsSync64(iosProjectYml(app)) ? readFileSync71(iosProjectYml(app), "utf8") : "";
58546
+ const storeConfig = existsSync64(storeConfigPath(app)) ? readFileSync71(storeConfigPath(app), "utf8") : "";
58365
58547
  if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }];
58366
58548
  const findings = analyze(
58367
58549
  projectYml,
58368
58550
  storeConfig,
58369
- await appIconState(join60(appDir(app), "ios")),
58551
+ await appIconState(join61(appDir(app), "ios")),
58370
58552
  profileAccount(app, storeConfig, opts)
58371
58553
  );
58372
58554
  findings.push(...analyzeListing(metadataFilesPresent(app), listScreenshots(app)));
@@ -58395,18 +58577,18 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
58395
58577
  return f;
58396
58578
  }
58397
58579
  function appLevelMetadataFiles(app, locale = "en-US") {
58398
- const root = join60(storeDir(app), "metadata");
58580
+ const root = join61(storeDir(app), "metadata");
58399
58581
  const out2 = /* @__PURE__ */ new Set();
58400
- if (existsSync63(root)) {
58401
- for (const n of readdirSync29(root)) if (n.endsWith(".txt")) out2.add(n);
58582
+ if (existsSync64(root)) {
58583
+ for (const n of readdirSync30(root)) if (n.endsWith(".txt")) out2.add(n);
58402
58584
  }
58403
- if (existsSync63(join60(root, locale, "privacy_url.txt"))) out2.add("privacy_url.txt");
58585
+ if (existsSync64(join61(root, locale, "privacy_url.txt"))) out2.add("privacy_url.txt");
58404
58586
  return out2;
58405
58587
  }
58406
58588
  function reviewInfoFiles(app) {
58407
- const dir = join60(storeDir(app), "review_information");
58408
- if (!existsSync63(dir)) return /* @__PURE__ */ new Set();
58409
- return new Set(readdirSync29(dir).filter((n) => n.endsWith(".txt")));
58589
+ const dir = join61(storeDir(app), "review_information");
58590
+ if (!existsSync64(dir)) return /* @__PURE__ */ new Set();
58591
+ return new Set(readdirSync30(dir).filter((n) => n.endsWith(".txt")));
58410
58592
  }
58411
58593
  function isValidAppStoreSize(w, h) {
58412
58594
  return APP_STORE_SIZES.some(([a, b]) => w === a && h === b || w === b && h === a);
@@ -58515,12 +58697,12 @@ function analyzePlayListing(assets) {
58515
58697
  return f;
58516
58698
  }
58517
58699
  function playListingAssets(app, locale = "en-US") {
58518
- const dir = join60(storeDir(app), "play", locale, "images");
58700
+ const dir = join61(storeDir(app), "play", locale, "images");
58519
58701
  const read = (names) => {
58520
58702
  for (const name of names) {
58521
- const p = join60(dir, name);
58703
+ const p = join61(dir, name);
58522
58704
  try {
58523
- if (statSync16(p).isFile()) return { name, bytes: readFileSync70(p) };
58705
+ if (statSync17(p).isFile()) return { name, bytes: readFileSync71(p) };
58524
58706
  } catch {
58525
58707
  }
58526
58708
  }
@@ -58551,26 +58733,26 @@ function analyzeListing(metaFiles, shots) {
58551
58733
  return f;
58552
58734
  }
58553
58735
  function metadataFilesPresent(app, locale = "en-US") {
58554
- const dir = join60(storeDir(app), "metadata", locale);
58555
- if (!existsSync63(dir)) return /* @__PURE__ */ new Set();
58556
- return new Set(readdirSync29(dir).filter((n) => n.endsWith(".txt")));
58736
+ const dir = join61(storeDir(app), "metadata", locale);
58737
+ if (!existsSync64(dir)) return /* @__PURE__ */ new Set();
58738
+ return new Set(readdirSync30(dir).filter((n) => n.endsWith(".txt")));
58557
58739
  }
58558
58740
  function listScreenshots(app, locale = "en-US") {
58559
58741
  const out2 = [];
58560
- const flat = join60(storeDir(app), "screenshots", locale);
58561
- if (existsSync63(flat)) {
58562
- for (const png of readdirSync29(flat).filter((n) => n.endsWith(".png"))) {
58563
- const sz = pngSize(readFileSync70(join60(flat, png)));
58742
+ const flat = join61(storeDir(app), "screenshots", locale);
58743
+ if (existsSync64(flat)) {
58744
+ for (const png of readdirSync30(flat).filter((n) => n.endsWith(".png"))) {
58745
+ const sz = pngSize(readFileSync71(join61(flat, png)));
58564
58746
  if (sz) out2.push({ name: png, w: sz.w, h: sz.h });
58565
58747
  }
58566
58748
  }
58567
- const legacy = join60(storeDir(app), "metadata", locale, "screenshots");
58568
- if (existsSync63(legacy)) {
58569
- for (const deviceDir of readdirSync29(legacy)) {
58570
- const d = join60(legacy, deviceDir);
58571
- if (!statSync16(d).isDirectory()) continue;
58572
- for (const png of readdirSync29(d).filter((n) => n.endsWith(".png"))) {
58573
- const sz = pngSize(readFileSync70(join60(d, png)));
58749
+ const legacy = join61(storeDir(app), "metadata", locale, "screenshots");
58750
+ if (existsSync64(legacy)) {
58751
+ for (const deviceDir of readdirSync30(legacy)) {
58752
+ const d = join61(legacy, deviceDir);
58753
+ if (!statSync17(d).isDirectory()) continue;
58754
+ for (const png of readdirSync30(d).filter((n) => n.endsWith(".png"))) {
58755
+ const sz = pngSize(readFileSync71(join61(d, png)));
58574
58756
  if (sz) out2.push({ name: `${deviceDir}/${png}`, w: sz.w, h: sz.h });
58575
58757
  }
58576
58758
  }
@@ -58578,13 +58760,13 @@ function listScreenshots(app, locale = "en-US") {
58578
58760
  return out2;
58579
58761
  }
58580
58762
  function placeholderHashes2() {
58581
- const templateIos = join60(appDir("_template"), "ios");
58582
- if (!existsSync63(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
58583
- for (const target of readdirSync29(templateIos)) {
58584
- const p = join60(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
58763
+ const templateIos = join61(appDir("_template"), "ios");
58764
+ if (!existsSync64(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
58765
+ for (const target of readdirSync30(templateIos)) {
58766
+ const p = join61(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
58585
58767
  try {
58586
- if (!statSync16(p).isFile()) continue;
58587
- return [LEGACY_PLACEHOLDER_SHA2562, createHash30("sha256").update(readFileSync70(p)).digest("hex")];
58768
+ if (!statSync17(p).isFile()) continue;
58769
+ return [LEGACY_PLACEHOLDER_SHA2562, createHash30("sha256").update(readFileSync71(p)).digest("hex")];
58588
58770
  } catch {
58589
58771
  }
58590
58772
  }
@@ -58615,12 +58797,12 @@ async function pixelIssues(bytes2) {
58615
58797
  }
58616
58798
  }
58617
58799
  async function appIconState(iosDir) {
58618
- if (!existsSync63(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
58619
- for (const target of readdirSync29(iosDir)) {
58620
- const p = join60(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
58800
+ if (!existsSync64(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
58801
+ for (const target of readdirSync30(iosDir)) {
58802
+ const p = join61(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
58621
58803
  try {
58622
- if (!statSync16(p).isFile()) continue;
58623
- const bytes2 = readFileSync70(p);
58804
+ if (!statSync17(p).isFile()) continue;
58805
+ const bytes2 = readFileSync71(p);
58624
58806
  const hash = createHash30("sha256").update(bytes2).digest("hex");
58625
58807
  const pixels = await pixelIssues(bytes2);
58626
58808
  return {
@@ -58692,7 +58874,7 @@ __export(version_exports, {
58692
58874
  setAndroidVersion: () => setAndroidVersion,
58693
58875
  setIosVersion: () => setIosVersion
58694
58876
  });
58695
- import { readFileSync as readFileSync71, writeFileSync as writeFileSync24 } from "node:fs";
58877
+ import { readFileSync as readFileSync72, writeFileSync as writeFileSync25 } from "node:fs";
58696
58878
  function readIosVersion(projectYml) {
58697
58879
  const marketing = matchScalar(projectYml, "CFBundleShortVersionString");
58698
58880
  const build2 = matchScalar(projectYml, "CFBundleVersion");
@@ -58750,15 +58932,15 @@ function setAndroidVersion(gradle, v) {
58750
58932
  function bumpVersion(app, opts) {
58751
58933
  const iosPath = iosProjectYml(app);
58752
58934
  const gradlePath = androidGradle(app);
58753
- const iosYml = readFileSync71(iosPath, "utf8");
58754
- const gradle = readFileSync71(gradlePath, "utf8");
58935
+ const iosYml = readFileSync72(iosPath, "utf8");
58936
+ const gradle = readFileSync72(gradlePath, "utf8");
58755
58937
  const current = readIosVersion(iosYml);
58756
58938
  const next = {
58757
58939
  marketing: opts.marketing ?? current.marketing,
58758
58940
  build: opts.build === "increment" || opts.build === void 0 ? current.build + (opts.build === "increment" ? 1 : 0) : opts.build
58759
58941
  };
58760
- writeFileSync24(iosPath, setIosVersion(iosYml, next));
58761
- writeFileSync24(gradlePath, setAndroidVersion(gradle, next));
58942
+ writeFileSync25(iosPath, setIosVersion(iosYml, next));
58943
+ writeFileSync25(gradlePath, setAndroidVersion(gradle, next));
58762
58944
  return next;
58763
58945
  }
58764
58946
  var init_version = __esm({
@@ -58768,7 +58950,7 @@ var init_version = __esm({
58768
58950
  });
58769
58951
 
58770
58952
  // ../store-release/register-bundle.ts
58771
- import { readFileSync as readFileSync72 } from "node:fs";
58953
+ import { readFileSync as readFileSync73 } from "node:fs";
58772
58954
  import { createPrivateKey as createPrivateKey2, sign } from "node:crypto";
58773
58955
  function b64url2(b) {
58774
58956
  return Buffer.from(b).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
@@ -58786,7 +58968,7 @@ function bundleIdBody(identifier, name, platform = "IOS") {
58786
58968
  async function registerBundleId(opts) {
58787
58969
  const env = requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
58788
58970
  assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
58789
- const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync72(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
58971
+ const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync73(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
58790
58972
  const res = await fetch(`${ASC_API}/v1/bundleIds`, {
58791
58973
  method: "POST",
58792
58974
  headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json" },
@@ -58840,7 +59022,7 @@ __export(asc_status_exports, {
58840
59022
  ascStatus: () => ascStatus,
58841
59023
  buildVerdict: () => buildVerdict
58842
59024
  });
58843
- import { readFileSync as readFileSync73 } from "node:fs";
59025
+ import { readFileSync as readFileSync74 } from "node:fs";
58844
59026
  function buildVerdict(builds) {
58845
59027
  if (!builds.length) {
58846
59028
  return "NO builds registered \u2014 if you uploaded recently and it's been >15 min, the binary was REJECTED IN PROCESSING (reason is email-only; run validate-binary.ts / scan-purpose-strings.ts to reproduce it).";
@@ -58854,7 +59036,7 @@ function buildVerdict(builds) {
58854
59036
  function client(creds) {
58855
59037
  const env = creds ?? requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
58856
59038
  assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
58857
- const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync73(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
59039
+ const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync74(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
58858
59040
  return async (path2) => {
58859
59041
  const r = await fetch(`${ASC}${path2}`, { headers: { Authorization: `Bearer ${jwt}` } });
58860
59042
  return { status: r.status, json: await r.json().catch(() => ({})) };
@@ -58903,7 +59085,7 @@ var init_asc_status = __esm({
58903
59085
  // ../../core/functions-secrets/src/vault.ts
58904
59086
  import { createCipheriv, createDecipheriv, randomBytes as randomBytes5 } from "node:crypto";
58905
59087
  import { mkdir, readFile as readFile2, rename, writeFile as writeFile2 } from "node:fs/promises";
58906
- import { dirname as dirname33 } from "node:path";
59088
+ import { dirname as dirname34 } from "node:path";
58907
59089
  function createJsonSecretStore(filePath) {
58908
59090
  const read = async () => {
58909
59091
  try {
@@ -58916,7 +59098,7 @@ function createJsonSecretStore(filePath) {
58916
59098
  }
58917
59099
  };
58918
59100
  const write2 = async (records) => {
58919
- await mkdir(dirname33(filePath), { recursive: true });
59101
+ await mkdir(dirname34(filePath), { recursive: true });
58920
59102
  const temporary = `${filePath}.${process.pid}.tmp`;
58921
59103
  await writeFile2(temporary, `${JSON.stringify(records, null, 2)}
58922
59104
  `, { mode: 384 });
@@ -59014,7 +59196,7 @@ __export(secrets_exports, {
59014
59196
  runRemoteSecretsCommand: () => runRemoteSecretsCommand,
59015
59197
  runSecretsCommand: () => runSecretsCommand
59016
59198
  });
59017
- import { readFileSync as readFileSync74 } from "node:fs";
59199
+ import { readFileSync as readFileSync75 } from "node:fs";
59018
59200
  function environment(value) {
59019
59201
  if (value === "preview" || value === "production") return value;
59020
59202
  throw new Error("--environment must be preview or production");
@@ -59045,7 +59227,7 @@ async function runSecretsCommand(operation, flags, io, options = {}) {
59045
59227
  io.log(JSON.stringify(await vault.list({ app, environment: env })));
59046
59228
  return 0;
59047
59229
  }
59048
- const value = options.readValue ? options.readValue() : readFileSync74(0, "utf8").replace(/\r?\n$/, "");
59230
+ const value = options.readValue ? options.readValue() : readFileSync75(0, "utf8").replace(/\r?\n$/, "");
59049
59231
  if (operation === "set") await vault.set({ app, environment: env, name, value });
59050
59232
  else if (operation === "rotate") await vault.rotate({ app, environment: env, name, value });
59051
59233
  else throw new Error(`unknown secrets operation ${operation}`);
@@ -59074,7 +59256,7 @@ async function runRemoteSecretsCommand(operation, flags, io, options) {
59074
59256
  }
59075
59257
  let body;
59076
59258
  if (operation !== "list") {
59077
- const value = options.readValue ? options.readValue() : readFileSync74(0, "utf8").replace(/\r?\n$/, "");
59259
+ const value = options.readValue ? options.readValue() : readFileSync75(0, "utf8").replace(/\r?\n$/, "");
59078
59260
  body = JSON.stringify({ value });
59079
59261
  }
59080
59262
  const response = await (options.fetchImpl ?? fetch)(url, { method: operation === "list" ? "GET" : operation === "set" ? "PUT" : "POST", headers: headers2, body });
@@ -59211,29 +59393,29 @@ __export(notify_ping_exports, {
59211
59393
  runNotifyPing: () => runNotifyPing
59212
59394
  });
59213
59395
  import { randomUUID as randomUUID5 } from "node:crypto";
59214
- import { resolve as resolve49 } from "node:path";
59215
- function refuse4(io, error, hint, exit = 2, extra = {}) {
59396
+ import { resolve as resolve50 } from "node:path";
59397
+ function refuse5(io, error, hint, exit = 2, extra = {}) {
59216
59398
  io.error(JSON.stringify({ ok: false, error, ...hint ? { hint } : {}, ...extra }));
59217
59399
  return exit;
59218
59400
  }
59219
59401
  async function runNotifyPing(flags, io, deps = {}) {
59220
59402
  const flagError = flagRefusal(flags);
59221
- if (flagError) return refuse4(io, flagError);
59222
- const input = mergePushInputs(pushInputsFromContent(resolve49(text7(flags.content) ?? process.cwd())), flags);
59403
+ if (flagError) return refuse5(io, flagError);
59404
+ const input = mergePushInputs(pushInputsFromContent(resolve50(text7(flags.content) ?? process.cwd())), flags);
59223
59405
  const missing = [...input.app ? [] : ["app"], ...input.site ? [] : ["site"], ...REQUIRED_FLAGS.filter((f) => !text7(flags[f]))];
59224
- if (missing.length) return refuse4(io, "needs_input", "Name the app and site (or --content), the member's login email, a title and a link.", 2, { missing });
59406
+ if (missing.length) return refuse5(io, "needs_input", "Name the app and site (or --content), the member's login email, a title and a link.", 2, { missing });
59225
59407
  const requestId2 = text7(flags["request-id"]) ?? (deps.newRequestId ?? randomUUID5)();
59226
- if (!UUID_RE.test(requestId2)) return refuse4(io, "invalid_request_id", "Reuse the requestId a previous send printed.");
59408
+ if (!UUID_RE.test(requestId2)) return refuse5(io, "invalid_request_id", "Reuse the requestId a previous send printed.");
59227
59409
  const owner = await hostedOwnerSession(flags, deps);
59228
- if (!owner.ok) return refuse4(io, owner.error, owner.hint, owner.exit);
59410
+ if (!owner.ok) return refuse5(io, owner.error, owner.hint, owner.exit);
59229
59411
  const { session } = owner;
59230
59412
  const ownership = await verifyAppOwnership({ ownerIssue: session.ownerIssue, controlToken: session.controlToken, declaredName: input.app, fetchImpl: deps.fetchImpl });
59231
- if (ownership.state !== "owned") return refuse4(io, `app_ownership_${ownership.state}`, "Sending requires the app owner.", 1);
59413
+ if (ownership.state !== "owned") return refuse5(io, `app_ownership_${ownership.state}`, "Sending requires the app owner.", 1);
59232
59414
  let siteToken2;
59233
59415
  try {
59234
59416
  siteToken2 = await (deps.siteToken ?? siteToken)(input.site);
59235
59417
  } catch {
59236
- return refuse4(io, "wix_site_token_required", "Run wix login as the site owner; the site token reads this site's members.", 1);
59418
+ return refuse5(io, "wix_site_token_required", "Run wix login as the site owner; the site token reads this site's members.", 1);
59237
59419
  }
59238
59420
  const body = {
59239
59421
  app: ownership.slug,
@@ -59256,12 +59438,12 @@ function flagRefusal(flags) {
59256
59438
  function report2(http, sent, flags, io) {
59257
59439
  const code = refusalCode(http);
59258
59440
  if (code === "send_outcome_unknown") {
59259
- return refuse4(io, code, `Ping may have accepted it. Re-run the same command with --request-id ${sent.requestId}: Ping runs one request at most once per site for 24 hours.`, 1, { requestId: sent.requestId });
59441
+ return refuse5(io, code, `Ping may have accepted it. Re-run the same command with --request-id ${sent.requestId}: Ping runs one request at most once per site for 24 hours.`, 1, { requestId: sent.requestId });
59260
59442
  }
59261
59443
  if (code === "rate_limited" && http.retryAfterSec) {
59262
- return refuse4(io, code, `Test sends are limited per owner; retry in ${http.retryAfterSec} seconds.`, 1, { retryAfterSec: http.retryAfterSec });
59444
+ return refuse5(io, code, `Test sends are limited per owner; retry in ${http.retryAfterSec} seconds.`, 1, { retryAfterSec: http.retryAfterSec });
59263
59445
  }
59264
- if (code) return refuse4(io, code, HINTS[code], 1);
59446
+ if (code) return refuse5(io, code, HINTS[code], 1);
59265
59447
  if (flags.json === true) io.log(JSON.stringify(http.body, null, 2));
59266
59448
  else io.log(summary(http.body ?? {}, sent));
59267
59449
  return 0;
@@ -59321,15 +59503,15 @@ __export(notify_exports, {
59321
59503
  runNotify: () => runNotify,
59322
59504
  saveAdminSession: () => saveAdminSession
59323
59505
  });
59324
- import { chmodSync as chmodSync3, mkdirSync as mkdirSync29, readFileSync as readFileSync75, writeFileSync as writeFileSync25 } from "node:fs";
59506
+ import { chmodSync as chmodSync3, mkdirSync as mkdirSync30, readFileSync as readFileSync76, writeFileSync as writeFileSync26 } from "node:fs";
59325
59507
  import { homedir as homedir6 } from "node:os";
59326
- import { dirname as dirname34, join as join61 } from "node:path";
59508
+ import { dirname as dirname35, join as join62 } from "node:path";
59327
59509
  function defaultSessionsPath() {
59328
- return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join61(homedir6(), ".himalaya", "admin-sessions.json");
59510
+ return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join62(homedir6(), ".himalaya", "admin-sessions.json");
59329
59511
  }
59330
59512
  function loadSessionsFile(path2 = defaultSessionsPath()) {
59331
59513
  try {
59332
- return JSON.parse(readFileSync75(path2, "utf8"));
59514
+ return JSON.parse(readFileSync76(path2, "utf8"));
59333
59515
  } catch {
59334
59516
  return {};
59335
59517
  }
@@ -59337,10 +59519,10 @@ function loadSessionsFile(path2 = defaultSessionsPath()) {
59337
59519
  function saveAdminSession(adminUrl, session, path2 = defaultSessionsPath()) {
59338
59520
  const file = loadSessionsFile(path2);
59339
59521
  file.sessions = { ...file.sessions, [adminUrl]: session };
59340
- mkdirSync29(dirname34(path2), { recursive: true, mode: 448 });
59341
- writeFileSync25(path2, JSON.stringify(file, null, 2) + "\n", { mode: 384 });
59522
+ mkdirSync30(dirname35(path2), { recursive: true, mode: 448 });
59523
+ writeFileSync26(path2, JSON.stringify(file, null, 2) + "\n", { mode: 384 });
59342
59524
  try {
59343
- chmodSync3(dirname34(path2), 448);
59525
+ chmodSync3(dirname35(path2), 448);
59344
59526
  chmodSync3(path2, 384);
59345
59527
  } catch {
59346
59528
  }
@@ -61940,10 +62122,10 @@ function assertPublicSiteUrl(raw) {
61940
62122
  if (refusal) throw new Error(refusal);
61941
62123
  }
61942
62124
  function resolveAll(hostname2) {
61943
- return new Promise((resolve53, reject) => {
62125
+ return new Promise((resolve54, reject) => {
61944
62126
  dnsLookup(hostname2, { all: true, verbatim: true }, (err, addresses) => {
61945
62127
  if (err) reject(err);
61946
- else resolve53(addresses);
62128
+ else resolve54(addresses);
61947
62129
  });
61948
62130
  });
61949
62131
  }
@@ -61951,13 +62133,13 @@ function withAbort(start, signal, what) {
61951
62133
  if (signal?.aborted) return Promise.reject(new Error(`${what} aborted`));
61952
62134
  const work = start();
61953
62135
  if (!signal) return work;
61954
- return new Promise((resolve53, reject) => {
62136
+ return new Promise((resolve54, reject) => {
61955
62137
  const onAbort = () => reject(new Error(`${what} aborted`));
61956
62138
  signal.addEventListener("abort", onAbort, { once: true });
61957
- work.then(resolve53, reject).finally(() => signal.removeEventListener("abort", onAbort));
62139
+ work.then(resolve54, reject).finally(() => signal.removeEventListener("abort", onAbort));
61958
62140
  });
61959
62141
  }
61960
- async function pinAddress(url, resolve53 = resolveAll, signal) {
62142
+ async function pinAddress(url, resolve54 = resolveAll, signal) {
61961
62143
  const host = url.hostname.replace(/^\[|\]$/g, "");
61962
62144
  if (ipv4Octets(host)) {
61963
62145
  if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
@@ -61967,7 +62149,7 @@ async function pinAddress(url, resolve53 = resolveAll, signal) {
61967
62149
  if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
61968
62150
  return { address: host, family: 6 };
61969
62151
  }
61970
- const addresses = await withAbort(() => resolve53(host), signal, `${host} lookup`);
62152
+ const addresses = await withAbort(() => resolve54(host), signal, `${host} lookup`);
61971
62153
  if (!addresses.length) throw new Error(`${host} resolved to no address`);
61972
62154
  const blocked = addresses.filter((a) => isBlockedAddress(a.address)).map((a) => a.address);
61973
62155
  if (blocked.length) throw new Error(`${host} resolves to a blocked address (${blocked.join(", ")})`);
@@ -62007,7 +62189,7 @@ function copyIncomingHeaders(headers2) {
62007
62189
  return out2;
62008
62190
  }
62009
62191
  function requestOnce(url, pinned, init) {
62010
- return new Promise((resolve53, reject) => {
62192
+ return new Promise((resolve54, reject) => {
62011
62193
  const headers2 = { host: url.host, "accept-encoding": "identity" };
62012
62194
  new Headers(init.headers ?? {}).forEach((value, key2) => {
62013
62195
  if (key2.toLowerCase() !== "host") headers2[key2] = value;
@@ -62037,7 +62219,7 @@ function requestOnce(url, pinned, init) {
62037
62219
  reject(err);
62038
62220
  return;
62039
62221
  }
62040
- resolve53(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out2 }));
62222
+ resolve54(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out2 }));
62041
62223
  }
62042
62224
  );
62043
62225
  req.on("error", reject);
@@ -63097,8 +63279,8 @@ var init_brand_font = __esm({
63097
63279
  });
63098
63280
 
63099
63281
  // src/site-analyze/write-artifacts.ts
63100
- import { mkdirSync as mkdirSync30, writeFileSync as writeFileSync26 } from "node:fs";
63101
- import { join as join62 } from "node:path";
63282
+ import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync27 } from "node:fs";
63283
+ import { join as join63 } from "node:path";
63102
63284
  function attachVeloSources(book, sources, put) {
63103
63285
  const byPath = new Map((sources ?? []).map((s) => [s.path, s.text]));
63104
63286
  for (const f of book.velo.files) {
@@ -63253,13 +63435,13 @@ async function downloadMedia(book, fetchImpl, put) {
63253
63435
  }
63254
63436
  async function writeBusinessBook(result, opts) {
63255
63437
  const out2 = opts.outDir;
63256
- mkdirSync30(join62(out2, "evidence/pages"), { recursive: true });
63257
- mkdirSync30(join62(out2, "media/catalog"), { recursive: true });
63438
+ mkdirSync31(join63(out2, "evidence/pages"), { recursive: true });
63439
+ mkdirSync31(join63(out2, "media/catalog"), { recursive: true });
63258
63440
  const files = [];
63259
63441
  const put = (rel, body) => {
63260
- const p = join62(out2, rel);
63261
- mkdirSync30(join62(p, ".."), { recursive: true });
63262
- writeFileSync26(p, body);
63442
+ const p = join63(out2, rel);
63443
+ mkdirSync31(join63(p, ".."), { recursive: true });
63444
+ writeFileSync27(p, body);
63263
63445
  files.push(rel);
63264
63446
  };
63265
63447
  const book = result.book;
@@ -63352,15 +63534,15 @@ var init_customer_build = __esm({
63352
63534
  });
63353
63535
 
63354
63536
  // src/site-analyze/apply.ts
63355
- import { existsSync as existsSync64, readFileSync as readFileSync76, writeFileSync as writeFileSync27, copyFileSync as copyFileSync3, mkdirSync as mkdirSync31, realpathSync as realpathSync9, statSync as statSync17 } from "node:fs";
63356
- import { dirname as dirname35, isAbsolute as isAbsolute6, join as join63, resolve as resolve50, sep as sep16 } from "node:path";
63537
+ import { existsSync as existsSync65, readFileSync as readFileSync77, writeFileSync as writeFileSync28, copyFileSync as copyFileSync3, mkdirSync as mkdirSync32, realpathSync as realpathSync10, statSync as statSync18 } from "node:fs";
63538
+ import { dirname as dirname36, isAbsolute as isAbsolute7, join as join64, resolve as resolve51, sep as sep17 } from "node:path";
63357
63539
  import { spawnSync as spawnSync4 } from "node:child_process";
63358
63540
  function unpairedRedirectNote(overlay) {
63359
63541
  if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
63360
63542
  return `no OAuth redirect paired with client ${overlay.wix.clientId} \u2014 the app (and prepare:customer) will refuse to start until one is set. Register it with \`himi site client ensure --site ${overlay.siteId?.trim() || "<msid>"} --redirect-uri <uri> --yes\`, then re-run analyze with \`--redirect-uri <uri>\` (or export HIMI_BRANDED_LITE_WIX_REDIRECT_URI)`;
63361
63543
  }
63362
63544
  function posix3(p) {
63363
- return resolve50(p).replace(/\\/g, "/");
63545
+ return resolve51(p).replace(/\\/g, "/");
63364
63546
  }
63365
63547
  function committedShellProvisioning(path2) {
63366
63548
  return committedShellFor(posix3(path2));
@@ -63368,8 +63550,8 @@ function committedShellProvisioning(path2) {
63368
63550
  function findRepoRoot(cwd) {
63369
63551
  let dir = cwd;
63370
63552
  for (let i = 0; i < 8; i++) {
63371
- if (SHELL_NAMES2.some((name) => existsSync64(join63(dir, shellAppDir(name), "package.json")))) return dir;
63372
- const next = dirname35(dir);
63553
+ if (SHELL_NAMES2.some((name) => existsSync65(join64(dir, shellAppDir(name), "package.json")))) return dir;
63554
+ const next = dirname36(dir);
63373
63555
  if (next === dir) break;
63374
63556
  dir = next;
63375
63557
  }
@@ -63394,7 +63576,7 @@ function assertNotCommitted(path2, forbidden) {
63394
63576
  `refusing to overwrite committed ${committedProvisioningPath(committed)} \u2014 use prepare:customer --contract`
63395
63577
  );
63396
63578
  }
63397
- if (forbidden && resolve50(path2) === resolve50(forbidden)) {
63579
+ if (forbidden && resolve51(path2) === resolve51(forbidden)) {
63398
63580
  const named = committedShellProvisioning(forbidden);
63399
63581
  throw new Error(
63400
63582
  `refusing to overwrite committed ${named ? committedProvisioningPath(named) : forbidden} \u2014 pass a content-package provisioning.json or use prepare:customer --contract`
@@ -63439,36 +63621,36 @@ function mergeCustomerOwned(committed, overlay) {
63439
63621
  }
63440
63622
  function buildMergedContract(options) {
63441
63623
  const { appDir: appDir3, packageDir, overlay } = options;
63442
- const committedPath = join63(appDir3, "provisioning.json");
63443
- if (!existsSync64(committedPath)) {
63624
+ const committedPath = join64(appDir3, "provisioning.json");
63625
+ if (!existsSync65(committedPath)) {
63444
63626
  throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
63445
63627
  }
63446
- const committed = JSON.parse(readFileSync76(committedPath, "utf8"));
63628
+ const committed = JSON.parse(readFileSync77(committedPath, "utf8"));
63447
63629
  const merged = mergeCustomerOwned(committed, overlay);
63448
63630
  const overlayFontFamily = (overlay.branding ?? {}).fontFamily;
63449
63631
  const branding = merged.branding ?? {};
63450
63632
  const staged = [];
63451
63633
  const contained = (root, rel) => {
63452
- if (isAbsolute6(rel)) return void 0;
63453
- const full = resolve50(root, rel);
63454
- return full.startsWith(resolve50(root) + sep16) ? full : void 0;
63634
+ if (isAbsolute7(rel)) return void 0;
63635
+ const full = resolve51(root, rel);
63636
+ return full.startsWith(resolve51(root) + sep17) ? full : void 0;
63455
63637
  };
63456
63638
  const stage = (fromRel, toRel) => {
63457
63639
  const from = contained(packageDir, fromRel);
63458
- const to = contained(join63(appDir3, STAGED), toRel.slice(STAGED.length + 1));
63459
- if (!from || !to || !existsSync64(from)) return void 0;
63640
+ const to = contained(join64(appDir3, STAGED), toRel.slice(STAGED.length + 1));
63641
+ if (!from || !to || !existsSync65(from)) return void 0;
63460
63642
  let real;
63461
63643
  let realRoot;
63462
63644
  try {
63463
- real = realpathSync9(from);
63464
- realRoot = realpathSync9(packageDir);
63645
+ real = realpathSync10(from);
63646
+ realRoot = realpathSync10(packageDir);
63465
63647
  } catch {
63466
63648
  return void 0;
63467
63649
  }
63468
- if (!real.startsWith(realRoot + sep16)) return void 0;
63650
+ if (!real.startsWith(realRoot + sep17)) return void 0;
63469
63651
  try {
63470
- if (!statSync17(real).isFile()) return void 0;
63471
- mkdirSync31(dirname35(to), { recursive: true });
63652
+ if (!statSync18(real).isFile()) return void 0;
63653
+ mkdirSync32(dirname36(to), { recursive: true });
63472
63654
  copyFileSync3(real, to);
63473
63655
  } catch {
63474
63656
  return void 0;
@@ -63478,11 +63660,11 @@ function buildMergedContract(options) {
63478
63660
  };
63479
63661
  const icon = stage("media/icon.png", `${STAGED}/icon.png`);
63480
63662
  if (icon) branding.appIconPath = icon;
63481
- const facesPath = join63(packageDir, "media/fonts/faces.json");
63482
- if (existsSync64(facesPath)) {
63663
+ const facesPath = join64(packageDir, "media/fonts/faces.json");
63664
+ if (existsSync65(facesPath)) {
63483
63665
  let faces = [];
63484
63666
  try {
63485
- const parsed = JSON.parse(readFileSync76(facesPath, "utf8"));
63667
+ const parsed = JSON.parse(readFileSync77(facesPath, "utf8"));
63486
63668
  faces = Array.isArray(parsed) ? parsed : [];
63487
63669
  } catch {
63488
63670
  faces = [];
@@ -63503,11 +63685,11 @@ function buildMergedContract(options) {
63503
63685
  merged.branding = branding;
63504
63686
  const body = `${JSON.stringify(merged, null, 2)}
63505
63687
  `;
63506
- const path2 = join63(packageDir, "provisioning.contract.json");
63507
- writeFileSync27(path2, body);
63508
- const localPath = join63(appDir3, LOCAL_CONTRACT_REL);
63509
- mkdirSync31(dirname35(localPath), { recursive: true });
63510
- writeFileSync27(localPath, body);
63688
+ const path2 = join64(packageDir, "provisioning.contract.json");
63689
+ writeFileSync28(path2, body);
63690
+ const localPath = join64(appDir3, LOCAL_CONTRACT_REL);
63691
+ mkdirSync32(dirname36(localPath), { recursive: true });
63692
+ writeFileSync28(localPath, body);
63511
63693
  staged.push(localPath);
63512
63694
  return { path: path2, staged };
63513
63695
  }
@@ -63540,10 +63722,10 @@ function catalogTypography(overlay, template) {
63540
63722
  function staticFaqFor(overlay, overlayPath) {
63541
63723
  const own3 = overlay.faq;
63542
63724
  if (own3 !== void 0) return deriveStaticFaq(own3);
63543
- const bookPath = join63(dirname35(resolve50(overlayPath)), "book.json");
63544
- if (!existsSync64(bookPath)) return void 0;
63725
+ const bookPath = join64(dirname36(resolve51(overlayPath)), "book.json");
63726
+ if (!existsSync65(bookPath)) return void 0;
63545
63727
  try {
63546
- const book = JSON.parse(readFileSync76(bookPath, "utf8"));
63728
+ const book = JSON.parse(readFileSync77(bookPath, "utf8"));
63547
63729
  const copy = book?.copy;
63548
63730
  if (!copy || typeof copy !== "object" || copy.unavailable) return void 0;
63549
63731
  const pairs = deriveStaticFaq(copy.faq);
@@ -63554,11 +63736,11 @@ function staticFaqFor(overlay, overlayPath) {
63554
63736
  }
63555
63737
  }
63556
63738
  async function applyOverlays(input) {
63557
- const cwd = resolve50(input.cwd);
63739
+ const cwd = resolve51(input.cwd);
63558
63740
  const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
63559
63741
  assertKnownShell(shell);
63560
- const overlay = JSON.parse(readFileSync76(input.overlayPath, "utf8"));
63561
- const tokens = JSON.parse(readFileSync76(input.tokensPath, "utf8"));
63742
+ const overlay = JSON.parse(readFileSync77(input.overlayPath, "utf8"));
63743
+ const tokens = JSON.parse(readFileSync77(input.tokensPath, "utf8"));
63562
63744
  const faq = staticFaqFor(overlay, input.overlayPath);
63563
63745
  if (faq !== void 0) overlay.faq = faq;
63564
63746
  const wrote = [];
@@ -63570,15 +63752,15 @@ async function applyOverlays(input) {
63570
63752
  `shell "${shell}" cannot bake a customer brand \u2014 it ships no prepare:customer script`
63571
63753
  );
63572
63754
  }
63573
- const appDir3 = join63(repoRoot2, shellAppDir(shell));
63574
- const committedPath = join63(appDir3, "provisioning.json");
63575
- const committedSite = existsSync64(committedPath) ? JSON.parse(readFileSync76(committedPath, "utf8")).site : void 0;
63755
+ const appDir3 = join64(repoRoot2, shellAppDir(shell));
63756
+ const committedPath = join64(appDir3, "provisioning.json");
63757
+ const committedSite = existsSync65(committedPath) ? JSON.parse(readFileSync77(committedPath, "utf8")).site : void 0;
63576
63758
  if (committedSite !== void 0 && overlay.site === void 0) {
63577
63759
  throw new Error(
63578
63760
  `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.`
63579
63761
  );
63580
63762
  }
63581
- const packageDir = dirname35(resolve50(input.overlayPath));
63763
+ const packageDir = dirname36(resolve51(input.overlayPath));
63582
63764
  const { path: contract, staged } = buildMergedContract({ appDir: appDir3, packageDir, overlay });
63583
63765
  wrote.push(...staged);
63584
63766
  const r = spawnSync4("npm", ["run", "prepare:customer", "--", "--contract", contract], {
@@ -63599,22 +63781,22 @@ async function applyOverlays(input) {
63599
63781
  note: `prepare:customer --contract with a merged contract (committed provisioning.json untouched)${unpairedInRepo ? ` \xB7 ${unpairedInRepo}` : ""}`
63600
63782
  };
63601
63783
  }
63602
- const pkgProv = join63(cwd, "provisioning.json");
63784
+ const pkgProv = join64(cwd, "provisioning.json");
63603
63785
  assertNotCommitted(pkgProv, input.forbiddenProvisioning);
63604
63786
  let packageFaq = faq;
63605
- if (existsSync64(pkgProv)) {
63606
- const cur = JSON.parse(readFileSync76(pkgProv, "utf8"));
63787
+ if (existsSync65(pkgProv)) {
63788
+ const cur = JSON.parse(readFileSync77(pkgProv, "utf8"));
63607
63789
  const merged = deepMerge4(cur, overlay);
63608
63790
  packageFaq = merged.faq;
63609
- writeFileSync27(pkgProv, JSON.stringify(merged, null, 2) + "\n");
63791
+ writeFileSync28(pkgProv, JSON.stringify(merged, null, 2) + "\n");
63610
63792
  wrote.push(pkgProv);
63611
63793
  } else {
63612
- writeFileSync27(pkgProv, JSON.stringify(overlay, null, 2) + "\n");
63794
+ writeFileSync28(pkgProv, JSON.stringify(overlay, null, 2) + "\n");
63613
63795
  wrote.push(pkgProv);
63614
63796
  }
63615
- const pkgTokens = join63(cwd, "tokens.json");
63616
- if (existsSync64(pkgTokens) && (tokens.colors || tokens.typography)) {
63617
- const cur = JSON.parse(readFileSync76(pkgTokens, "utf8"));
63797
+ const pkgTokens = join64(cwd, "tokens.json");
63798
+ if (existsSync65(pkgTokens) && (tokens.colors || tokens.typography)) {
63799
+ const cur = JSON.parse(readFileSync77(pkgTokens, "utf8"));
63618
63800
  let tokensIn = tokens;
63619
63801
  if (tokens.typography) {
63620
63802
  const fonts = catalogTypography(tokens.typography, cur.typography);
@@ -63635,13 +63817,13 @@ async function applyOverlays(input) {
63635
63817
  if (primary && glow && typeof glow.color === "string") glow.color = primary;
63636
63818
  stripBrandFromIdiom(merged);
63637
63819
  }
63638
- writeFileSync27(pkgTokens, JSON.stringify(merged, null, 2) + "\n");
63820
+ writeFileSync28(pkgTokens, JSON.stringify(merged, null, 2) + "\n");
63639
63821
  wrote.push(pkgTokens);
63640
63822
  }
63641
63823
  const homeAction = homeRefreshActionId(shell);
63642
- const homeSrc = join63(cwd, "dev/index.ts");
63643
- if (homeAction && existsSync64(homeSrc)) {
63644
- const prev = readFileSync76(homeSrc, "utf8");
63824
+ const homeSrc = join64(cwd, "dev/index.ts");
63825
+ if (homeAction && existsSync65(homeSrc)) {
63826
+ const prev = readFileSync77(homeSrc, "utf8");
63645
63827
  const patched = patchBrandParams(prev, overlay, homeAction);
63646
63828
  let next = patched.src;
63647
63829
  if (!patched.foreign && faq?.length && prev.includes('"tier5.himiBrandedFaq.load"') && !prev.includes('"staticFaq"')) {
@@ -63665,20 +63847,20 @@ async function applyOverlays(input) {
63665
63847
  }
63666
63848
  }
63667
63849
  if (next !== prev) {
63668
- writeFileSync27(homeSrc, next);
63850
+ writeFileSync28(homeSrc, next);
63669
63851
  wrote.push(homeSrc);
63670
63852
  }
63671
63853
  if (patched.unparsed) {
63672
63854
  notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
63673
63855
  }
63674
63856
  }
63675
- if (!input.iconPath || !existsSync64(input.iconPath)) {
63676
- const book = input.iconPath ? dirname35(dirname35(resolve50(input.iconPath))) : void 0;
63857
+ if (!input.iconPath || !existsSync65(input.iconPath)) {
63858
+ const book = input.iconPath ? dirname36(dirname36(resolve51(input.iconPath))) : void 0;
63677
63859
  notes.push(
63678
63860
  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"
63679
63861
  );
63680
63862
  }
63681
- if (input.iconPath && existsSync64(input.iconPath)) {
63863
+ if (input.iconPath && existsSync65(input.iconPath)) {
63682
63864
  try {
63683
63865
  const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
63684
63866
  wrote.push(...installed.wrote);
@@ -64792,10 +64974,10 @@ function permuteDomain(domain, allowSpecialUseDomain) {
64792
64974
  }
64793
64975
  function createPromiseCallback(cb) {
64794
64976
  let callback;
64795
- let resolve53;
64977
+ let resolve54;
64796
64978
  let reject;
64797
64979
  const promise = new Promise((_resolve, _reject) => {
64798
- resolve53 = _resolve;
64980
+ resolve54 = _resolve;
64799
64981
  reject = _reject;
64800
64982
  });
64801
64983
  if (typeof cb === "function") {
@@ -64811,7 +64993,7 @@ function createPromiseCallback(cb) {
64811
64993
  callback = (err, result) => {
64812
64994
  try {
64813
64995
  if (err) reject(err);
64814
- else resolve53(result);
64996
+ else resolve54(result);
64815
64997
  } catch (e) {
64816
64998
  reject(e instanceof Error ? e : new Error());
64817
64999
  }
@@ -67899,14 +68081,14 @@ async function runSiteFunction(opts) {
67899
68081
  }
67900
68082
  if (opts.op === "publish") {
67901
68083
  const snap = await snapshotAndPublish(fetchImpl, opts.token, opts.msid, { production: true, initiator: "himi" });
67902
- const ok = httpOk(snap.rev) && httpOk(snap.live);
68084
+ const ok2 = httpOk(snap.rev) && httpOk(snap.live);
67903
68085
  return {
67904
68086
  ...base,
67905
- ok,
68087
+ ok: ok2,
67906
68088
  revision: snap.revision,
67907
68089
  codeAppId: snap.codeAppId,
67908
68090
  publish: { revision: httpOk(snap.rev), rc: httpOk(snap.rc), live: httpOk(snap.live), status: snap.live?.status },
67909
- error: ok ? void 0 : snippet2(snap.live?.json ?? snap.rev.json)
68091
+ error: ok2 ? void 0 : snippet2(snap.live?.json ?? snap.rev.json)
67910
68092
  };
67911
68093
  }
67912
68094
  const { id, listed } = await withGrid(fetchImpl, opts.token, opts.msid, opts.siteUrl);
@@ -68001,12 +68183,12 @@ async function invokeAndReport(fetchImpl, opts, base, name, method) {
68001
68183
  await new Promise((res) => setTimeout(res, 2500));
68002
68184
  hit = await tryInvoke();
68003
68185
  }
68004
- const ok = httpOk(hit.r);
68186
+ const ok2 = httpOk(hit.r);
68005
68187
  return {
68006
68188
  ...base,
68007
- ok,
68189
+ ok: ok2,
68008
68190
  invoke: { url: hit.url, status: hit.r.status, body: hit.r.json ?? snippet2(hit.r.text) },
68009
- error: ok ? void 0 : `invoke ${hit.r.status}: ${snippet2(hit.r.json ?? hit.r.text)}`
68191
+ error: ok2 ? void 0 : `invoke ${hit.r.status}: ${snippet2(hit.r.json ?? hit.r.text)}`
68010
68192
  };
68011
68193
  }
68012
68194
  var HTTP_METHODS2, WRITE_LAYOUTS, VELO_PROVISION_URL, SITE_PUBLISH_URL, PUBLISH_RC_URL, SITE_FUNCTION_USAGE, NAME_RE, EXPORT_HEAD, WIX_HTTP_IMPORT_LINE;
@@ -68040,8 +68222,8 @@ __export(cli_exports, {
68040
68222
  runSiteAnalyze: () => runSiteAnalyze,
68041
68223
  runSiteFunctionCli: () => runSiteFunctionCli
68042
68224
  });
68043
- import { readFileSync as readFileSync77 } from "node:fs";
68044
- import { resolve as resolve51 } from "node:path";
68225
+ import { readFileSync as readFileSync78 } from "node:fs";
68226
+ import { resolve as resolve52 } from "node:path";
68045
68227
  function assetFetchFor(_opts) {
68046
68228
  return pinnedFetch2;
68047
68229
  }
@@ -68061,7 +68243,7 @@ async function runSiteAnalyze(opts) {
68061
68243
  const assetFetch = assetFetchFor(opts);
68062
68244
  const siteFetch = guardedSiteFetch;
68063
68245
  const cwd = opts.cwd ?? process.cwd();
68064
- const outDir = resolve51(cwd, opts.outDir ?? ".himi/business-book");
68246
+ const outDir = resolve52(cwd, opts.outDir ?? ".himi/business-book");
68065
68247
  let ownerAuth;
68066
68248
  let msid;
68067
68249
  const ownerSite = ownerSiteFor(opts);
@@ -68113,9 +68295,9 @@ async function runSiteAnalyze(opts) {
68113
68295
  if (opts.apply) {
68114
68296
  applied = await applyOverlays({
68115
68297
  cwd,
68116
- overlayPath: resolve51(outDir, "provisioning.overlay.json"),
68117
- tokensPath: resolve51(outDir, "tokens.overlay.json"),
68118
- iconPath: resolve51(outDir, "media/icon.png"),
68298
+ overlayPath: resolve52(outDir, "provisioning.overlay.json"),
68299
+ tokensPath: resolve52(outDir, "tokens.overlay.json"),
68300
+ iconPath: resolve52(outDir, "media/icon.png"),
68119
68301
  shell: opts.shell
68120
68302
  });
68121
68303
  const note = noteWithWarnings(applied.note, warnings);
@@ -68151,8 +68333,8 @@ async function runSiteFunctionCli(opts) {
68151
68333
  const token = opts.token ?? await siteToken(msid);
68152
68334
  let source;
68153
68335
  if (opts.sourcePath) {
68154
- const p = resolve51(opts.cwd ?? process.cwd(), opts.sourcePath);
68155
- source = readFileSync77(p, "utf8");
68336
+ const p = resolve52(opts.cwd ?? process.cwd(), opts.sourcePath);
68337
+ source = readFileSync78(p, "utf8");
68156
68338
  }
68157
68339
  let body;
68158
68340
  if (opts.bodyRaw != null) {
@@ -68207,7 +68389,7 @@ async function accountToken2(spawnImpl = spawn6) {
68207
68389
  cached2 = fromEnv;
68208
68390
  return fromEnv;
68209
68391
  }
68210
- const token = await new Promise((resolve53, reject) => {
68392
+ const token = await new Promise((resolve54, reject) => {
68211
68393
  let child;
68212
68394
  try {
68213
68395
  child = spawnImpl("wix", ["token"]);
@@ -68236,7 +68418,7 @@ async function accountToken2(spawnImpl = spawn6) {
68236
68418
  const scan = (d) => {
68237
68419
  out2 += String(d);
68238
68420
  const m = out2.match(TOKEN_RE2);
68239
- if (m) done(() => resolve53(m[0]));
68421
+ if (m) done(() => resolve54(m[0]));
68240
68422
  };
68241
68423
  child.stdout?.on("data", scan);
68242
68424
  child.stderr?.on("data", scan);
@@ -68413,7 +68595,7 @@ __export(site_create_exports, {
68413
68595
  runSiteList: () => runSiteList,
68414
68596
  writeProvisioningBinding: () => writeProvisioningBinding
68415
68597
  });
68416
- import { existsSync as existsSync65, readFileSync as readFileSync78, writeFileSync as writeFileSync28 } from "node:fs";
68598
+ import { existsSync as existsSync66, readFileSync as readFileSync79, writeFileSync as writeFileSync29 } from "node:fs";
68417
68599
  import { resolve as resolvePath2 } from "node:path";
68418
68600
  function oauthClientName(projectName) {
68419
68601
  return `${projectName} client`;
@@ -68562,7 +68744,7 @@ async function runSiteCreate(opts) {
68562
68744
  if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
68563
68745
  return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
68564
68746
  }
68565
- function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync65, readFileSync: readFileSync78, writeFileSync: writeFileSync28 }) {
68747
+ function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync66, readFileSync: readFileSync79, writeFileSync: writeFileSync29 }) {
68566
68748
  const msid = binding2.siteId;
68567
68749
  const path2 = resolvePath2(target);
68568
68750
  const committed = committedShellProvisioning(path2);
@@ -69235,12 +69417,12 @@ var init_context = __esm({
69235
69417
  });
69236
69418
 
69237
69419
  // src/cli.ts
69238
- import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync79, mkdirSync as mkdirSync32, writeFileSync as writeFileSync29, existsSync as existsSync66, rmSync as rmSync15, readdirSync as readdirSync30, statSync as statSync18, lstatSync as lstatSync13, accessSync, constants as constants2, renameSync as renameSync7, cpSync as cpSync3 } from "node:fs";
69420
+ import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync80, mkdirSync as mkdirSync33, writeFileSync as writeFileSync30, existsSync as existsSync67, rmSync as rmSync16, readdirSync as readdirSync31, statSync as statSync19, lstatSync as lstatSync14, accessSync, constants as constants2, renameSync as renameSync7, cpSync as cpSync3 } from "node:fs";
69239
69421
  import { execFile, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn7 } from "node:child_process";
69240
69422
  import { AsyncLocalStorage } from "node:async_hooks";
69241
69423
  import { createHash as createHash31, randomUUID as randomUUID7 } from "node:crypto";
69242
69424
  import { tmpdir as tmpdir5, homedir as homedir7, hostname } from "node:os";
69243
- import { join as join64, resolve as resolve52, relative as relative13, basename as basename17, dirname as dirname36 } from "node:path";
69425
+ import { join as join65, resolve as resolve53, relative as relative14, basename as basename17, dirname as dirname37 } from "node:path";
69244
69426
  import { fileURLToPath as fileURLToPath26 } from "node:url";
69245
69427
 
69246
69428
  // ../serve-cli/src/client.ts
@@ -69981,7 +70163,7 @@ async function browserLogin(opts) {
69981
70163
  const log = opts.log ?? (() => {
69982
70164
  });
69983
70165
  const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
69984
- return await new Promise((resolve53, reject) => {
70166
+ return await new Promise((resolve54, reject) => {
69985
70167
  let settled = false;
69986
70168
  let loginUrl = "";
69987
70169
  const server = createServer();
@@ -70045,7 +70227,7 @@ async function browserLogin(opts) {
70045
70227
  return;
70046
70228
  }
70047
70229
  res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store", connection: "close" }).end(CLOSE_PAGE);
70048
- finish2(() => resolve53({ token, loginUrl }));
70230
+ finish2(() => resolve54({ token, loginUrl }));
70049
70231
  });
70050
70232
  });
70051
70233
  server.on("error", (err) => finish2(() => reject(err)));
@@ -71375,8 +71557,8 @@ var str8 = (v) => typeof v === "string" ? v : void 0;
71375
71557
  var num2 = (v) => typeof v === "string" && v !== "" && Number.isFinite(Number(v)) ? Number(v) : void 0;
71376
71558
  function embeddedTemplateCatalog() {
71377
71559
  return availableTemplates().map((name) => {
71378
- const path2 = join64(templateSourceDir(name), TEMPLATE_META_FILE);
71379
- const meta = JSON.parse(readFileSync79(path2, "utf8"));
71560
+ const path2 = join65(templateSourceDir(name), TEMPLATE_META_FILE);
71561
+ const meta = JSON.parse(readFileSync80(path2, "utf8"));
71380
71562
  if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
71381
71563
  throw new Error(`${path2} must be { title: string, description: string, tags: string[], category?: string }`);
71382
71564
  }
@@ -72058,7 +72240,7 @@ var COMMANDS = [
72058
72240
  { name: "pull", summary: "restore an app's SOURCE from the serve plane into an editable content package \u2014 the other half of `himi push`, which archives the content package on every publish. Owner or editor only: a viewer may download the RUNNING app (`/v1/owner/package`), not the codebase it was built from. A PAST release is restorable, not only the live one \u2014 the archive is content-addressed per release, so it has none of the live-single-slot problem that makes `himi pack` current-release-only. Two limits: pruning keeps the current release plus the newest ~20 ledger entries, and a release id identifies OTA content rather than source, so a source-only change republishes under the same id and replaces that id's archive. A release published before source archiving shipped, or pushed with `--no-source`, answers `app_source_not_found` and says to push again. `--name` re-substitutes the app identity through the same machinery `himi init --template` uses, so the restored tree is a NEW app rather than a second copy of the same one, and a name that also appears inside a screen id (`feed` in `feed_home`) is left alone. A NON-EMPTY destination is refused unless you say which you mean: `--force` merges and reports \u2014 it writes the archive over what is there, keeps files the release does not carry, and NAMES every one of them as `left: [...]` so a tree that matches no release is never silent (#2437); `--replace` restores exactly what was archived, removing those files first (`removed: [...]`) and implying `--force`. `--replace` refuses a directory holding no `himalaya.content.json`, so a mistyped `--out` cannot clear an unrelated tree, and the only paths it can remove are the ones a push would have archived \u2014 `.git/`, `node_modules/`, `dist/`, `.env*` and key material are out of its reach by construction.", required: "<app> [--release <id>] [--out <dir>] [--name <new>] [--force|--replace] [--target <t>]" },
72059
72241
  { name: "share", summary: "publish or revoke a content-addressed `.himi` share link. The package must be a validated archive for an already-published release; the resulting https URL is safe to QR, copy, or open in Himi Player.", required: "--file <package.himi> [--expires-at <ISO>] | revoke --app <app> <shareId>" },
72060
72242
  { name: "run", summary: "serve a .himi package on localhost and open it in a browser \u2014 no serve plane, no dev-server, no setup. Given no argument it builds the current content package first, so `himi run` is the inner loop: edit, run, look at it. The SPA and /v1 are served from ONE origin because Tier-5 bundle fetches on web are same-origin-only. --chrome preview frames the app in a device chassis; --chrome app serves it as a plain web app. Blocks until Ctrl-C, like any dev server. --browser runs the whole plane INSIDE the tab (service worker + in-memory store) so no app code executes in this process or on any pod. --lan also serves it to the local network and prints a QR, so a phone on the same Wi-Fi opens it as the real app, full screen. --watch keeps the preview LIVE: every save in the content package rebuilds it and repaints the open tab with only what changed (the dev-server's hot-reload events); a build that fails keeps the last good preview on screen and says why. --idle-exit <min> (with --watch only) stops the watch once that many minutes pass with no source save, printing `{\"watch\":\"idle_exit\"}` and removing its .himi/run.json on the way out \u2014 the watch `himi init` starts passes 30; one started by hand runs until Ctrl-C. Stopping (Ctrl-C, SIGTERM, SIGHUP or the idle exit) removes the run's own .himi/run.json. Any `himi run` of a content package (plain, --watch or --browser) frames its preview on the build board (`himi studio`) while it serves, and all but --browser also serve that board at /__himi/studio/ on the preview's own origin. Its .himi/run.json (pid, watching) is also how `himi render` and `himi test` tell a live --watch is running: while none is, they add a `reminder` naming `himi run --watch --content <dir> &`, and while one is (the one `himi init` started, usually, whose .himi/watch.json vouches for it until it serves) the reminder names its url and board instead (either at most once every ten minutes per app) \u2014 first in `next[]` and again as the envelope's LAST key (the last line of `himi test`'s plain report), so an output read with `tail` still carries it.", required: "[<package.himi|dir|url>] [--browser] [--watch] [--idle-exit <min>] [--lan] [--content <dir>] [--port <n>] [--chrome preview|app] [--screen <id>] [--surface <id>] [--no-open] [--spa <url>]" },
72061
- { name: "mcp", summary: "run the himi tools as a local Model Context Protocol server over stdio, for coding agents \u2014 Claude Code, Cursor, Codex, VS Code. Tools: docs/components/sdk/icons, init, build, validate, test (hermetic), render (returns the PNG), progress, a live preview (start/status/stop a `himi run --watch`), whoami, login (opens the browser sign-in for the user; the credential goes to a child `himi login` and onto disk, never through the server), and DRAFT-only push/share/preview links \u2014 never promote, dist or secrets. A sign-in's target is the one push/share then use. Each tool runs the same command in-process on the content package on disk (default: the host's workspace root). `himi init` and `himi agent-init` write the config for every host (.mcp.json, .cursor/mcp.json, .vscode/mcp.json, .codex/config.toml when absent) plus a `himi-preview` launch configuration (.claude/launch.json) that opens the live preview in Claude Code desktop's browser pane. Never self-updates (npx already runs the current CLI). Blocks until the host closes stdin. `himi mcp plugin --out <dir>` writes the Claude Code plugin (the customer skill + this server) as a folder \u2014 the same plugin the serve plane's marketplace hands out at /.claude-plugin/marketplace.json.", required: "[plugin --out <dir>]" },
72243
+ { name: "mcp", summary: "run the himi tools as a local Model Context Protocol server over stdio, for coding agents \u2014 Claude Code, Cursor, Codex, VS Code. Tools: docs/components/sdk/icons, init, build, validate, test (hermetic), render (returns the PNG), progress, a live preview (start/status/stop a `himi run --watch`), whoami, login (opens the browser sign-in for the user; the credential goes to a child `himi login` and onto disk, never through the server), and DRAFT-only push/share/preview links \u2014 never promote, dist or secrets. A sign-in's target is the one push/share then use. Each tool runs the same command in-process on the content package on disk (default: the host's workspace root). `himi init` and `himi agent-init` write the config for every host (.mcp.json, .cursor/mcp.json, .vscode/mcp.json, .codex/config.toml when absent) plus a `himi-preview` launch configuration (.claude/launch.json) that opens the live preview in Claude Code desktop's browser pane. Never self-updates (npx already runs the current CLI). Blocks until the host closes stdin. `himi mcp plugin --out <dir>` writes the Claude Code plugin (the customer skill + this server) as a folder \u2014 the same plugin the serve plane's marketplace hands out at /.claude-plugin/marketplace.json. `--with-files` adds list/read/write/delete file tools confined to the workspace folder, for a host that cannot edit files (Claude Desktop chat, via the Desktop Extension); `HIMI_WORKSPACE` names that folder when the host names none.", required: "[plugin --out <dir>] [--with-files]" },
72062
72244
  { name: "preview", summary: "print the shareable web URL + himi:// deep link + agent /v1/preview JSON URLs for an app+release; --surface frames the web preview as any catalog surface (?surface=)", required: "--app --release [--screen] [--surface]" },
72063
72245
  { name: "surfaces", summary: "the surface catalog vs this app's envelope (platforms.json): targeted surfaces, the opt-in key for the rest, per-surface preview links with --app --release, and which widget families the package produces with --measure-widgets (which runs its built bundles)", required: "[--content <dir>] [--app --release] [--measure-widgets]" },
72064
72246
  { name: "context", summary: "fetch the agent preview envelope (GET /v1/preview/a/<app>) \u2014 ok/issues/screens/links; exit 1 if ok:false", required: "--app --release [--screen] [--include telemetry]" },
@@ -72090,7 +72272,7 @@ var COMMANDS = [
72090
72272
  ];
72091
72273
  function cliVersion() {
72092
72274
  try {
72093
- return JSON.parse(readFileSync79(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
72275
+ return JSON.parse(readFileSync80(new URL("../package.json", import.meta.url), "utf8")).version ?? "unknown";
72094
72276
  } catch {
72095
72277
  return "unknown";
72096
72278
  }
@@ -72141,16 +72323,16 @@ function createScopedRegistryResolver(exec = execNpmConfig) {
72141
72323
  }
72142
72324
  var SCOPED_REGISTRY_TIMEOUT_MS = 5e3;
72143
72325
  function execNpmConfig(file, args, options) {
72144
- return new Promise((resolve53, reject) => {
72145
- execFile(file, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) : resolve53(String(stdout)));
72326
+ return new Promise((resolve54, reject) => {
72327
+ execFile(file, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) : resolve54(String(stdout)));
72146
72328
  });
72147
72329
  }
72148
72330
  var npmScopedWixRegistry = createScopedRegistryResolver();
72149
72331
  async function scopedRegistryBefore(lookup2, deadline) {
72150
72332
  let cancel = () => {
72151
72333
  };
72152
- const expired = new Promise((resolve53) => {
72153
- const timer = setTimeout(() => resolve53(void 0), Math.max(0, deadline - Date.now()));
72334
+ const expired = new Promise((resolve54) => {
72335
+ const timer = setTimeout(() => resolve54(void 0), Math.max(0, deadline - Date.now()));
72154
72336
  cancel = () => clearTimeout(timer);
72155
72337
  });
72156
72338
  try {
@@ -72208,18 +72390,18 @@ function ageInDays(publishedAt, now = Date.now()) {
72208
72390
  }
72209
72391
  function packageVersion(path2) {
72210
72392
  try {
72211
- const version2 = JSON.parse(readFileSync79(path2, "utf8")).version;
72393
+ const version2 = JSON.parse(readFileSync80(path2, "utf8")).version;
72212
72394
  return typeof version2 === "string" && version2 ? version2 : void 0;
72213
72395
  } catch {
72214
72396
  return void 0;
72215
72397
  }
72216
72398
  }
72217
72399
  function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
72218
- let dir = resolve52(fromDir);
72400
+ let dir = resolve53(fromDir);
72219
72401
  for (; ; ) {
72220
- const version2 = packageVersion(join64(dir, "node_modules", "@wix", "himalaya", "package.json"));
72402
+ const version2 = packageVersion(join65(dir, "node_modules", "@wix", "himalaya", "package.json"));
72221
72403
  if (version2) return { version: version2, source: "local" };
72222
- const parent = dirname36(dir);
72404
+ const parent = dirname37(dir);
72223
72405
  if (parent === dir) break;
72224
72406
  dir = parent;
72225
72407
  }
@@ -72227,7 +72409,7 @@ function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("
72227
72409
  if (bundled) return { version: bundled, source: "bundled" };
72228
72410
  try {
72229
72411
  const root = execFileSync7("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
72230
- const version2 = root ? packageVersion(join64(root, "@wix", "himalaya", "package.json")) : void 0;
72412
+ const version2 = root ? packageVersion(join65(root, "@wix", "himalaya", "package.json")) : void 0;
72231
72413
  return version2 ? { version: version2, source: "global" } : {};
72232
72414
  } catch {
72233
72415
  return {};
@@ -72274,11 +72456,11 @@ var UPDATE_RETRY_AFTER_FAILURE_MS = 60 * 60 * 1e3;
72274
72456
  var UPDATE_SNOOZE_MS = 24 * 60 * 60 * 1e3;
72275
72457
  var UPDATE_REEXEC_ENV = "HIMI_UPDATED_ONCE";
72276
72458
  function updateCachePath(env = process.env) {
72277
- return env.HIMI_UPDATE_CACHE_FILE ?? join64(homedir7(), ".himalaya", "update-check.json");
72459
+ return env.HIMI_UPDATE_CACHE_FILE ?? join65(homedir7(), ".himalaya", "update-check.json");
72278
72460
  }
72279
72461
  function readUpdateCache(path2) {
72280
72462
  try {
72281
- const parsed = JSON.parse(readFileSync79(path2, "utf8"));
72463
+ const parsed = JSON.parse(readFileSync80(path2, "utf8"));
72282
72464
  return parsed && typeof parsed === "object" ? parsed : {};
72283
72465
  } catch {
72284
72466
  return {};
@@ -72286,8 +72468,8 @@ function readUpdateCache(path2) {
72286
72468
  }
72287
72469
  function writeUpdateCache(path2, cache) {
72288
72470
  try {
72289
- mkdirSync32(dirname36(path2), { recursive: true, mode: 448 });
72290
- writeFileSync29(path2, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
72471
+ mkdirSync33(dirname37(path2), { recursive: true, mode: 448 });
72472
+ writeFileSync30(path2, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
72291
72473
  } catch {
72292
72474
  }
72293
72475
  }
@@ -72347,12 +72529,12 @@ function createUpdateRunner(spawn8 = spawnSync5) {
72347
72529
  },
72348
72530
  installedVersion: () => {
72349
72531
  const root = globalNodeModulesRoot();
72350
- return root ? packageVersion(join64(root, "@wix", "himalaya-cli", "package.json")) : void 0;
72532
+ return root ? packageVersion(join65(root, "@wix", "himalaya-cli", "package.json")) : void 0;
72351
72533
  },
72352
72534
  reexec: (argv) => {
72353
72535
  const root = globalNodeModulesRoot();
72354
- const entry = root ? join64(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
72355
- if (!entry || !existsSync66(entry)) return void 0;
72536
+ const entry = root ? join65(root, "@wix", "himalaya-cli", "dist", "cli.mjs") : void 0;
72537
+ if (!entry || !existsSync67(entry)) return void 0;
72356
72538
  const result = spawnSync5(process.execPath, [entry, ...argv], {
72357
72539
  // inherit keeps PIPED STDIN working — commands that read stdin must survive a re-exec.
72358
72540
  stdio: "inherit",
@@ -72399,7 +72581,7 @@ function staleUpdateLockFile(cachePath, now) {
72399
72581
  for (const path2 of [`${cachePath}.lock.break`, `${cachePath}.lock`]) {
72400
72582
  let content;
72401
72583
  try {
72402
- content = readFileSync79(path2, "utf8");
72584
+ content = readFileSync80(path2, "utf8");
72403
72585
  } catch {
72404
72586
  continue;
72405
72587
  }
@@ -72407,7 +72589,7 @@ function staleUpdateLockFile(cachePath, now) {
72407
72589
  let since = stamped;
72408
72590
  if (!Number.isFinite(since)) {
72409
72591
  try {
72410
- since = statSync18(path2).mtimeMs;
72592
+ since = statSync19(path2).mtimeMs;
72411
72593
  } catch {
72412
72594
  continue;
72413
72595
  }
@@ -72422,14 +72604,14 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
72422
72604
  const mine = lockStamp(now);
72423
72605
  const readLock = (path2) => {
72424
72606
  try {
72425
- return readFileSync79(path2, "utf8");
72607
+ return readFileSync80(path2, "utf8");
72426
72608
  } catch {
72427
72609
  return void 0;
72428
72610
  }
72429
72611
  };
72430
72612
  const tryCreate = (path2) => {
72431
72613
  try {
72432
- writeFileSync29(path2, mine, { flag: "wx", mode: 384 });
72614
+ writeFileSync30(path2, mine, { flag: "wx", mode: 384 });
72433
72615
  return true;
72434
72616
  } catch {
72435
72617
  return false;
@@ -72437,13 +72619,13 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
72437
72619
  };
72438
72620
  const removeIfMine = (path2) => {
72439
72621
  try {
72440
- if (readLock(path2) === mine) rmSync15(path2, { force: true });
72622
+ if (readLock(path2) === mine) rmSync16(path2, { force: true });
72441
72623
  } catch {
72442
72624
  }
72443
72625
  };
72444
72626
  const release = () => removeIfMine(lockPath);
72445
72627
  try {
72446
- mkdirSync32(dirname36(lockPath), { recursive: true, mode: 448 });
72628
+ mkdirSync33(dirname37(lockPath), { recursive: true, mode: 448 });
72447
72629
  } catch {
72448
72630
  return () => {
72449
72631
  };
@@ -72460,7 +72642,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
72460
72642
  hooks.underBreakLock?.();
72461
72643
  if (current === void 0) return tryCreate(lockPath) ? release : void 0;
72462
72644
  if (!isAbandoned(current)) return void 0;
72463
- rmSync15(lockPath, { force: true });
72645
+ rmSync16(lockPath, { force: true });
72464
72646
  return tryCreate(lockPath) ? release : void 0;
72465
72647
  } finally {
72466
72648
  removeIfMine(breakPath);
@@ -72556,7 +72738,7 @@ function createTrimValidator(deps = {}, spawnFn = spawn7) {
72556
72738
  return { code, counts, ...errors ? { errors } : {}, ...code !== 0 ? { tail: said.slice(-4e3) } : {} };
72557
72739
  };
72558
72740
  return async (dir, opts = {}) => {
72559
- const argv = ["validate", "--content", resolve52(dir), "--strict", "--skip-version-check"];
72741
+ const argv = ["validate", "--content", resolve53(dir), "--strict", "--skip-version-check"];
72560
72742
  if (!opts.fresh) {
72561
72743
  const out2 = [];
72562
72744
  const err = [];
@@ -73014,9 +73196,9 @@ function executableOnPath(name, env = process.env) {
73014
73196
  const suffixes = process.platform === "win32" ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
73015
73197
  for (const dir of entries) {
73016
73198
  for (const suffix of suffixes) {
73017
- const candidate = join64(dir, `${name}${suffix}`);
73199
+ const candidate = join65(dir, `${name}${suffix}`);
73018
73200
  try {
73019
- if (!statSync18(candidate).isFile()) continue;
73201
+ if (!statSync19(candidate).isFile()) continue;
73020
73202
  if (process.platform !== "win32") accessSync(candidate, constants2.X_OK);
73021
73203
  return true;
73022
73204
  } catch {
@@ -73063,9 +73245,9 @@ function buildDoctorReport(input) {
73063
73245
  const versionSkew = versions?.cli.status === "outdated" || sdkSkew;
73064
73246
  const hostRefused = auth.controlTokenStatus === "refused";
73065
73247
  const staleToken = auth.controlTokenPresent === true && auth.controlToken === false && !hostRefused;
73066
- const ok = data.reachable && serve.reachable && !versionSkew && !staleToken && !hostRefused;
73248
+ const ok2 = data.reachable && serve.reachable && !versionSkew && !staleToken && !hostRefused;
73067
73249
  return {
73068
- ok,
73250
+ ok: ok2,
73069
73251
  target,
73070
73252
  version: version2,
73071
73253
  dataPlane: { ...data, note: "public Wix APIs \u2014 reachable off-VPN" },
@@ -73123,7 +73305,7 @@ async function nativeConfigAdvisories(app, configSource) {
73123
73305
  const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths2(), paths_exports));
73124
73306
  const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
73125
73307
  const iosYmlPath = iosProjectYml2(app);
73126
- const iosYml = existsSync66(iosYmlPath) ? readFileSync79(iosYmlPath, "utf8") : "";
73308
+ const iosYml = existsSync67(iosYmlPath) ? readFileSync80(iosYmlPath, "utf8") : "";
73127
73309
  let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
73128
73310
  if (!optedIn) {
73129
73311
  const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
@@ -73137,14 +73319,14 @@ async function nativeConfigAdvisories(app, configSource) {
73137
73319
  }
73138
73320
  function readConfigSource(dir) {
73139
73321
  try {
73140
- return readFileSync79(join64(dir, "config.ts"), "utf8");
73322
+ return readFileSync80(join65(dir, "config.ts"), "utf8");
73141
73323
  } catch {
73142
73324
  return null;
73143
73325
  }
73144
73326
  }
73145
73327
  function writePngFile(path2, base64) {
73146
- mkdirSync32(dirname36(path2), { recursive: true });
73147
- writeFileSync29(path2, Buffer.from(base64, "base64"));
73328
+ mkdirSync33(dirname37(path2), { recursive: true });
73329
+ writeFileSync30(path2, Buffer.from(base64, "base64"));
73148
73330
  return path2;
73149
73331
  }
73150
73332
  async function seedAgentFilesFor(dir, flags, mode = "init") {
@@ -73172,8 +73354,8 @@ function keptPlan(kept) {
73172
73354
  return note ? { kept, note } : {};
73173
73355
  }
73174
73356
  async function initFromRemoteTemplate(name, parentDir, template, c) {
73175
- const dir = resolve52(parentDir, name);
73176
- if (existsSync66(join64(dir, "himalaya.content.json"))) {
73357
+ const dir = resolve53(parentDir, name);
73358
+ if (existsSync67(join65(dir, "himalaya.content.json"))) {
73177
73359
  throw new Error(`content package already exists at ${dir}`);
73178
73360
  }
73179
73361
  const r = await c.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
@@ -73185,7 +73367,7 @@ async function initFromRemoteTemplate(name, parentDir, template, c) {
73185
73367
  return finishScaffold(materializeSource(archive.files, name, dir), template);
73186
73368
  }
73187
73369
  function contentDir(flags) {
73188
- return resolve52(str8(flags.content) ?? process.cwd());
73370
+ return resolve53(str8(flags.content) ?? process.cwd());
73189
73371
  }
73190
73372
  function renameRestoredSource(restored, declaredApp, renamed) {
73191
73373
  const text8 = {};
@@ -73203,7 +73385,7 @@ function renameRestoredSource(restored, declaredApp, renamed) {
73203
73385
  function symlinkDestinationIssue(dest) {
73204
73386
  let kind;
73205
73387
  try {
73206
- kind = lstatSync13(dest);
73388
+ kind = lstatSync14(dest);
73207
73389
  } catch {
73208
73390
  return null;
73209
73391
  }
@@ -73216,11 +73398,11 @@ function symlinkDestinationIssue(dest) {
73216
73398
  function restoreDestinationIssue(dest, force) {
73217
73399
  const link = symlinkDestinationIssue(dest);
73218
73400
  if (link) return link;
73219
- if (!existsSync66(dest)) return null;
73220
- if (!statSync18(dest).isDirectory()) {
73401
+ if (!existsSync67(dest)) return null;
73402
+ if (!statSync19(dest).isDirectory()) {
73221
73403
  return { error: `${dest} exists and is not a directory`, hint: "pass --out/--name to land somewhere else, or remove the file" };
73222
73404
  }
73223
- if (readdirSync30(dest).length > 0 && !force) {
73405
+ if (readdirSync31(dest).length > 0 && !force) {
73224
73406
  return {
73225
73407
  error: `${dest} already exists and is not empty`,
73226
73408
  hint: "pass --force to write into it anyway, or --out/--name to land somewhere else"
@@ -73229,10 +73411,10 @@ function restoreDestinationIssue(dest, force) {
73229
73411
  return null;
73230
73412
  }
73231
73413
  function isHimalayaMonorepoCheckout(start) {
73232
- let dir = resolve52(start);
73414
+ let dir = resolve53(start);
73233
73415
  for (; ; ) {
73234
- if (existsSync66(join64(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync66(join64(dir, "core", "serve", "src", "server.ts"))) return true;
73235
- const parent = dirname36(dir);
73416
+ if (existsSync67(join65(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync67(join65(dir, "core", "serve", "src", "server.ts"))) return true;
73417
+ const parent = dirname37(dir);
73236
73418
  if (parent === dir) return false;
73237
73419
  dir = parent;
73238
73420
  }
@@ -73291,8 +73473,8 @@ function materializeForPreview(appDir3, slug, displayName) {
73291
73473
  const forBuild = Object.fromEntries(
73292
73474
  Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
73293
73475
  );
73294
- const repoRoot2 = resolve52(fileURLToPath26(new URL("../../..", import.meta.url)));
73295
- const root = join64(repoRoot2, "node_modules", ".cache", "himi-template-preview");
73476
+ const repoRoot2 = resolve53(fileURLToPath26(new URL("../../..", import.meta.url)));
73477
+ const root = join65(repoRoot2, "node_modules", ".cache", "himi-template-preview");
73296
73478
  const stillRunning = (pid) => {
73297
73479
  try {
73298
73480
  process.kill(pid, 0);
@@ -73302,30 +73484,30 @@ function materializeForPreview(appDir3, slug, displayName) {
73302
73484
  }
73303
73485
  };
73304
73486
  try {
73305
- for (const entry of readdirSync30(root, { withFileTypes: true })) {
73487
+ for (const entry of readdirSync31(root, { withFileTypes: true })) {
73306
73488
  if (!entry.isDirectory()) continue;
73307
73489
  const pid = Number(entry.name.startsWith(`${slug}-`) ? entry.name.slice(slug.length + 1) : NaN);
73308
73490
  if (Number.isInteger(pid) && pid > 0 && pid !== process.pid && !stillRunning(pid)) {
73309
- rmSync15(join64(root, entry.name), { recursive: true, force: true });
73491
+ rmSync16(join65(root, entry.name), { recursive: true, force: true });
73310
73492
  }
73311
73493
  }
73312
73494
  } catch {
73313
73495
  }
73314
- const dest = join64(root, `${slug}-${process.pid}`);
73315
- rmSync15(dest, { recursive: true, force: true });
73316
- mkdirSync32(dest, { recursive: true });
73496
+ const dest = join65(root, `${slug}-${process.pid}`);
73497
+ rmSync16(dest, { recursive: true, force: true });
73498
+ mkdirSync33(dest, { recursive: true });
73317
73499
  try {
73318
73500
  materializeSource(forBuild, displayName, dest, slug);
73319
73501
  } catch (e) {
73320
- rmSync15(dest, { recursive: true, force: true });
73502
+ rmSync16(dest, { recursive: true, force: true });
73321
73503
  throw e;
73322
73504
  }
73323
73505
  return dest;
73324
73506
  }
73325
73507
  async function appId(dir) {
73326
73508
  try {
73327
- const { readFileSync: readFileSync80 } = await import("node:fs");
73328
- const m = JSON.parse(readFileSync80(join64(dir, "himalaya.content.json"), "utf8"));
73509
+ const { readFileSync: readFileSync81 } = await import("node:fs");
73510
+ const m = JSON.parse(readFileSync81(join65(dir, "himalaya.content.json"), "utf8"));
73329
73511
  if (m.name) return m.name;
73330
73512
  } catch {
73331
73513
  }
@@ -73333,8 +73515,8 @@ async function appId(dir) {
73333
73515
  }
73334
73516
  async function contentVisibility(dir) {
73335
73517
  try {
73336
- const { readFileSync: readFileSync80 } = await import("node:fs");
73337
- const m = JSON.parse(readFileSync80(join64(dir, "himalaya.content.json"), "utf8"));
73518
+ const { readFileSync: readFileSync81 } = await import("node:fs");
73519
+ const m = JSON.parse(readFileSync81(join65(dir, "himalaya.content.json"), "utf8"));
73338
73520
  if (m.visibility === "public" || m.visibility === "unlisted") return m.visibility;
73339
73521
  } catch {
73340
73522
  }
@@ -73537,7 +73719,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
73537
73719
  return 0;
73538
73720
  }
73539
73721
  case "agent-init": {
73540
- const dir = resolve52(str8(flags.dir) ?? process.cwd());
73722
+ const dir = resolve53(str8(flags.dir) ?? process.cwd());
73541
73723
  const { seedAgentFiles: seedAgentFiles2, NotAContentPackage: NotAContentPackage2 } = await Promise.resolve().then(() => (init_agent_context(), agent_context_exports));
73542
73724
  let res;
73543
73725
  try {
@@ -73559,7 +73741,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
73559
73741
  ...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/" } : {},
73560
73742
  // In a git repo the refresh moves the diff identity an earlier `himi test` attested (that
73561
73743
  // hash is shared with the repo gates and deliberately exempts nothing but its own metadata).
73562
- ...existsSync66(join64(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" } : {},
73744
+ ...existsSync67(join65(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" } : {},
73563
73745
  ...res.skipped.length ? { skipped: res.skipped } : {},
73564
73746
  portalUrl: idx.portalUrl
73565
73747
  });
@@ -73582,7 +73764,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
73582
73764
  try {
73583
73765
  const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
73584
73766
  const bres = await buildContentForValidation2(dir, { resolution });
73585
- out2 = mkdtempSync4(join64(tmpdir5(), "himi-ux-record-"));
73767
+ out2 = mkdtempSync4(join65(tmpdir5(), "himi-ux-record-"));
73586
73768
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
73587
73769
  const outcome = await buildReleaseFromContent2(dir, out2, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {}, collect: { lint: true } });
73588
73770
  const releaseId = outcome.manifest.releaseId;
@@ -73595,7 +73777,7 @@ async function recordedReleaseForContentQuietly(dir, resolution, onDrift) {
73595
73777
  return null;
73596
73778
  } finally {
73597
73779
  if (out2 !== void 0) try {
73598
- rmSync15(out2, { recursive: true, force: true });
73780
+ rmSync16(out2, { recursive: true, force: true });
73599
73781
  } catch {
73600
73782
  }
73601
73783
  }
@@ -73749,7 +73931,7 @@ async function producedWidgetFamilies(dir) {
73749
73931
  }
73750
73932
  const outDir = tier5Dir.bundleOutDir(dir);
73751
73933
  try {
73752
- readdirSync30(outDir);
73934
+ readdirSync31(outDir);
73753
73935
  } catch {
73754
73936
  return { families: void 0, source: "unbuilt" };
73755
73937
  }
@@ -73760,7 +73942,7 @@ async function producedWidgetFamilies(dir) {
73760
73942
  let js;
73761
73943
  for (const candidate of [`${name}.bundle.js`, `${name}.js`, name]) {
73762
73944
  try {
73763
- js = readFileSync79(join64(outDir, candidate), "utf8");
73945
+ js = readFileSync80(join65(outDir, candidate), "utf8");
73764
73946
  break;
73765
73947
  } catch {
73766
73948
  }
@@ -73791,7 +73973,7 @@ async function producedWidgetFamilies(dir) {
73791
73973
  }
73792
73974
  return { families, source: "dist/bundles" };
73793
73975
  }
73794
- var boardOpen = (dir) => existsSync66(join64(dir, ".himi", "studio", "index.html"));
73976
+ var boardOpen = (dir) => existsSync67(join65(dir, ".himi", "studio", "index.html"));
73795
73977
  var BOARD_REFRESHERS = /* @__PURE__ */ new Set(["render", "test", "validate", "build", "push", "icon", "site", "ux", "progress"]);
73796
73978
  async function leaveForBoard(dir, record2, value) {
73797
73979
  if (!boardOpen(dir)) return;
@@ -73815,7 +73997,7 @@ async function liveMapFor(dir) {
73815
73997
  }
73816
73998
  var commandScratch = new AsyncLocalStorage();
73817
73999
  function commandScratchDir(prefix) {
73818
- const dir = mkdtempSync4(join64(tmpdir5(), prefix));
74000
+ const dir = mkdtempSync4(join65(tmpdir5(), prefix));
73819
74001
  commandScratch.getStore()?.push(dir);
73820
74002
  return dir;
73821
74003
  }
@@ -73826,7 +74008,7 @@ async function run(argv, io = defaultIO, deps = {}) {
73826
74008
  code = await commandScratch.run(scratch, () => runCommand(argv, io, deps));
73827
74009
  } finally {
73828
74010
  for (const dir of scratch) try {
73829
- rmSync15(dir, { recursive: true, force: true });
74011
+ rmSync16(dir, { recursive: true, force: true });
73830
74012
  } catch {
73831
74013
  }
73832
74014
  }
@@ -74094,7 +74276,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
74094
74276
  return 2;
74095
74277
  }
74096
74278
  const template = str8(flags.template);
74097
- const parentDir = resolve52(str8(flags.dir) ?? process.cwd());
74279
+ const parentDir = resolve53(str8(flags.dir) ?? process.cwd());
74098
74280
  const withAgentFiles = async (dir) => {
74099
74281
  const seeded = await seedAgentFilesFor(dir, flags);
74100
74282
  if (!seeded.agent || "error" in seeded.agent) return seeded;
@@ -74107,7 +74289,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
74107
74289
  const owed = openApprovals2(readApprovals2(dir).events).length;
74108
74290
  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`);
74109
74291
  }
74110
- const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f) => existsSync66(join64(parentDir, f)));
74292
+ const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f) => existsSync67(join65(parentDir, f)));
74111
74293
  if (planInParent.length) {
74112
74294
  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}`);
74113
74295
  }
@@ -74255,11 +74437,11 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74255
74437
  return 2;
74256
74438
  }
74257
74439
  }
74258
- const appDir3 = resolve52(str8(flags.dir) ?? process.cwd());
74259
- const sourceDir = resolve52(str8(flags["source-dir"]) ?? appDir3);
74440
+ const appDir3 = resolve53(str8(flags.dir) ?? process.cwd());
74441
+ const sourceDir = resolve53(str8(flags["source-dir"]) ?? appDir3);
74260
74442
  let meta;
74261
74443
  try {
74262
- meta = JSON.parse(readFileSync79(join64(sourceDir, TEMPLATE_META_FILE), "utf8"));
74444
+ meta = JSON.parse(readFileSync80(join65(sourceDir, TEMPLATE_META_FILE), "utf8"));
74263
74445
  } catch {
74264
74446
  io.error(JSON.stringify({ error: `no ${TEMPLATE_META_FILE} in ${sourceDir} \u2014 a template must declare { title, description, tags } to be published`, hint: `add ${TEMPLATE_META_FILE} next to himalaya.content.json (or pass --source-dir <dir>)` }));
74265
74447
  return 2;
@@ -74269,7 +74451,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74269
74451
  return 2;
74270
74452
  }
74271
74453
  try {
74272
- const appearance = extractTemplateAppearance(JSON.parse(readFileSync79(join64(sourceDir, "tokens.json"), "utf8")));
74454
+ const appearance = extractTemplateAppearance(JSON.parse(readFileSync80(join65(sourceDir, "tokens.json"), "utf8")));
74273
74455
  meta = { ...appearance, ...meta };
74274
74456
  } catch {
74275
74457
  }
@@ -74291,14 +74473,14 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74291
74473
  const force = flags.force === true;
74292
74474
  const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
74293
74475
  const bres = await buildContentForValidation2(buildDir, { resolution: resolutionFlag(flags) });
74294
- const out2 = mkdtempSync4(join64(tmpdir5(), "himi-template-"));
74476
+ const out2 = mkdtempSync4(join65(tmpdir5(), "himi-template-"));
74295
74477
  publishScratch.push(out2);
74296
74478
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
74297
74479
  const outcome = await buildReleaseFromContent2(buildDir, out2, {
74298
74480
  ...hasWorkers ? { tier5Dir: bundleOutDir2(buildDir) } : {},
74299
74481
  collect: { lint: true, strict }
74300
74482
  });
74301
- const scaffoldSourceFindings = resolve52(sourceDir) === resolve52(appDir3) ? [] : [
74483
+ const scaffoldSourceFindings = resolve53(sourceDir) === resolve53(appDir3) ? [] : [
74302
74484
  ...tokenColorIssues(sourceDir),
74303
74485
  ...surfaceIssues(sourceDir, void 0, strict),
74304
74486
  ...await fontIssues(sourceDir, strict),
@@ -74341,11 +74523,11 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74341
74523
  }));
74342
74524
  return 1;
74343
74525
  }
74344
- const iconPath = str8(flags.icon) ? resolve52(str8(flags.icon)) : templateIconPath(name);
74526
+ const iconPath = str8(flags.icon) ? resolve53(str8(flags.icon)) : templateIconPath(name);
74345
74527
  let iconHash;
74346
74528
  if (iconPath) {
74347
74529
  try {
74348
- const bytes2 = readFileSync79(iconPath);
74530
+ const bytes2 = readFileSync80(iconPath);
74349
74531
  payload.icon = bytes2.toString("base64");
74350
74532
  iconHash = createHash31("sha256").update(bytes2).digest("hex");
74351
74533
  } catch {
@@ -74518,7 +74700,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74518
74700
  } finally {
74519
74701
  for (const dir of publishScratch) {
74520
74702
  try {
74521
- rmSync15(dir, { recursive: true, force: true });
74703
+ rmSync16(dir, { recursive: true, force: true });
74522
74704
  } catch (e) {
74523
74705
  io.error(JSON.stringify({ warning: `could not remove temp dir ${dir}: ${e.message}` }));
74524
74706
  }
@@ -74552,12 +74734,12 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74552
74734
  print({ ok: false, error: "eject needs a module", hint: `one of: ${EJECTABLE2.join(", ")}` });
74553
74735
  return 2;
74554
74736
  }
74555
- const { readdirSync: readdirSync31, existsSync: fileExists } = await import("node:fs");
74737
+ const { readdirSync: readdirSync32, existsSync: fileExists } = await import("node:fs");
74556
74738
  const { join: pathJoin } = await import("node:path");
74557
74739
  const targets = [];
74558
74740
  const t5 = pathJoin(dir, "tier5-src");
74559
74741
  if (fileExists(t5)) {
74560
- for (const d of readdirSync31(t5, { withFileTypes: true })) {
74742
+ for (const d of readdirSync32(t5, { withFileTypes: true })) {
74561
74743
  if (d.isDirectory()) targets.push(pathJoin(t5, d.name, "index.ts"));
74562
74744
  }
74563
74745
  }
@@ -74632,7 +74814,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74632
74814
  const path2 = dpxSessionTokenPath();
74633
74815
  let raw;
74634
74816
  try {
74635
- raw = readFileSync79(path2, "utf8");
74817
+ raw = readFileSync80(path2, "utf8");
74636
74818
  } catch {
74637
74819
  throw new Error(`no DPX BO session at ${path2}; run dpx auth login, write dpx auth token to that path, then himi login --dpx --target bo`);
74638
74820
  }
@@ -74763,32 +74945,37 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
74763
74945
  return 1;
74764
74946
  }
74765
74947
  const { himiPluginFiles: himiPluginFiles2 } = await Promise.resolve().then(() => (init_claude_plugin(), claude_plugin_exports));
74766
- const dir = resolve52(out2);
74948
+ const dir = resolve53(out2);
74767
74949
  const files = himiPluginFiles2(skills.skillMd);
74768
74950
  for (const f of files) {
74769
- mkdirSync32(dirname36(join64(dir, f.path)), { recursive: true });
74770
- writeFileSync29(join64(dir, f.path), f.text);
74951
+ mkdirSync33(dirname37(join65(dir, f.path)), { recursive: true });
74952
+ writeFileSync30(join65(dir, f.path), f.text);
74771
74953
  }
74772
74954
  print({ ok: true, dir, files: files.map((f) => f.path), next: [`claude plugin validate ${dir}`, `claude --plugin-dir ${dir}`] });
74773
74955
  return 0;
74774
74956
  }
74775
74957
  const { startMcpServer: startMcpServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
74776
- await startMcpServer2({ run, version: cliVersion() });
74958
+ await startMcpServer2({
74959
+ run,
74960
+ version: cliVersion(),
74961
+ withFiles: flags["with-files"] === true,
74962
+ ...process.env.HIMI_WORKSPACE ? { workspace: resolve53(process.env.HIMI_WORKSPACE) } : {}
74963
+ });
74777
74964
  return 0;
74778
74965
  }
74779
74966
  case "studio": {
74780
74967
  const { openStudio: openStudio2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
74781
74968
  const dir = contentDir(flags);
74782
- if (!existsSync66(join64(dir, "himalaya.content.json"))) {
74969
+ if (!existsSync67(join65(dir, "himalaya.content.json"))) {
74783
74970
  io.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/" }));
74784
74971
  return 2;
74785
74972
  }
74786
74973
  if (pos[1] === "reel") {
74787
74974
  const { buildReel: buildReel2 } = await Promise.resolve().then(() => (init_studio_reel(), studio_reel_exports));
74788
- const out2 = resolve52(str8(flags.out) ?? join64(dir, ".himi", "making-of.html"));
74975
+ const out2 = resolve53(str8(flags.out) ?? join65(dir, ".himi", "making-of.html"));
74789
74976
  const { html, plan } = buildReel2(dir);
74790
- mkdirSync32(dirname36(out2), { recursive: true });
74791
- writeFileSync29(out2, html);
74977
+ mkdirSync33(dirname37(out2), { recursive: true });
74978
+ writeFileSync30(out2, html);
74792
74979
  const { pathToFileURL: pathToFileURL9 } = await import("node:url");
74793
74980
  const url2 = pathToFileURL9(out2).href;
74794
74981
  const open2 = flags["no-open"] !== true;
@@ -74857,7 +75044,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
74857
75044
  } = await Promise.resolve().then(() => (init_progress(), progress_exports));
74858
75045
  const dir = contentDir(flags);
74859
75046
  const journal2 = journalPath2(dir);
74860
- const isContentPackage = existsSync66(join64(dir, "himalaya.content.json"));
75047
+ const isContentPackage = existsSync67(join65(dir, "himalaya.content.json"));
74861
75048
  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" };
74862
75049
  const message = pos.slice(1).join(" ").trim();
74863
75050
  const approvalFlags = ["approve", "done", "drop"].filter((f) => flags[f] !== void 0);
@@ -75006,7 +75193,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
75006
75193
  case "test": {
75007
75194
  const dir = contentDir(flags);
75008
75195
  const structuredOutput = flags.json === true || io.isTTY !== true;
75009
- if (existsSync66(join64(dir, "functions"))) {
75196
+ if (existsSync67(join65(dir, "functions"))) {
75010
75197
  const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
75011
75198
  const loaded = await loadFunctionsApp2(dir);
75012
75199
  const results = [];
@@ -75138,7 +75325,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
75138
75325
  io.error(JSON.stringify({ error: `screen "${screen.screenId}" has no Tier-5 worker, so there is nothing for the browser loop to build` }));
75139
75326
  return 2;
75140
75327
  }
75141
- const sources = collectWorkerSources2(join64(dir, "tier5-src"), screen.bundleName);
75328
+ const sources = collectWorkerSources2(join65(dir, "tier5-src"), screen.bundleName);
75142
75329
  if (!sources) {
75143
75330
  io.error(JSON.stringify({ error: `no worker source found at tier5-src/${screen.bundleName} \u2014 the browser loop compiles SOURCE, not the built bundle` }));
75144
75331
  return 2;
@@ -75315,7 +75502,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
75315
75502
  const sp = await runShotsPass2({
75316
75503
  descriptors: scopeDescriptors2(outcome.descriptors ?? [], pos.slice(1), invalidScreens),
75317
75504
  tokens: outcome.tokens,
75318
- outDir: join64(dir, ".himi", "shots"),
75505
+ outDir: join65(dir, ".himi", "shots"),
75319
75506
  width: 390,
75320
75507
  layers: { rules: shotRules, ...cmsSeed ? { cmsSeed } : {}, ...canned ? { canned: canned.byKey } : {} },
75321
75508
  ...budgetMs ? { budgetMs } : {},
@@ -75325,7 +75512,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
75325
75512
  renderDescriptorWeb: renderDescriptorWeb2,
75326
75513
  renderPngBatch: renderPngBatch2,
75327
75514
  writePng: (path2, base64) => writePngFile(path2, base64),
75328
- clearDir: (d) => rmSync15(d, { recursive: true, force: true })
75515
+ clearDir: (d) => rmSync16(d, { recursive: true, force: true })
75329
75516
  }
75330
75517
  });
75331
75518
  writtenShots = sp.written;
@@ -75353,7 +75540,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
75353
75540
  releaseId: result.releaseId,
75354
75541
  releasePayload: release,
75355
75542
  descriptors: attestedDescriptors,
75356
- screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join64(dir, ".himi", "shots", name)])),
75543
+ screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join65(dir, ".himi", "shots", name)])),
75357
75544
  coverage: {
75358
75545
  screens: crawledScreens.size,
75359
75546
  actionsDispatched: result.actions.exercised,
@@ -75464,7 +75651,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
75464
75651
  return 2;
75465
75652
  }
75466
75653
  try {
75467
- const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync79(stateArg.replace(/^@/, ""), "utf8");
75654
+ const raw = stateArg.trim().startsWith("{") ? stateArg : readFileSync80(stateArg.replace(/^@/, ""), "utf8");
75468
75655
  injectedState = JSON.parse(raw);
75469
75656
  } catch (e) {
75470
75657
  io.error(JSON.stringify({ error: `--state must be inline JSON or a path to a .json file \u2014 ${e.message}` }));
@@ -75479,7 +75666,7 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
75479
75666
  return 2;
75480
75667
  }
75481
75668
  try {
75482
- const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync79(inputArg.replace(/^@/, ""), "utf8");
75669
+ const raw = inputArg.trim().startsWith("{") ? inputArg : readFileSync80(inputArg.replace(/^@/, ""), "utf8");
75483
75670
  const parsed = JSON.parse(raw);
75484
75671
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("must be a JSON object");
75485
75672
  injectedInput = parsed;
@@ -75542,11 +75729,11 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
75542
75729
  const diagnostics = (outcome.lint ?? []).find((s) => s.screenId === screenId)?.issues ?? [];
75543
75730
  let pngFile;
75544
75731
  let attestationPngFile;
75545
- const shotPath = join64(dir, ".himi", "shots", `${screenId}.png`);
75732
+ const shotPath = join65(dir, ".himi", "shots", `${screenId}.png`);
75546
75733
  const pngTarget = typeof flags.png === "string" ? str8(flags.png) : flags.png === true ? shotPath : void 0;
75547
75734
  if (pngTarget && r.pngBase64) {
75548
75735
  pngFile = writePngFile(pngTarget, r.pngBase64);
75549
- attestationPngFile = resolve52(pngTarget) === resolve52(shotPath) ? pngFile : writePngFile(shotPath, r.pngBase64);
75736
+ attestationPngFile = resolve53(pngTarget) === resolve53(shotPath) ? pngFile : writePngFile(shotPath, r.pngBase64);
75550
75737
  }
75551
75738
  if (renderWidth !== void 0 && r.renderable) {
75552
75739
  recordRenderWidth(dir, {
@@ -75882,7 +76069,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
75882
76069
  return 2;
75883
76070
  }
75884
76071
  const renamed = str8(flags.name);
75885
- const dest = resolve52(str8(flags.out) ?? process.cwd(), renamed ?? wanted);
76072
+ const dest = resolve53(str8(flags.out) ?? process.cwd(), renamed ?? wanted);
75886
76073
  const replace = flags.replace === true;
75887
76074
  const force = replace || flags.force === true;
75888
76075
  const linked = symlinkDestinationIssue(dest);
@@ -75890,20 +76077,20 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
75890
76077
  io.error(JSON.stringify(linked));
75891
76078
  return 1;
75892
76079
  }
75893
- if (existsSync66(dest)) {
75894
- if (!statSync18(dest).isDirectory()) {
76080
+ if (existsSync67(dest)) {
76081
+ if (!statSync19(dest).isDirectory()) {
75895
76082
  io.error(JSON.stringify({
75896
76083
  error: `${dest} exists and is not a directory`,
75897
76084
  hint: "pass --out/--name to land somewhere else, or remove the file"
75898
76085
  }));
75899
76086
  return 1;
75900
76087
  }
75901
- const occupied = readdirSync30(dest).length > 0;
76088
+ const occupied = readdirSync31(dest).length > 0;
75902
76089
  if (occupied && !force) {
75903
76090
  io.error(JSON.stringify({ error: `${dest} already exists and is not empty`, hint: "pass --force to write into it anyway (merging, and naming what it keeps), --replace to restore exactly what was archived, or --out/--name to land somewhere else" }));
75904
76091
  return 1;
75905
76092
  }
75906
- if (replace && occupied && !existsSync66(join64(dest, "himalaya.content.json"))) {
76093
+ if (replace && occupied && !existsSync67(join65(dest, "himalaya.content.json"))) {
75907
76094
  io.error(JSON.stringify({
75908
76095
  error: `${dest} is not a content package \u2014 refusing to --replace it`,
75909
76096
  hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
@@ -76070,7 +76257,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76070
76257
  const manifest = outcome.manifest;
76071
76258
  const payload = await loadReleaseFromDir(declared, out2);
76072
76259
  const { shellQuote: shellQuote3 } = await Promise.resolve().then(() => (init_shell_quote(), shell_quote_exports));
76073
- const contentRel = relative13(process.cwd(), dir) || ".";
76260
+ const contentRel = relative14(process.cwd(), dir) || ".";
76074
76261
  const contentArg2 = shellQuote3(contentRel);
76075
76262
  if (onlyRaw !== void 0) {
76076
76263
  const onlyDraft = flags.draft === true;
@@ -76541,7 +76728,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76541
76728
  return 2;
76542
76729
  }
76543
76730
  try {
76544
- const res = writePack(resolve52(releaseDir), only, resolve52(str8(flags.out) ?? process.cwd()));
76731
+ const res = writePack(resolve53(releaseDir), only, resolve53(str8(flags.out) ?? process.cwd()));
76545
76732
  print({
76546
76733
  ok: true,
76547
76734
  app: res.app,
@@ -76590,7 +76777,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76590
76777
  }
76591
76778
  const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
76592
76779
  const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
76593
- const built = mkdtempSync4(join64(tmpdir5(), "himi-pack-"));
76780
+ const built = mkdtempSync4(join65(tmpdir5(), "himi-pack-"));
76594
76781
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
76595
76782
  const outcome = await buildReleaseFromContent2(dir, built, {
76596
76783
  ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
@@ -76607,12 +76794,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76607
76794
  ...await navIssues2(dir, strict)
76608
76795
  ]);
76609
76796
  if (hasErrors && !force) {
76610
- rmSync15(built, { recursive: true, force: true });
76797
+ rmSync16(built, { recursive: true, force: true });
76611
76798
  print({ ...report3, packed: false, hint: "lint found errors \u2014 fix them, or re-run `himi pack --force` to pack anyway" });
76612
76799
  return 1;
76613
76800
  }
76614
76801
  try {
76615
- const res = writePack(built, app, resolve52(str8(flags.out) ?? dir), sourceArchive);
76802
+ const res = writePack(built, app, resolve53(str8(flags.out) ?? dir), sourceArchive);
76616
76803
  print({
76617
76804
  ok: true,
76618
76805
  app: res.app,
@@ -76643,7 +76830,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76643
76830
  io.error(JSON.stringify({ error: e.message }));
76644
76831
  return 1;
76645
76832
  } finally {
76646
- rmSync15(built, { recursive: true, force: true });
76833
+ rmSync16(built, { recursive: true, force: true });
76647
76834
  }
76648
76835
  }
76649
76836
  // ---- himi import — turn a dev .himi back into an editable content package ----
@@ -76657,7 +76844,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76657
76844
  const { HIMI_PACKAGE_SOURCE_PATH: HIMI_PACKAGE_SOURCE_PATH2, isSafeAppId: isSafeAppId2, packageContents: packageContents2 } = await Promise.resolve().then(() => (init_himi_package(), himi_package_exports));
76658
76845
  let opened;
76659
76846
  try {
76660
- opened = openPackageFile2(resolve52(file));
76847
+ opened = openPackageFile2(resolve53(file));
76661
76848
  } catch (e) {
76662
76849
  io.error(JSON.stringify({ error: e.message }));
76663
76850
  return 1;
@@ -76670,7 +76857,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76670
76857
  io.error(JSON.stringify({
76671
76858
  ok: false,
76672
76859
  error: "app_source_not_in_package",
76673
- detail: `${resolve52(file)} is a release package: it carries built output (screens, bundles, tokens) and no source`,
76860
+ detail: `${resolve53(file)} is a release package: it carries built output (screens, bundles, tokens) and no source`,
76674
76861
  hint: "re-pack it from the content package with `himi pack --dev`, or restore from the serve plane with `himi pull <app>`"
76675
76862
  }));
76676
76863
  return 1;
@@ -76693,7 +76880,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76693
76880
  return 1;
76694
76881
  }
76695
76882
  }
76696
- const dest = resolve52(str8(flags.out) ?? process.cwd(), renamed ?? opened.header.app);
76883
+ const dest = resolve53(str8(flags.out) ?? process.cwd(), renamed ?? opened.header.app);
76697
76884
  const issue2 = restoreDestinationIssue(dest, flags.force === true);
76698
76885
  if (issue2) {
76699
76886
  io.error(JSON.stringify(issue2));
@@ -76780,7 +76967,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76780
76967
  }
76781
76968
  try {
76782
76969
  const { openPackageFile: openPackageFile2 } = await Promise.resolve().then(() => (init_pack(), pack_exports));
76783
- const opened = openPackageFile2(resolve52(file));
76970
+ const opened = openPackageFile2(resolve53(file));
76784
76971
  if (!opened.validation.ok || !opened.header) {
76785
76972
  io.error(JSON.stringify({ error: "refusing to share an invalid package", issues: opened.validation.errors }));
76786
76973
  return 1;
@@ -76790,12 +76977,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76790
76977
  io.error(JSON.stringify({
76791
76978
  ok: false,
76792
76979
  error: "refusing to share a package that carries the app's source",
76793
- detail: `${resolve52(file)} was packed with --dev, and a share link is public and unauthenticated \u2014 anyone with the URL could \`himi import\` your codebase`,
76980
+ detail: `${resolve53(file)} was packed with --dev, and a share link is public and unauthenticated \u2014 anyone with the URL could \`himi import\` your codebase`,
76794
76981
  hint: "share a release package instead (`himi pack` with no --dev), or hand the dev package over directly"
76795
76982
  }));
76796
76983
  return 1;
76797
76984
  }
76798
- const archive = readFileSync79(resolve52(file));
76985
+ const archive = readFileSync80(resolve53(file));
76799
76986
  const result = await client2().createPackageShare({
76800
76987
  app: opened.header.app,
76801
76988
  releaseId: opened.header.releaseId,
@@ -76871,11 +77058,11 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76871
77058
  const app = await appId(dir2);
76872
77059
  const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
76873
77060
  const bres = await buildContentBundles2(dir2, { resolution: resolutionFlag(flags) });
76874
- temp = mkdtempSync4(join64(tmpdir5(), "himi-run-build-"));
77061
+ temp = mkdtempSync4(join65(tmpdir5(), "himi-run-build-"));
76875
77062
  const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
76876
77063
  const initial = await buildReleaseFromContent2(dir2, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir2) } : {} });
76877
77064
  servedMissing = initial.missingBundles;
76878
- source = join64(temp, app);
77065
+ source = join65(temp, app);
76879
77066
  }
76880
77067
  const chromeArg = str8(flags.chrome) ?? "preview";
76881
77068
  if (chromeArg !== "preview" && chromeArg !== "app") {
@@ -76911,7 +77098,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76911
77098
  if (!recordKit) return;
76912
77099
  startedAt = (/* @__PURE__ */ new Date()).toISOString();
76913
77100
  const failure = record2(served2, { ok: true, at: startedAt });
76914
- if (!recorded) io.error(JSON.stringify({ run: "run_record_skipped", message: `${failure ?? `${join64(dir, ".himi")} is not a real directory`}, so the build board will not frame this preview.` }));
77101
+ if (!recorded) io.error(JSON.stringify({ run: "run_record_skipped", message: `${failure ?? `${join65(dir, ".himi")} is not a real directory`}, so the build board will not frame this preview.` }));
76915
77102
  await refreshBoard();
76916
77103
  };
76917
77104
  const retract = async () => {
@@ -76934,9 +77121,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76934
77121
  });
76935
77122
  await announce(run2);
76936
77123
  print({ ok: true, app: run2.app, url: run2.url, port: run2.port, plane: "browser" });
76937
- await new Promise((resolve53) => {
77124
+ await new Promise((resolve54) => {
76938
77125
  const stop = () => {
76939
- void retract().catch((e) => io.error(JSON.stringify({ run: "stop_cleanup_failed", message: e.message }))).finally(() => run2.close().finally(() => resolve53()));
77126
+ void retract().catch((e) => io.error(JSON.stringify({ run: "stop_cleanup_failed", message: e.message }))).finally(() => run2.close().finally(() => resolve54()));
76940
77127
  };
76941
77128
  process.once("SIGINT", stop);
76942
77129
  process.once("SIGTERM", stop);
@@ -76945,7 +77132,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76945
77132
  }
76946
77133
  const watchKit = watch2 ? await Promise.resolve().then(() => (init_run_watch(), run_watch_exports)) : null;
76947
77134
  const bus = watchKit ? new watchKit.ReloadBus() : void 0;
76948
- if (watch2) served = mkdtempSync4(join64(tmpdir5(), "himi-run-served-"));
77135
+ if (watch2) served = mkdtempSync4(join65(tmpdir5(), "himi-run-served-"));
76949
77136
  const running = await runPackage2(source, {
76950
77137
  port,
76951
77138
  chrome: chromeArg,
@@ -76974,8 +77161,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76974
77161
  await announce(running);
76975
77162
  if (watchKit && bus) {
76976
77163
  const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
76977
- const live2 = join64(running.releaseRoot, running.app);
76978
- const manifestOf = (tree) => JSON.parse(readFileSync79(join64(tree, "release-manifest.json"), "utf8"));
77164
+ const live2 = join65(running.releaseRoot, running.app);
77165
+ const manifestOf = (tree) => JSON.parse(readFileSync80(join65(tree, "release-manifest.json"), "utf8"));
76979
77166
  let current = manifestOf(live2);
76980
77167
  const failed2 = async (message) => {
76981
77168
  if (stopping) return;
@@ -76986,7 +77173,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
76986
77173
  };
76987
77174
  rebuild = watchKit.serialize(async () => {
76988
77175
  const t0 = Date.now();
76989
- const next = mkdtempSync4(join64(tmpdir5(), "himi-run-build-"));
77176
+ const next = mkdtempSync4(join65(tmpdir5(), "himi-run-build-"));
76990
77177
  try {
76991
77178
  const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
76992
77179
  if (bres.compileErrors.length) {
@@ -77003,18 +77190,18 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77003
77190
  return;
77004
77191
  }
77005
77192
  if (stopping) return;
77006
- const fresh = manifestOf(join64(next, running.app));
77193
+ const fresh = manifestOf(join65(next, running.app));
77007
77194
  const diff = watchKit.diffReleases(current, fresh);
77008
77195
  const { describeChanges: describeChanges2, headline: headline2 } = await Promise.resolve().then(() => (init_build_changes(), build_changes_exports));
77009
- const changes = describeChanges2(live2, join64(next, running.app), diff);
77196
+ const changes = describeChanges2(live2, join65(next, running.app), diff);
77010
77197
  const retired = `${live2}.retired-${Date.now()}`;
77011
77198
  renameSync7(live2, retired);
77012
77199
  try {
77013
- renameSync7(join64(next, running.app), live2);
77200
+ renameSync7(join65(next, running.app), live2);
77014
77201
  } catch {
77015
- cpSync3(join64(next, running.app), live2, { recursive: true });
77202
+ cpSync3(join65(next, running.app), live2, { recursive: true });
77016
77203
  }
77017
- rmSync15(retired, { recursive: true, force: true });
77204
+ rmSync16(retired, { recursive: true, force: true });
77018
77205
  current = fresh;
77019
77206
  servedMissing = outcome.missingBundles;
77020
77207
  for (const [event, data] of watchKit.reloadEvents(diff)) bus.publish(event, data);
@@ -77024,7 +77211,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77024
77211
  } catch (e) {
77025
77212
  await failed2(e.message.split("\n")[0]);
77026
77213
  } finally {
77027
- rmSync15(next, { recursive: true, force: true });
77214
+ rmSync16(next, { recursive: true, force: true });
77028
77215
  }
77029
77216
  });
77030
77217
  watcher2 = watchKit.watchContent(dir, () => {
@@ -77092,9 +77279,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77092
77279
  io.error(JSON.stringify({ error: e.message }));
77093
77280
  return 1;
77094
77281
  } finally {
77095
- if (temp) rmSync15(temp, { recursive: true, force: true });
77096
- if (served) rmSync15(served, { recursive: true, force: true });
77097
- if (browserCopy) rmSync15(browserCopy, { recursive: true, force: true });
77282
+ if (temp) rmSync16(temp, { recursive: true, force: true });
77283
+ if (served) rmSync16(served, { recursive: true, force: true });
77284
+ if (browserCopy) rmSync16(browserCopy, { recursive: true, force: true });
77098
77285
  }
77099
77286
  }
77100
77287
  case "preview": {
@@ -77636,7 +77823,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77636
77823
  io.error(JSON.stringify({ error: `patch ${kind} needs --file`, usage: PATCH_USAGE }));
77637
77824
  return 2;
77638
77825
  }
77639
- if (!existsSync66(file)) {
77826
+ if (!existsSync67(file)) {
77640
77827
  io.error(JSON.stringify({ error: `no such file: ${file}` }));
77641
77828
  return 2;
77642
77829
  }
@@ -77692,7 +77879,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77692
77879
  lintNote: "`himi patch` sends a raw file. Nothing here built or linted your app \u2014 `himi push --only <selector>` is the same edit with the full lint gate in front of it."
77693
77880
  };
77694
77881
  if (kind === "tokens" || kind === "app-config") {
77695
- const body = readFileSync79(file, "utf8");
77882
+ const body = readFileSync80(file, "utf8");
77696
77883
  const patch2 = kind === "tokens" ? { tokens: body } : { appConfig: body };
77697
77884
  return runReleasePatch({
77698
77885
  ...common,
@@ -77707,7 +77894,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77707
77894
  io.error(JSON.stringify({ error: "patch screen needs a <screenId>", usage: PATCH_USAGE }));
77708
77895
  return 2;
77709
77896
  }
77710
- const descriptor = readFileSync79(file, "utf8");
77897
+ const descriptor = readFileSync80(file, "utf8");
77711
77898
  try {
77712
77899
  JSON.parse(descriptor);
77713
77900
  } catch (e) {
@@ -77747,7 +77934,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77747
77934
  extra: { kind, screen: id, file: { path: file, bytes: Buffer.byteLength(descriptor, "utf8") } }
77748
77935
  });
77749
77936
  }
77750
- const bytes2 = readFileSync79(file);
77937
+ const bytes2 = readFileSync80(file);
77751
77938
  const sha = createHash31("sha256").update(bytes2).digest("hex");
77752
77939
  const forScreens = (str8(flags["for-screen"]) ?? "").split(",").map((s) => s.trim()).filter(Boolean);
77753
77940
  if (flags["no-rebind"] !== void 0 && flags["no-rebind"] !== true) {
@@ -77891,7 +78078,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
77891
78078
  }
77892
78079
  let def;
77893
78080
  try {
77894
- const parsed = JSON.parse(arg.startsWith("@") ? readFileSync79(arg.slice(1), "utf8") : arg);
78081
+ const parsed = JSON.parse(arg.startsWith("@") ? readFileSync80(arg.slice(1), "utf8") : arg);
77895
78082
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
77896
78083
  io.error(JSON.stringify({ error: "invalid_definition", problems: [`--definition must be a JSON object, got ${Array.isArray(parsed) ? "an array" : parsed === null ? "null" : typeof parsed}`] }));
77897
78084
  return 2;
@@ -78355,7 +78542,7 @@ ${label2}`);
78355
78542
  const platform = str8(flags.platform)?.split(",").map((p) => p.trim()).filter(Boolean);
78356
78543
  {
78357
78544
  const distDir = contentDir(flags);
78358
- if (existsSync66(join64(distDir, "himalaya.content.json"))) {
78545
+ if (existsSync67(join65(distDir, "himalaya.content.json"))) {
78359
78546
  const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
78360
78547
  const errors = issues.filter((i) => i.severity === "error");
78361
78548
  for (const i of issues.filter((i2) => i2.severity === "warning")) {
@@ -78641,7 +78828,7 @@ ${label2}`);
78641
78828
  const dpxPath = dpxSessionTokenPath();
78642
78829
  let dpx;
78643
78830
  try {
78644
- dpx = readFileSync79(dpxPath, "utf8").trim();
78831
+ dpx = readFileSync80(dpxPath, "utf8").trim();
78645
78832
  } catch {
78646
78833
  io.error(JSON.stringify({ error: `no dpx session at ${dpxPath} \u2014 run \`dpx auth login\` then \`dpx auth token > ${dpxPath}\` (dpx 2.x keeps its own state in ~/.dpx/auth.json and does NOT write the legacy session file), or omit --dpx` }));
78647
78834
  return 1;
@@ -79049,7 +79236,7 @@ ${report3.ok ? "OK \u2014 data + serve plane reachable." : typeof report3.hint =
79049
79236
  const path2 = dpxSessionTokenPath();
79050
79237
  let raw;
79051
79238
  try {
79052
- raw = readFileSync79(path2, "utf8");
79239
+ raw = readFileSync80(path2, "utf8");
79053
79240
  } catch {
79054
79241
  io.error(JSON.stringify({ error: `no DPX BO session at ${path2}` }));
79055
79242
  return 1;