@wix/himalaya-cli 0.842.0 → 0.844.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/stores-v1/src/index.d.ts +1 -0
  2. package/dist/cli.mjs +100 -73
  3. package/guides/sdk-reference.json +1 -1
  4. package/package.json +2 -2
  5. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-aria/index.ts +1 -1
  6. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-aria-history/index.ts +1 -1
  7. package/templates/community-club-owner/tier5-src/himi-owner-lite-aria/index.ts +1 -1
  8. package/templates/community-club-owner/tier5-src/himi-owner-lite-aria-history/index.ts +1 -1
  9. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-aria/index.ts +1 -1
  10. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-aria-history/index.ts +1 -1
  11. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-aria/index.ts +1 -1
  12. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-aria-history/index.ts +1 -1
  13. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-aria/index.ts +1 -1
  14. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-aria-history/index.ts +1 -1
  15. package/templates/owner-lite/tier5-src/himi-owner-lite-aria/index.ts +1 -1
  16. package/templates/owner-lite/tier5-src/himi-owner-lite-aria-history/index.ts +1 -1
  17. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-aria/index.ts +1 -1
  18. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-aria-history/index.ts +1 -1
  19. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-aria/index.ts +1 -1
  20. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-aria-history/index.ts +1 -1
  21. package/templates/restaurant-owner/tier5-src/himi-owner-lite-aria/index.ts +1 -1
  22. package/templates/restaurant-owner/tier5-src/himi-owner-lite-aria-history/index.ts +1 -1
  23. package/templates/retail-store-owner/tier5-src/himi-owner-lite-aria/index.ts +1 -1
  24. package/templates/retail-store-owner/tier5-src/himi-owner-lite-aria-history/index.ts +1 -1
  25. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-aria/index.ts +1 -1
  26. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-aria-history/index.ts +1 -1
@@ -41,6 +41,7 @@ export interface WixProductStock {
41
41
  }
42
42
  export interface WixProductMedia {
43
43
  mainMedia?: Record<string, unknown>;
44
+ items?: unknown[];
44
45
  }
45
46
  export interface WixProduct {
46
47
  id: string;
package/dist/cli.mjs CHANGED
@@ -18609,6 +18609,81 @@ var init_token_colors = __esm({
18609
18609
  }
18610
18610
  });
18611
18611
 
