peachsim 0.1.2199 → 0.1.2200

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 (106) hide show
  1. package/cli/commands/inspect/settling.ts +20 -20
  2. package/cli/outbound-endpoints.ts +12 -0
  3. package/dist-lib/agent-daemon-client.cjs +1 -1
  4. package/dist-lib/agent-events.cjs +1 -1
  5. package/dist-lib/attached-projects.cjs +1 -1
  6. package/dist-lib/auth/shared-session.cjs +1 -1
  7. package/dist-lib/backend-origin.cjs +1 -1
  8. package/dist-lib/beta.cjs +1 -1
  9. package/dist-lib/beta.mjs +1 -1
  10. package/dist-lib/bridge-constants.cjs +1 -1
  11. package/dist-lib/bridge-contract-input.cjs +1 -1
  12. package/dist-lib/bridge-contract-input.mjs +1 -1
  13. package/dist-lib/bridge-contract.cjs +1 -1
  14. package/dist-lib/bridge-contract.mjs +1 -1
  15. package/dist-lib/bundle-channel.cjs +1421 -1117
  16. package/dist-lib/capture-contract.cjs +1 -1
  17. package/dist-lib/capture-contract.mjs +1 -1
  18. package/dist-lib/cloud-contract.cjs +1 -1
  19. package/dist-lib/cloud-contract.mjs +1 -1
  20. package/dist-lib/cloud-test-args.cjs +1 -1
  21. package/dist-lib/cloud-test-args.mjs +1 -1
  22. package/dist-lib/cloud.cjs +1 -1
  23. package/dist-lib/cloud.mjs +1 -1
  24. package/dist-lib/config.cjs +1 -1
  25. package/dist-lib/config.mjs +1 -1
  26. package/dist-lib/detox/index.cjs +22 -22
  27. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  28. package/dist-lib/expo-swift-bundle.cjs +45896 -39977
  29. package/dist-lib/expo-swift-metadata.cjs +1 -1
  30. package/dist-lib/expo-swift-metadata.mjs +1 -1
  31. package/dist-lib/home-paths.cjs +1 -1
  32. package/dist-lib/host/bridge-host.cjs +50877 -49773
  33. package/dist-lib/host/fetch-proxy-handler.cjs +16 -4
  34. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  35. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  36. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  37. package/dist-lib/host/websocket-proxy.cjs +1 -1
  38. package/dist-lib/index.cjs +36 -24
  39. package/dist-lib/jump-to-source-babel.cjs +1 -1
  40. package/dist-lib/jump-to-source-native.cjs +1 -1
  41. package/dist-lib/kotlin-host.cjs +100 -10
  42. package/dist-lib/menu.cjs +1 -1
  43. package/dist-lib/menu.mjs +1 -1
  44. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  45. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  46. package/dist-lib/metro-production-bundle.cjs +1 -1
  47. package/dist-lib/metro-production-bundle.mjs +1 -1
  48. package/dist-lib/metro.cjs +16 -4
  49. package/dist-lib/native-app-identity-project.cjs +14 -2
  50. package/dist-lib/native-app-identity-project.mjs +14 -2
  51. package/dist-lib/native-app-identity.cjs +1 -1
  52. package/dist-lib/native-app-identity.mjs +1 -1
  53. package/dist-lib/native-firebase-metadata.cjs +1 -1
  54. package/dist-lib/native-firebase-metadata.mjs +1 -1
  55. package/dist-lib/pdfium-raster.cjs +1 -1
  56. package/dist-lib/pdfium-raster.mjs +1 -1
  57. package/dist-lib/plist.cjs +1 -1
  58. package/dist-lib/plist.mjs +1 -1
  59. package/dist-lib/profiles.cjs +1 -1
  60. package/dist-lib/public-brand.cjs +1 -1
  61. package/dist-lib/public-origins-lib-esm.json +24 -24
  62. package/dist-lib/public-origins-lib.json +302 -289
  63. package/dist-lib/react-native-host-modules.cjs +1 -1
  64. package/dist-lib/react-native-host-modules.mjs +1 -1
  65. package/dist-lib/reap-browser.cjs +1 -1
  66. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  67. package/dist-lib/sdk.cjs +21 -21
  68. package/dist-lib/sdk.mjs +21 -21
  69. package/dist-lib/skills.cjs +3518 -2919
  70. package/dist-lib/swift-compile.cjs +34 -3
  71. package/dist-lib/swift-compile.mjs +34 -3
  72. package/dist-lib/swift-package.cjs +1 -1
  73. package/dist-lib/swift-package.mjs +1 -1
  74. package/dist-lib/swift-submit.cjs +1 -1
  75. package/dist-lib/swift-submit.mjs +1 -1
  76. package/dist-lib/swift-toolchain.cjs +1 -1
  77. package/dist-lib/swift.cjs +1 -1
  78. package/dist-lib/vite-swift.cjs +41 -7
  79. package/dist-lib/vite.cjs +16 -4
  80. package/dist-lib/worklet-executable.cjs +1 -1
  81. package/dist-lib/worklet-executable.mjs +1 -1
  82. package/dist-types/packages/peach-engine/src/engine/scene-table.d.ts +2 -0
  83. package/dist-types/packages/peach-engine/src/render-worker/app-prefetch-contract.d.ts +5 -0
  84. package/dist-types/packages/peach-engine/src/render-worker/protocol.d.ts +2 -0
  85. package/dist-types/packages/peach-engine/src/render-worker/tree-sync-port.d.ts +5 -0
  86. package/kotlin/sdk.tar.gz +0 -0
  87. package/package.json +1 -1
  88. package/runtime-companion.json +1 -1
  89. package/sdk/ios/System/Library/Frameworks/QuartzCore.framework/Headers/CAValueFunction.h +1 -1
  90. package/sdk/ios/System/Library/Frameworks/QuartzCore.framework/Modules/module.modulemap +1 -0
  91. package/sdk/ios/System/Library/Frameworks/UIKitText.framework/Headers/UIKitText.apinotes +14 -0
  92. package/src/android-layout-ids.ts +50 -0
  93. package/src/android-view-classes.ts +41 -0
  94. package/src/expo-swift-host.ts +6 -1
  95. package/src/java-module-abi.ts +2 -0
  96. package/src/javaAbiContract.ts +2 -0
  97. package/src/kotlin-app.ts +33 -7
  98. package/src/kotlin-host.ts +83 -6
  99. package/src/kotlin-maven-sources.ts +248 -0
  100. package/src/native-prebuilt.ts +2 -2
  101. package/src/react-native-core-build.ts +176 -0
  102. package/src/react-native-core-digest.ts +1 -1
  103. package/src/react-native-core.ts +24 -7
  104. package/src/swift-standin-emit.ts +9 -1
  105. package/src/swift-wasm-prune.ts +41 -3
  106. package/src/turbo-compile.ts +2 -1
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2199 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2200 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2199 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2200 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/react-native-host-modules.ts
4
4
  var REACT_NATIVE_PASSTHROUGH_SPECIFIERS = [
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2199 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2200 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2199 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2200 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
package/dist-lib/sdk.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2199 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2200 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1852,7 +1852,7 @@ function renderActivityIdleScript({
1852
1852
  const requiredStillMs = ${Math.max(1, Math.round(requiredStillMs))}
1853
1853
  let deadline = start + budgetMs
1854
1854
  // with no tenant running, nothing an app draws can move.
1855
- const host = window.__sootsimRenderHost ?? null
1855
+ const host = globalThis.__sootsimRenderHost ?? null
1856
1856
  // a runtime that predates the animating flag reports render work as busy.
1857
1857
  const moving = (activity) => activity.animating ?? activity.busy
1858
1858
  const initial = host ? host.getRenderActivity() : null
@@ -1880,10 +1880,10 @@ function renderActivityIdleScript({
1880
1880
  // budget proves the new screen. a loaded host runs a push past a tap's
1881
1881
  // budget, so the transition carries its own timeout.
1882
1882
  let transitionEndedAt = null
1883
- let transitionPending = budgetMs > 120 && typeof window.__sootsimTest?.waitForScreenTransitions === 'function'
1883
+ let transitionPending = budgetMs > 120 && typeof globalThis.__sootsimTest?.waitForScreenTransitions === 'function'
1884
1884
  if (transitionPending) {
1885
1885
  Promise.resolve()
1886
- .then(() => window.__sootsimTest.waitForScreenTransitions({
1886
+ .then(() => globalThis.__sootsimTest.waitForScreenTransitions({
1887
1887
  timeoutMs: ${Math.max(0, Math.round(transitionTimeoutMs))},
1888
1888
  settleMs: 64,
1889
1889
  startWindowMs: ${Math.max(0, Math.round(transitionStartWindowMs))},
@@ -1969,12 +1969,12 @@ async function waitForSootsimIdle({
1969
1969
  transitionTimeoutMs
1970
1970
  }) : `(async () => {
1971
1971
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
1972
- // tests inject a virtual clock as window.__sootsimIdleClock ({ now, sleep })
1972
+ // tests inject a virtual clock as globalThis.__sootsimIdleClock ({ now, sleep })
1973
1973
  // so the stillness window is proven in virtual time: real-timer polls under
1974
1974
  // load stretch past a tight budget on a still screen. the busy guards below
1975
1975
  // stay on the real setTimeout: virtual time advances only on poll sleeps,
1976
1976
  // never on a guard that loses its race to an instant read.
1977
- const idleClock = window.__sootsimIdleClock
1977
+ const idleClock = globalThis.__sootsimIdleClock
1978
1978
  const hasIdleClock =
1979
1979
  idleClock && typeof idleClock.now === 'function' && typeof idleClock.sleep === 'function'
1980
1980
  const clockNow = hasIdleClock ? () => idleClock.now() : () => Date.now()
@@ -1998,7 +1998,7 @@ async function waitForSootsimIdle({
1998
1998
  const fullGeometry = ${!maestro && maxMs >= 1e3 ? "true" : "false"}
1999
1999
  const requiredStillMs = paintStill ? 0 : ${Math.max(1, Math.round(stablePolls)) * Math.max(1, Math.round(pollMs))}
2000
2000
  const minimumStablePolls = paintStill ? 1 : ${Math.min(2, Math.max(1, Math.round(stablePolls)))}
2001
- const composite = paintStill ? window.SootSim?.bridges?.liveComposite : null
2001
+ const composite = paintStill ? globalThis.SootSim?.bridges?.liveComposite : null
2002
2002
  if (paintStill && !composite) {
2003
2003
  return { settled: false, elapsed: clockNow() - start, blockedBy: 'screen pixels unavailable' }
2004
2004
  }
@@ -2012,7 +2012,7 @@ async function waitForSootsimIdle({
2012
2012
  // it outlives this wait: a revision still current when a later wait
2013
2013
  // polls names the same geometry, so a step that follows a settled one
2014
2014
  // proves an unchanged screen without walking the tree again.
2015
- const geometry = (window.__peachSettleGeometry ??= { revision: null, hierarchy: null })
2015
+ const geometry = (globalThis.__peachSettleGeometry ??= { revision: null, hierarchy: null })
2016
2016
  try {
2017
2017
 
2018
2018
  // discover transitions while observing layout. when motion starts,
@@ -2022,7 +2022,7 @@ async function waitForSootsimIdle({
2022
2022
  // the budget restarts once it drains.
2023
2023
  let transitionWait = (async () => {
2024
2024
  try {
2025
- const wfst = window.__sootsimTest?.waitForScreenTransitions
2025
+ const wfst = globalThis.__sootsimTest?.waitForScreenTransitions
2026
2026
  if (typeof wfst === 'function' && budgetMs > 120) {
2027
2027
  const transition = await wfst({
2028
2028
  timeoutMs: ${Math.max(0, Math.round(transitionTimeoutMs))},
@@ -2078,19 +2078,19 @@ async function waitForSootsimIdle({
2078
2078
  // animations in both realms: a worklet can move the app while the
2079
2079
  // tenant's basic animation flag and last presented pixels read still.
2080
2080
  const accessibilityRead = maestro
2081
- ? answer(() => window.__sootsimTest.captureAccessibilityTree()).catch(() => null)
2081
+ ? answer(() => globalThis.__sootsimTest.captureAccessibilityTree()).catch(() => null)
2082
2082
  : null
2083
2083
  const motionRead = strict || paintStill
2084
- ? answer(() => window.__sootsimTest?.listAnimations?.()).catch(() => null)
2084
+ ? answer(() => globalThis.__sootsimTest?.listAnimations?.()).catch(() => null)
2085
2085
  : null
2086
- const statsRead = answer(() => window.__sootsimRenderHost?.queryStats?.()).catch(() => null)
2086
+ const statsRead = answer(() => globalThis.__sootsimRenderHost?.queryStats?.()).catch(() => null)
2087
2087
  // image preparation ends in the tenant before the compositor decodes
2088
2088
  // and realizes its pixels. both owners must finish before settling.
2089
2089
  // the compositor rejects a stats request it is too busy to answer.
2090
- const compositorRead = answer(() => window.__sootsimCompositor.getStats({ detail: 'readiness' })).catch(() => BUSY)
2091
- const countsRead = answer(() => window.__sootsimTest?.getRequestCounts?.()).catch(() => null)
2090
+ const compositorRead = answer(() => globalThis.__sootsimCompositor.getStats({ detail: 'readiness' })).catch(() => BUSY)
2091
+ const countsRead = answer(() => globalThis.__sootsimTest?.getRequestCounts?.()).catch(() => null)
2092
2092
  // the mounted hierarchy in render-worker mode comes from the test
2093
- // bridge: window.__sootsimRoot is an empty placeholder there, so a
2093
+ // bridge: globalThis.__sootsimRoot is an empty placeholder there, so a
2094
2094
  // walk over it hashes every screen to the same empty string while
2095
2095
  // it moves. listInspectable is the worker-backed read describe
2096
2096
  // uses; a worker too busy to answer it reads as unsettled. tight
@@ -2098,13 +2098,13 @@ async function waitForSootsimIdle({
2098
2098
  // it walks every node, so a poll whose geometry revision matches the
2099
2099
  // last read, in this wait or an earlier one, reuses that read.
2100
2100
  const hierarchyRead =
2101
- fullGeometry && typeof window.__sootsimTest?.listInspectable === 'function'
2102
- ? answer(() => window.__sootsimTest.getGeometryRevision?.())
2101
+ fullGeometry && typeof globalThis.__sootsimTest?.listInspectable === 'function'
2102
+ ? answer(() => globalThis.__sootsimTest.getGeometryRevision?.())
2103
2103
  .catch(() => null)
2104
2104
  .then((revision) => {
2105
2105
  if (revision === BUSY) return BUSY
2106
2106
  if (typeof revision === 'string' && geometry.revision === revision) return geometry.hierarchy
2107
- return answer(() => window.__sootsimTest.listInspectable({}))
2107
+ return answer(() => globalThis.__sootsimTest.listInspectable({}))
2108
2108
  .catch(() => null)
2109
2109
  .then((hierarchy) => {
2110
2110
  const kept = typeof revision === 'string' && Array.isArray(hierarchy)
@@ -2144,7 +2144,7 @@ async function waitForSootsimIdle({
2144
2144
  return {
2145
2145
  runtimeUnsupported: {
2146
2146
  error: 'runtime_readiness_unsupported',
2147
- runtimeVersion: window.__sootsimRuntimeVersion || 'unknown',
2147
+ runtimeVersion: globalThis.__sootsimRuntimeVersion || 'unknown',
2148
2148
  missingFields,
2149
2149
  },
2150
2150
  }
@@ -2190,7 +2190,7 @@ async function waitForSootsimIdle({
2190
2190
  // pre-motion baseline to compare against.
2191
2191
  const motionStill = !workerBusy && !animating && !layoutDirty && !shellAnimating
2192
2192
  const nodeCountRead = motionStill
2193
- ? answer(() => window.__sootsimTest?.getWindowNodeCount?.()).catch(() => null)
2193
+ ? answer(() => globalThis.__sootsimTest?.getWindowNodeCount?.()).catch(() => null)
2194
2194
  : null
2195
2195
  const compositor = await compositorRead
2196
2196
  if (compositor === BUSY) {
@@ -2262,7 +2262,7 @@ async function waitForSootsimIdle({
2262
2262
  )
2263
2263
  }
2264
2264
  } else {
2265
- const root = window.__sootsimRoot
2265
+ const root = globalThis.__sootsimRoot
2266
2266
  if (root) {
2267
2267
  const walk = (n) => {
2268
2268
  if (n.layout && n.layout.width > 0) {
package/dist-lib/sdk.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2199 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2200 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -1739,7 +1739,7 @@ function renderActivityIdleScript({
1739
1739
  const requiredStillMs = ${Math.max(1, Math.round(requiredStillMs))}
1740
1740
  let deadline = start + budgetMs
1741
1741
  // with no tenant running, nothing an app draws can move.
1742
- const host = window.__sootsimRenderHost ?? null
1742
+ const host = globalThis.__sootsimRenderHost ?? null
1743
1743
  // a runtime that predates the animating flag reports render work as busy.
1744
1744
  const moving = (activity) => activity.animating ?? activity.busy
1745
1745
  const initial = host ? host.getRenderActivity() : null
@@ -1767,10 +1767,10 @@ function renderActivityIdleScript({
1767
1767
  // budget proves the new screen. a loaded host runs a push past a tap's
1768
1768
  // budget, so the transition carries its own timeout.
1769
1769
  let transitionEndedAt = null
1770
- let transitionPending = budgetMs > 120 && typeof window.__sootsimTest?.waitForScreenTransitions === 'function'
1770
+ let transitionPending = budgetMs > 120 && typeof globalThis.__sootsimTest?.waitForScreenTransitions === 'function'
1771
1771
  if (transitionPending) {
1772
1772
  Promise.resolve()
1773
- .then(() => window.__sootsimTest.waitForScreenTransitions({
1773
+ .then(() => globalThis.__sootsimTest.waitForScreenTransitions({
1774
1774
  timeoutMs: ${Math.max(0, Math.round(transitionTimeoutMs))},
1775
1775
  settleMs: 64,
1776
1776
  startWindowMs: ${Math.max(0, Math.round(transitionStartWindowMs))},
@@ -1856,12 +1856,12 @@ async function waitForSootsimIdle({
1856
1856
  transitionTimeoutMs
1857
1857
  }) : `(async () => {
1858
1858
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
1859
- // tests inject a virtual clock as window.__sootsimIdleClock ({ now, sleep })
1859
+ // tests inject a virtual clock as globalThis.__sootsimIdleClock ({ now, sleep })
1860
1860
  // so the stillness window is proven in virtual time: real-timer polls under
1861
1861
  // load stretch past a tight budget on a still screen. the busy guards below
1862
1862
  // stay on the real setTimeout: virtual time advances only on poll sleeps,
1863
1863
  // never on a guard that loses its race to an instant read.
1864
- const idleClock = window.__sootsimIdleClock
1864
+ const idleClock = globalThis.__sootsimIdleClock
1865
1865
  const hasIdleClock =
1866
1866
  idleClock && typeof idleClock.now === 'function' && typeof idleClock.sleep === 'function'
1867
1867
  const clockNow = hasIdleClock ? () => idleClock.now() : () => Date.now()
@@ -1885,7 +1885,7 @@ async function waitForSootsimIdle({
1885
1885
  const fullGeometry = ${!maestro && maxMs >= 1e3 ? "true" : "false"}
1886
1886
  const requiredStillMs = paintStill ? 0 : ${Math.max(1, Math.round(stablePolls)) * Math.max(1, Math.round(pollMs))}
1887
1887
  const minimumStablePolls = paintStill ? 1 : ${Math.min(2, Math.max(1, Math.round(stablePolls)))}
1888
- const composite = paintStill ? window.SootSim?.bridges?.liveComposite : null
1888
+ const composite = paintStill ? globalThis.SootSim?.bridges?.liveComposite : null
1889
1889
  if (paintStill && !composite) {
1890
1890
  return { settled: false, elapsed: clockNow() - start, blockedBy: 'screen pixels unavailable' }
1891
1891
  }
@@ -1899,7 +1899,7 @@ async function waitForSootsimIdle({
1899
1899
  // it outlives this wait: a revision still current when a later wait
1900
1900
  // polls names the same geometry, so a step that follows a settled one
1901
1901
  // proves an unchanged screen without walking the tree again.
1902
- const geometry = (window.__peachSettleGeometry ??= { revision: null, hierarchy: null })
1902
+ const geometry = (globalThis.__peachSettleGeometry ??= { revision: null, hierarchy: null })
1903
1903
  try {
1904
1904
 
1905
1905
  // discover transitions while observing layout. when motion starts,
@@ -1909,7 +1909,7 @@ async function waitForSootsimIdle({
1909
1909
  // the budget restarts once it drains.
1910
1910
  let transitionWait = (async () => {
1911
1911
  try {
1912
- const wfst = window.__sootsimTest?.waitForScreenTransitions
1912
+ const wfst = globalThis.__sootsimTest?.waitForScreenTransitions
1913
1913
  if (typeof wfst === 'function' && budgetMs > 120) {
1914
1914
  const transition = await wfst({
1915
1915
  timeoutMs: ${Math.max(0, Math.round(transitionTimeoutMs))},
@@ -1965,19 +1965,19 @@ async function waitForSootsimIdle({
1965
1965
  // animations in both realms: a worklet can move the app while the
1966
1966
  // tenant's basic animation flag and last presented pixels read still.
1967
1967
  const accessibilityRead = maestro
1968
- ? answer(() => window.__sootsimTest.captureAccessibilityTree()).catch(() => null)
1968
+ ? answer(() => globalThis.__sootsimTest.captureAccessibilityTree()).catch(() => null)
1969
1969
  : null
1970
1970
  const motionRead = strict || paintStill
1971
- ? answer(() => window.__sootsimTest?.listAnimations?.()).catch(() => null)
1971
+ ? answer(() => globalThis.__sootsimTest?.listAnimations?.()).catch(() => null)
1972
1972
  : null
1973
- const statsRead = answer(() => window.__sootsimRenderHost?.queryStats?.()).catch(() => null)
1973
+ const statsRead = answer(() => globalThis.__sootsimRenderHost?.queryStats?.()).catch(() => null)
1974
1974
  // image preparation ends in the tenant before the compositor decodes
1975
1975
  // and realizes its pixels. both owners must finish before settling.
1976
1976
  // the compositor rejects a stats request it is too busy to answer.
1977
- const compositorRead = answer(() => window.__sootsimCompositor.getStats({ detail: 'readiness' })).catch(() => BUSY)
1978
- const countsRead = answer(() => window.__sootsimTest?.getRequestCounts?.()).catch(() => null)
1977
+ const compositorRead = answer(() => globalThis.__sootsimCompositor.getStats({ detail: 'readiness' })).catch(() => BUSY)
1978
+ const countsRead = answer(() => globalThis.__sootsimTest?.getRequestCounts?.()).catch(() => null)
1979
1979
  // the mounted hierarchy in render-worker mode comes from the test
1980
- // bridge: window.__sootsimRoot is an empty placeholder there, so a
1980
+ // bridge: globalThis.__sootsimRoot is an empty placeholder there, so a
1981
1981
  // walk over it hashes every screen to the same empty string while
1982
1982
  // it moves. listInspectable is the worker-backed read describe
1983
1983
  // uses; a worker too busy to answer it reads as unsettled. tight
@@ -1985,13 +1985,13 @@ async function waitForSootsimIdle({
1985
1985
  // it walks every node, so a poll whose geometry revision matches the
1986
1986
  // last read, in this wait or an earlier one, reuses that read.
1987
1987
  const hierarchyRead =
1988
- fullGeometry && typeof window.__sootsimTest?.listInspectable === 'function'
1989
- ? answer(() => window.__sootsimTest.getGeometryRevision?.())
1988
+ fullGeometry && typeof globalThis.__sootsimTest?.listInspectable === 'function'
1989
+ ? answer(() => globalThis.__sootsimTest.getGeometryRevision?.())
1990
1990
  .catch(() => null)
1991
1991
  .then((revision) => {
1992
1992
  if (revision === BUSY) return BUSY
1993
1993
  if (typeof revision === 'string' && geometry.revision === revision) return geometry.hierarchy
1994
- return answer(() => window.__sootsimTest.listInspectable({}))
1994
+ return answer(() => globalThis.__sootsimTest.listInspectable({}))
1995
1995
  .catch(() => null)
1996
1996
  .then((hierarchy) => {
1997
1997
  const kept = typeof revision === 'string' && Array.isArray(hierarchy)
@@ -2031,7 +2031,7 @@ async function waitForSootsimIdle({
2031
2031
  return {
2032
2032
  runtimeUnsupported: {
2033
2033
  error: 'runtime_readiness_unsupported',
2034
- runtimeVersion: window.__sootsimRuntimeVersion || 'unknown',
2034
+ runtimeVersion: globalThis.__sootsimRuntimeVersion || 'unknown',
2035
2035
  missingFields,
2036
2036
  },
2037
2037
  }
@@ -2077,7 +2077,7 @@ async function waitForSootsimIdle({
2077
2077
  // pre-motion baseline to compare against.
2078
2078
  const motionStill = !workerBusy && !animating && !layoutDirty && !shellAnimating
2079
2079
  const nodeCountRead = motionStill
2080
- ? answer(() => window.__sootsimTest?.getWindowNodeCount?.()).catch(() => null)
2080
+ ? answer(() => globalThis.__sootsimTest?.getWindowNodeCount?.()).catch(() => null)
2081
2081
  : null
2082
2082
  const compositor = await compositorRead
2083
2083
  if (compositor === BUSY) {
@@ -2149,7 +2149,7 @@ async function waitForSootsimIdle({
2149
2149
  )
2150
2150
  }
2151
2151
  } else {
2152
- const root = window.__sootsimRoot
2152
+ const root = globalThis.__sootsimRoot
2153
2153
  if (root) {
2154
2154
  const walk = (n) => {
2155
2155
  if (n.layout && n.layout.width > 0) {