18612
+ // src/token-lint.ts
18613
+ import { existsSync as existsSync13, readFileSync as readFileSync16 } from "node:fs";
18614
+ import { join as join17 } from "node:path";
18615
+ function configuredTokensPath(dir) {
18616
+ for (const name of ["config.ts", "config.js", "himi.config.ts"]) {
18617
+ const f = join17(dir, name);
18618
+ if (!existsSync13(f)) continue;
18619
+ const src = readFileSync16(f, "utf8");
18620
+ const m = /designTokensPath\s*:\s*["'`]([^"'`]+)["'`]/.exec(src);
18621
+ if (m) return { path: m[1].replace(/^\.\//, "") };
18622
+ if (/designTokensPath\s*:/.test(src)) return { computed: true };
18623
+ }
18624
+ return {};
18625
+ }
18626
+ function tokenColorIssues(dir, tokensPathOverride) {
18627
+ const issues = [];
18628
+ const error = (message) => issues.push({ screen: null, pass: "tokens", severity: "error", message });
18629
+ const warn = (message) => issues.push({ screen: null, pass: "tokens", severity: "warning", message });
18630
+ const configured = tokensPathOverride ? { path: tokensPathOverride } : configuredTokensPath(dir);
18631
+ if (configured.computed) {
18632
+ warn(
18633
+ "config designTokensPath is a computed expression, so this pass cannot tell which file holds the palette -- only tokens.json was checked"
18634
+ );
18635
+ }
18636
+ const tokensPath = configured.path ?? "tokens.json";
18637
+ const p = join17(dir, tokensPath);
18638
+ if (!existsSync13(p)) {
18639
+ if (tokensPath !== "tokens.json") {
18640
+ warn(`config designTokensPath points at ${tokensPath}, which does not exist -- colour tokens were not checked`);
18641
+ }
18642
+ return issues;
18643
+ }
18644
+ let raw;
18645
+ try {
18646
+ raw = JSON.parse(readFileSync16(p, "utf8"));
18647
+ } catch (e) {
18648
+ error(`${tokensPath}: unparsable JSON \u2014 ${e.message}`);
18649
+ return issues;
18650
+ }
18651
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
18652
+ error(`${tokensPath}: must be an object`);
18653
+ return issues;
18654
+ }
18655
+ const shadows = raw.shadows;
18656
+ if (shadows !== null && typeof shadows === "object" && !Array.isArray(shadows)) {
18657
+ for (const [name, token] of Object.entries(shadows)) {
18658
+ const value = token?.color;
18659
+ if (value === void 0) continue;
18660
+ if (typeof value === "string" && isCanonicalHex(value)) continue;
18661
+ const suggestion = typeof value === "string" ? canonicalHex(value) : void 0;
18662
+ const shown2 = typeof value === "string" ? value : JSON.stringify(value) ?? String(value);
18663
+ error(
18664
+ `${tokensPath}: shadows.${name}.color is ${shown2} \u2014 the native runtimes parse only #RRGGBB or #RRGGBBAA` + (suggestion ? `. Write ${suggestion}.` : `, and this value names no colour that can be converted for you. Write the hex it should be.`)
18665
+ );
18666
+ }
18667
+ }
18668
+ const colors = raw.colors;
18669
+ if (colors === void 0) return issues;
18670
+ if (colors === null || typeof colors !== "object" || Array.isArray(colors)) {
18671
+ error(`${tokensPath}: "colors" must be an object of { "<token>": "#RRGGBB" | { "<variant>": "#RRGGBB" } }`);
18672
+ return issues;
18673
+ }
18674
+ for (const problem of tokenColorProblems(colors)) {
18675
+ error(
18676
+ `${tokensPath}: colors.${problem.path} is ${problem.value} \u2014 the native runtimes parse only #RRGGBB or #RRGGBBAA` + (problem.suggestion ? `. Write ${problem.suggestion}.` : `, and this value names no colour that can be converted for you. Write the hex it should be.`)
18677
+ );
18678
+ }
18679
+ return issues;
18680
+ }
18681
+ var init_token_lint = __esm({
18682
+ "src/token-lint.ts"() {
18683
+ init_token_colors();
18684
+ }
18685
+ });
18686
+
18612
18687
  // ../app-icons/glyphs.ts
18613
18688
  function shade(hex2, f) {
18614
18689
  const n = parseInt(hex2.slice(1), 16);
@@ -20014,7 +20089,7 @@ function listReport(opts = {}) {
20014
20089
  return { ok: true, count: families.length, totalBytes, families };
20015
20090
  }
20016
20091
  function fontFindings(appDir2) {
20017
- const tokensPath = join23(appDir2, "tokens.json");
20092
+ const tokensPath = join23(appDir2, configuredTokensPath(appDir2).path ?? "tokens.json");
20018
20093
  if (!existsSync19(tokensPath)) return null;
20019
20094
  const catalog = loadCatalog();
20020
20095
  const tokens = readJson(tokensPath, {});
@@ -20049,7 +20124,8 @@ function fontFindings(appDir2) {
20049
20124
  function checkReport(appDir2) {
20050
20125
  const result = fontFindings(appDir2);
20051
20126
  if (!result) {
20052
- return { ok: false, count: 0, totalBytes: 0, problems: [`${appDir2}: no tokens.json`], hint: "run inside an app directory" };
20127
+ const looked = configuredTokensPath(appDir2).path ?? "tokens.json";
20128
+ return { ok: false, count: 0, totalBytes: 0, problems: [`${appDir2}: no ${looked}`], hint: "run inside an app directory" };
20053
20129
  }
20054
20130
  const { plan, findings } = result;
20055
20131
  const catalog = loadCatalog();
@@ -20113,6 +20189,7 @@ var init_fonts = __esm({
20113
20189
  init_catalog();
20114
20190
  init_plan_fonts();
20115
20191
  init_face_source();
20192
+ init_token_lint();
20116
20193
  DEFAULT_ASSET_BUDGET_BYTES = 32 * 1024 * 1024;
20117
20194
  }
20118
20195
  });
@@ -59816,76 +59893,8 @@ function readLocalPlatforms(dir) {
59816
59893
  }
59817
59894
  }
59818
59895
 
59819
- // src/token-lint.ts
59820
- init_token_colors();
59821
- import { existsSync as existsSync13, readFileSync as readFileSync16 } from "node:fs";
59822
- import { join as join17 } from "node:path";
59823
- function configuredTokensPath(dir) {
59824
- for (const name of ["config.ts", "config.js", "himi.config.ts"]) {
59825
- const f = join17(dir, name);
59826
- if (!existsSync13(f)) continue;
59827
- const src = readFileSync16(f, "utf8");
59828
- const m = /designTokensPath\s*:\s*["'`]([^"'`]+)["'`]/.exec(src);
59829
- if (m) return { path: m[1].replace(/^\.\//, "") };
59830
- if (/designTokensPath\s*:/.test(src)) return { computed: true };
59831
- }
59832
- return {};
59833
- }
59834
- function tokenColorIssues(dir, tokensPathOverride) {
59835
- const issues = [];
59836
- const error = (message) => issues.push({ screen: null, pass: "tokens", severity: "error", message });
59837
- const warn = (message) => issues.push({ screen: null, pass: "tokens", severity: "warning", message });
59838
- const configured = tokensPathOverride ? { path: tokensPathOverride } : configuredTokensPath(dir);
59839
- if (configured.computed) {
59840
- warn(
59841
- "config designTokensPath is a computed expression, so this pass cannot tell which file holds the palette -- only tokens.json was checked"
59842
- );
59843
- }
59844
- const tokensPath = configured.path ?? "tokens.json";
59845
- const p = join17(dir, tokensPath);
59846
- if (!existsSync13(p)) {
59847
- if (tokensPath !== "tokens.json") {
59848
- warn(`config designTokensPath points at ${tokensPath}, which does not exist -- colour tokens were not checked`);
59849
- }
59850
- return issues;
59851
- }
59852
- let raw;
59853
- try {
59854
- raw = JSON.parse(readFileSync16(p, "utf8"));
59855
- } catch (e) {
59856
- error(`${tokensPath}: unparsable JSON \u2014 ${e.message}`);
59857
- return issues;
59858
- }
59859
- if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
59860
- error(`${tokensPath}: must be an object`);
59861
- return issues;
59862
- }
59863
- const shadows = raw.shadows;
59864
- if (shadows !== null && typeof shadows === "object" && !Array.isArray(shadows)) {
59865
- for (const [name, token] of Object.entries(shadows)) {
59866
- const value = token?.color;
59867
- if (value === void 0) continue;
59868
- if (typeof value === "string" && isCanonicalHex(value)) continue;
59869
- const suggestion = typeof value === "string" ? canonicalHex(value) : void 0;
59870
- const shown2 = typeof value === "string" ? value : JSON.stringify(value) ?? String(value);
59871
- error(
59872
- `${tokensPath}: shadows.${name}.color is ${shown2} \u2014 the native runtimes parse only #RRGGBB or #RRGGBBAA` + (suggestion ? `. Write ${suggestion}.` : `, and this value names no colour that can be converted for you. Write the hex it should be.`)
59873
- );
59874
- }
59875
- }
59876
- const colors = raw.colors;
59877
- if (colors === void 0) return issues;
59878
- if (colors === null || typeof colors !== "object" || Array.isArray(colors)) {
59879
- error(`${tokensPath}: "colors" must be an object of { "<token>": "#RRGGBB" | { "<variant>": "#RRGGBB" } }`);
59880
- return issues;
59881
- }
59882
- for (const problem of tokenColorProblems(colors)) {
59883
- error(
59884
- `${tokensPath}: colors.${problem.path} is ${problem.value} \u2014 the native runtimes parse only #RRGGBB or #RRGGBBAA` + (problem.suggestion ? `. Write ${problem.suggestion}.` : `, and this value names no colour that can be converted for you. Write the hex it should be.`)
59885
- );
59886
- }
59887
- return issues;
59888
- }
59896
+ // src/cli.ts
59897
+ init_token_lint();
59889
59898
 
59890
59899
  // src/icon-lint.ts
59891
59900
  init_icon();
@@ -61808,7 +61817,25 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
61808
61817
  ...hasWorkers ? { tier5Dir: bundleOutDir2(buildDir) } : {},
61809
61818
  collect: { lint: true, strict }
61810
61819
  });
61811
- const { report, hasErrors } = summarizeLint(app, bres, outcome, strict);
61820
+ const scaffoldSourceFindings = resolve40(sourceDir) === resolve40(appDir2) ? [] : [
61821
+ ...tokenColorIssues(sourceDir),
61822
+ ...surfaceIssues(sourceDir, void 0, strict),
61823
+ ...fontIssues(sourceDir, strict),
61824
+ ...storesV1Issues(sourceDir, strict)
61825
+ ].map((issue2) => ({
61826
+ ...issue2,
61827
+ // Say WHICH tree. The same message against two trees means two different fixes,
61828
+ // and the scaffold source is the one the author is least likely to be looking at.
61829
+ message: `scaffold source (--source-dir ${sourceDir}): ${issue2.message}`
61830
+ }));
61831
+ const { report, hasErrors } = summarizeLint(app, bres, outcome, strict, [
61832
+ ...await cmsIssues(buildDir, app, strict, { local: true }),
61833
+ ...surfaceIssues(buildDir, outcome.surfaceNav, strict),
61834
+ ...tokenColorIssues(buildDir),
61835
+ ...fontIssues(buildDir, strict),
61836
+ ...storesV1Issues(buildDir, strict),
61837
+ ...scaffoldSourceFindings
61838
+ ]);
61812
61839
  if (hasErrors && !force) {
61813
61840
  print({ ...report, published: false, hint: "lint found errors \u2014 fix them, or re-run with --force to publish anyway" });
61814
61841
  return 1;
@@ -20590,7 +20590,7 @@
20590
20590
  "name": "WixProductMedia",
20591
20591
  "kind": "interface",
20592
20592
  "jsdoc": "",
20593
- "decl": "export interface WixProductMedia {\n mainMedia?: Record<string, unknown>;\n}"
20593
+ "decl": "export interface WixProductMedia {\n mainMedia?: Record<string, unknown>;\n items?: unknown[];\n}"
20594
20594
  },
20595
20595
  {
20596
20596
  "name": "WixProduct",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.842.0",
3
+ "version": "0.844.0",
4
4
  "type": "module",
5
5
  "description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
6
6
  "keywords": [
@@ -63,5 +63,5 @@
63
63
  "artifactId": "himalaya-cli"
64
64
  }
65
65
  },
66
- "falconPackageHash": "b45ead5f2fb4dcd64fd4c31516607200700f0f8e9a1926efb5d6a6e2"
66
+ "falconPackageHash": "8835cc4b62bf41497a590d6558191fd77398f79e776d75eb0d554eaf"
67
67
  }
@@ -200,7 +200,7 @@ const svc = defineService<AriaChatState, {
200
200
  // either. Result on Android: no greeting, no prompt chips, no conversation, and a
201
201
  // Send that does nothing, for the life of the screen. Nothing reports it, because
202
202
  // a pending dispatch has no timeout: an action that never settles is
203
- // indistinguishable from one still running (#2518).
203
+ // indistinguishable from one still running.
204
204
  //
205
205
  // That stall is a known Android defect, not a new one. `WebViewJSWorker` already
206
206
  // prepends per-screen input into the bundle's own evaluate rather than assigning it
@@ -41,7 +41,7 @@ const svc = defineService<AriaHistoryState, {
41
41
  // NO module-scope `svc.load()` — same reason as the chat adapter next door, which
42
42
  // carries the full explanation. This `load` opens with `getConversations`, so a
43
43
  // self-kick makes a bridge call inside the bundle's own evaluation, and such a call
44
- // stalls on the Android WebView (#2518).
44
+ // stalls on the Android WebView.
45
45
  //
46
46
  // It is less damaging here than on the chat screen: this load has no create latch
47
47
  // for a dead promise to poison, so the `onAppear` load issues its own request and
@@ -200,7 +200,7 @@ const svc = defineService<AriaChatState, {
200
200
  // either. Result on Android: no greeting, no prompt chips, no conversation, and a
201
201
  // Send that does nothing, for the life of the screen. Nothing reports it, because
202
202
  // a pending dispatch has no timeout: an action that never settles is
203
- // indistinguishable from one still running (#2518).
203
+ // indistinguishable from one still running.
204
204
  //
205
205
  // That stall is a known Android defect, not a new one. `WebViewJSWorker` already
206
206
  // prepends per-screen input into the bundle's own evaluate rather than assigning it
@@ -41,7 +41,7 @@ const svc = defineService<AriaHistoryState, {
41
41
  // NO module-scope `svc.load()` — same reason as the chat adapter next door, which
42
42
  // carries the full explanation. This `load` opens with `getConversations`, so a
43
43
  // self-kick makes a bridge call inside the bundle's own evaluation, and such a call
44
- // stalls on the Android WebView (#2518).
44
+ // stalls on the Android WebView.
45
45
  //
46
46
  // It is less damaging here than on the chat screen: this load has no create latch
47
47
  // for a dead promise to poison, so the `onAppear` load issues its own request and
@@ -200,7 +200,7 @@ const svc = defineService<AriaChatState, {
200
200
  // either. Result on Android: no greeting, no prompt chips, no conversation, and a
201
201
  // Send that does nothing, for the life of the screen. Nothing reports it, because
202
202
  // a pending dispatch has no timeout: an action that never settles is
203
- // indistinguishable from one still running (#2518).
203
+ // indistinguishable from one still running.
204
204
  //
205
205
  // That stall is a known Android defect, not a new one. `WebViewJSWorker` already
206
206
  // prepends per-screen input into the bundle's own evaluate rather than assigning it
@@ -41,7 +41,7 @@ const svc = defineService<AriaHistoryState, {
41
41
  // NO module-scope `svc.load()` — same reason as the chat adapter next door, which
42
42
  // carries the full explanation. This `load` opens with `getConversations`, so a
43
43
  // self-kick makes a bridge call inside the bundle's own evaluation, and such a call
44
- // stalls on the Android WebView (#2518).
44
+ // stalls on the Android WebView.
45
45
  //
46
46
  // It is less damaging here than on the chat screen: this load has no create latch
47
47
  // for a dead promise to poison, so the `onAppear` load issues its own request and
@@ -200,7 +200,7 @@ const svc = defineService<AriaChatState, {
200
200
  // either. Result on Android: no greeting, no prompt chips, no conversation, and a
201
201
  // Send that does nothing, for the life of the screen. Nothing reports it, because
202
202
  // a pending dispatch has no timeout: an action that never settles is
203
- // indistinguishable from one still running (#2518).
203
+ // indistinguishable from one still running.
204
204
  //
205
205
  // That stall is a known Android defect, not a new one. `WebViewJSWorker` already
206
206
  // prepends per-screen input into the bundle's own evaluate rather than assigning it
@@ -41,7 +41,7 @@ const svc = defineService<AriaHistoryState, {
41
41
  // NO module-scope `svc.load()` — same reason as the chat adapter next door, which
42
42
  // carries the full explanation. This `load` opens with `getConversations`, so a
43
43
  // self-kick makes a bridge call inside the bundle's own evaluation, and such a call
44
- // stalls on the Android WebView (#2518).
44
+ // stalls on the Android WebView.
45
45
  //
46
46
  // It is less damaging here than on the chat screen: this load has no create latch
47
47
  // for a dead promise to poison, so the `onAppear` load issues its own request and
@@ -200,7 +200,7 @@ const svc = defineService<AriaChatState, {
200
200
  // either. Result on Android: no greeting, no prompt chips, no conversation, and a
201
201
  // Send that does nothing, for the life of the screen. Nothing reports it, because
202
202
  // a pending dispatch has no timeout: an action that never settles is
203
- // indistinguishable from one still running (#2518).
203
+ // indistinguishable from one still running.
204
204
  //
205
205
  // That stall is a known Android defect, not a new one. `WebViewJSWorker` already
206
206
  // prepends per-screen input into the bundle's own evaluate rather than assigning it
@@ -41,7 +41,7 @@ const svc = defineService<AriaHistoryState, {
41
41
  // NO module-scope `svc.load()` — same reason as the chat adapter next door, which
42
42
  // carries the full explanation. This `load` opens with `getConversations`, so a
43
43
  // self-kick makes a bridge call inside the bundle's own evaluation, and such a call
44
- // stalls on the Android WebView (#2518).
44
+ // stalls on the Android WebView.
45
45
  //
46
46
  // It is less damaging here than on the chat screen: this load has no create latch
47
47
  // for a dead promise to poison, so the `onAppear` load issues its own request and
@@ -200,7 +200,7 @@ const svc = defineService<AriaChatState, {
200
200
  // either. Result on Android: no greeting, no prompt chips, no conversation, and a
201
201
  // Send that does nothing, for the life of the screen. Nothing reports it, because
202
202
  // a pending dispatch has no timeout: an action that never settles is
203
- // indistinguishable from one still running (#2518).
203
+ // indistinguishable from one still running.
204
204
  //
205
205
  // That stall is a known Android defect, not a new one. `WebViewJSWorker` already
206
206
  // prepends per-screen input into the bundle's own evaluate rather than assigning it
@@ -41,7 +41,7 @@ const svc = defineService<AriaHistoryState, {
41
41
  // NO module-scope `svc.load()` — same reason as the chat adapter next door, which
42
42
  // carries the full explanation. This `load` opens with `getConversations`, so a
43
43
  // self-kick makes a bridge call inside the bundle's own evaluation, and such a call
44
- // stalls on the Android WebView (#2518).
44
+ // stalls on the Android WebView.
45
45
  //
46
46
  // It is less damaging here than on the chat screen: this load has no create latch
47
47
  // for a dead promise to poison, so the `onAppear` load issues its own request and
@@ -200,7 +200,7 @@ const svc = defineService<AriaChatState, {
200
200
  // either. Result on Android: no greeting, no prompt chips, no conversation, and a
201
201
  // Send that does nothing, for the life of the screen. Nothing reports it, because
202
202
  // a pending dispatch has no timeout: an action that never settles is
203
- // indistinguishable from one still running (#2518).
203
+ // indistinguishable from one still running.
204
204
  //
205
205
  // That stall is a known Android defect, not a new one. `WebViewJSWorker` already
206
206
  // prepends per-screen input into the bundle's own evaluate rather than assigning it
@@ -41,7 +41,7 @@ const svc = defineService<AriaHistoryState, {
41
41
  // NO module-scope `svc.load()` — same reason as the chat adapter next door, which
42
42
  // carries the full explanation. This `load` opens with `getConversations`, so a
43
43
  // self-kick makes a bridge call inside the bundle's own evaluation, and such a call
44
- // stalls on the Android WebView (#2518).
44
+ // stalls on the Android WebView.
45
45
  //
46
46
  // It is less damaging here than on the chat screen: this load has no create latch
47
47
  // for a dead promise to poison, so the `onAppear` load issues its own request and
@@ -200,7 +200,7 @@ const svc = defineService<AriaChatState, {
200
200
  // either. Result on Android: no greeting, no prompt chips, no conversation, and a
201
201
  // Send that does nothing, for the life of the screen. Nothing reports it, because
202
202
  // a pending dispatch has no timeout: an action that never settles is
203
- // indistinguishable from one still running (#2518).
203
+ // indistinguishable from one still running.
204
204
  //
205
205
  // That stall is a known Android defect, not a new one. `WebViewJSWorker` already
206
206
  // prepends per-screen input into the bundle's own evaluate rather than assigning it
@@ -41,7 +41,7 @@ const svc = defineService<AriaHistoryState, {
41
41
  // NO module-scope `svc.load()` — same reason as the chat adapter next door, which
42
42
  // carries the full explanation. This `load` opens with `getConversations`, so a
43
43
  // self-kick makes a bridge call inside the bundle's own evaluation, and such a call
44
- // stalls on the Android WebView (#2518).
44
+ // stalls on the Android WebView.
45
45
  //
46
46
  // It is less damaging here than on the chat screen: this load has no create latch
47
47
  // for a dead promise to poison, so the `onAppear` load issues its own request and
@@ -200,7 +200,7 @@ const svc = defineService<AriaChatState, {
200
200
  // either. Result on Android: no greeting, no prompt chips, no conversation, and a
201
201
  // Send that does nothing, for the life of the screen. Nothing reports it, because
202
202
  // a pending dispatch has no timeout: an action that never settles is
203
- // indistinguishable from one still running (#2518).
203
+ // indistinguishable from one still running.
204
204
  //
205
205
  // That stall is a known Android defect, not a new one. `WebViewJSWorker` already
206
206
  // prepends per-screen input into the bundle's own evaluate rather than assigning it
@@ -41,7 +41,7 @@ const svc = defineService<AriaHistoryState, {
41
41
  // NO module-scope `svc.load()` — same reason as the chat adapter next door, which
42
42
  // carries the full explanation. This `load` opens with `getConversations`, so a
43
43
  // self-kick makes a bridge call inside the bundle's own evaluation, and such a call
44
- // stalls on the Android WebView (#2518).
44
+ // stalls on the Android WebView.
45
45
  //
46
46
  // It is less damaging here than on the chat screen: this load has no create latch
47
47
  // for a dead promise to poison, so the `onAppear` load issues its own request and
@@ -200,7 +200,7 @@ const svc = defineService<AriaChatState, {
200
200
  // either. Result on Android: no greeting, no prompt chips, no conversation, and a
201
201
  // Send that does nothing, for the life of the screen. Nothing reports it, because
202
202
  // a pending dispatch has no timeout: an action that never settles is
203
- // indistinguishable from one still running (#2518).
203
+ // indistinguishable from one still running.
204
204
  //
205
205
  // That stall is a known Android defect, not a new one. `WebViewJSWorker` already
206
206
  // prepends per-screen input into the bundle's own evaluate rather than assigning it
@@ -41,7 +41,7 @@ const svc = defineService<AriaHistoryState, {
41
41
  // NO module-scope `svc.load()` — same reason as the chat adapter next door, which
42
42
  // carries the full explanation. This `load` opens with `getConversations`, so a
43
43
  // self-kick makes a bridge call inside the bundle's own evaluation, and such a call
44
- // stalls on the Android WebView (#2518).
44
+ // stalls on the Android WebView.
45
45
  //
46
46
  // It is less damaging here than on the chat screen: this load has no create latch
47
47
  // for a dead promise to poison, so the `onAppear` load issues its own request and
@@ -200,7 +200,7 @@ const svc = defineService<AriaChatState, {
200
200
  // either. Result on Android: no greeting, no prompt chips, no conversation, and a
201
201
  // Send that does nothing, for the life of the screen. Nothing reports it, because
202
202
  // a pending dispatch has no timeout: an action that never settles is
203
- // indistinguishable from one still running (#2518).
203
+ // indistinguishable from one still running.
204
204
  //
205
205
  // That stall is a known Android defect, not a new one. `WebViewJSWorker` already
206
206
  // prepends per-screen input into the bundle's own evaluate rather than assigning it
@@ -41,7 +41,7 @@ const svc = defineService<AriaHistoryState, {
41
41
  // NO module-scope `svc.load()` — same reason as the chat adapter next door, which
42
42
  // carries the full explanation. This `load` opens with `getConversations`, so a
43
43
  // self-kick makes a bridge call inside the bundle's own evaluation, and such a call
44
- // stalls on the Android WebView (#2518).
44
+ // stalls on the Android WebView.
45
45
  //
46
46
  // It is less damaging here than on the chat screen: this load has no create latch
47
47
  // for a dead promise to poison, so the `onAppear` load issues its own request and