peachsim 0.1.940 → 0.1.1399

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 (396) hide show
  1. package/README.md +28 -22
  2. package/cli/app-catalog.ts +29 -14
  3. package/cli/app-fonts.ts +5 -3
  4. package/cli/bridge-flow-runner.ts +40 -29
  5. package/cli/cloud-client.ts +57 -21
  6. package/cli/cloud-test-tunnel.ts +12 -18
  7. package/cli/commands/agent.ts +1 -1
  8. package/cli/commands/app-fonts.ts +3 -3
  9. package/cli/commands/assert.ts +8 -8
  10. package/cli/commands/auth.ts +8 -3
  11. package/cli/commands/box/bundle-plane.ts +13 -1
  12. package/cli/commands/box.ts +16 -5
  13. package/cli/commands/compat.ts +1 -1
  14. package/cli/commands/config.ts +2 -2
  15. package/cli/commands/control.ts +125 -71
  16. package/cli/commands/cpu-profile.ts +45 -1
  17. package/cli/commands/daemon.ts +131 -33
  18. package/cli/commands/debug.ts +24 -17
  19. package/cli/commands/desktop.ts +7 -1
  20. package/cli/commands/detect.ts +101 -0
  21. package/cli/commands/detox.ts +6 -6
  22. package/cli/commands/device.ts +12 -12
  23. package/cli/commands/electron.ts +32 -14
  24. package/cli/commands/flow.ts +49 -41
  25. package/cli/commands/guest-host.ts +39 -1
  26. package/cli/commands/inspect/core.ts +14 -8
  27. package/cli/commands/inspect/list.ts +1 -1
  28. package/cli/commands/inspect/settle.ts +5 -3
  29. package/cli/commands/inspect/settling.ts +229 -44
  30. package/cli/commands/inspect/wait-idle.ts +3 -2
  31. package/cli/commands/inspect.ts +105 -93
  32. package/cli/commands/install-cli.ts +36 -15
  33. package/cli/commands/install-desktop.ts +68 -195
  34. package/cli/commands/kotlin.ts +6 -5
  35. package/cli/commands/login.ts +5 -5
  36. package/cli/commands/maestro-compare.ts +554 -0
  37. package/cli/commands/maestro-generate.ts +6 -3
  38. package/cli/commands/maestro.ts +22 -0
  39. package/cli/commands/mode.ts +2 -2
  40. package/cli/commands/no-bridge-hint.ts +6 -2
  41. package/cli/commands/platform.ts +35 -6
  42. package/cli/commands/preview.ts +6 -0
  43. package/cli/commands/project-report.ts +10 -12
  44. package/cli/commands/record.ts +37 -37
  45. package/cli/commands/runtime.ts +9 -9
  46. package/cli/commands/screenshot-layers.ts +4 -4
  47. package/cli/commands/screenshot-mode.ts +2 -2
  48. package/cli/commands/screenshot.ts +8 -8
  49. package/cli/commands/screenshots-capture.ts +2 -2
  50. package/cli/commands/serve.ts +9 -12
  51. package/cli/commands/setup.ts +29 -14
  52. package/cli/commands/shell-boolean-mode.ts +2 -2
  53. package/cli/commands/show-touches-mode.ts +2 -2
  54. package/cli/commands/skills.ts +11 -11
  55. package/cli/commands/swift.ts +29 -11
  56. package/cli/commands/telemetry.ts +2 -2
  57. package/cli/commands/test.ts +5 -0
  58. package/cli/commands/three-mode.ts +3 -3
  59. package/cli/commands/timeline.ts +4 -4
  60. package/cli/commands/upgrade.ts +2 -2
  61. package/cli/commands/upload.ts +15 -15
  62. package/cli/commands/what-happened.ts +2 -2
  63. package/cli/current-sim.ts +6 -3
  64. package/cli/desktop-companion.ts +55 -149
  65. package/cli/dev-build-freshness.ts +2 -2
  66. package/cli/drivers/desktop.ts +17 -9
  67. package/cli/drivers/electron.ts +1 -2
  68. package/cli/drivers/playwright-sim-host.ts +11 -2
  69. package/cli/drivers/playwright.ts +35 -2
  70. package/cli/drivers/types.ts +8 -0
  71. package/cli/maestro-compare.ts +670 -0
  72. package/cli/outbound-endpoints.ts +46 -8
  73. package/cli/recording-access.ts +6 -6
  74. package/cli/run-registry.ts +1 -1
  75. package/cli/runtime-compat.ts +5 -1
  76. package/cli/send-to-box.ts +3 -3
  77. package/cli/shell-init.ts +2 -1
  78. package/cli/ws-bridge.ts +9 -5
  79. package/detox/element-types.ts +1 -0
  80. package/detox/gestures.ts +3 -3
  81. package/detox/index.ts +67 -38
  82. package/detox/navigation-lifecycle.ts +9 -6
  83. package/detox/proof-frame.cjs +6 -4
  84. package/dist-lib/agent-daemon-client.cjs +1 -1
  85. package/dist-lib/agent-events.cjs +1 -1
  86. package/dist-lib/attached-projects.cjs +1 -1
  87. package/dist-lib/auth/shared-session.cjs +1 -1
  88. package/dist-lib/backend-origin.cjs +1 -1
  89. package/dist-lib/beta.cjs +1 -1
  90. package/dist-lib/beta.mjs +1 -1
  91. package/dist-lib/bridge-constants.cjs +1 -1
  92. package/dist-lib/bridge-contract-input.cjs +42 -17
  93. package/dist-lib/bridge-contract-input.mjs +41 -16
  94. package/dist-lib/bridge-contract.cjs +1 -4
  95. package/dist-lib/bridge-contract.mjs +1 -3
  96. package/dist-lib/bundle-channel.cjs +2918 -550
  97. package/dist-lib/capture-contract.cjs +65 -24
  98. package/dist-lib/capture-contract.mjs +63 -24
  99. package/dist-lib/cloud-contract.cjs +2 -2
  100. package/dist-lib/cloud-contract.mjs +2 -2
  101. package/dist-lib/cloud-test-args.cjs +1 -1
  102. package/dist-lib/cloud-test-args.mjs +1 -1
  103. package/dist-lib/cloud.cjs +3 -3
  104. package/dist-lib/cloud.mjs +3 -3
  105. package/dist-lib/config.cjs +15 -5
  106. package/dist-lib/config.mjs +154 -0
  107. package/dist-lib/detox/index.cjs +495 -139
  108. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  109. package/dist-lib/expo-swift-bundle.cjs +1168 -238
  110. package/dist-lib/expo-swift-metadata.cjs +34 -23
  111. package/dist-lib/expo-swift-metadata.mjs +32 -23
  112. package/dist-lib/home-paths.cjs +2 -2
  113. package/dist-lib/host/bridge-host.cjs +2938 -654
  114. package/dist-lib/host/fetch-proxy-handler.cjs +14 -1
  115. package/dist-lib/host/fetch-proxy-overrides.cjs +7 -1
  116. package/dist-lib/host/fetch-proxy-overrides.mjs +5 -1
  117. package/dist-lib/host/replacement-module-handler.cjs +2 -2
  118. package/dist-lib/host/websocket-proxy.cjs +1 -1
  119. package/dist-lib/index.cjs +981 -353
  120. package/dist-lib/jump-to-source-babel.cjs +1 -1
  121. package/dist-lib/jump-to-source-native.cjs +1 -1
  122. package/dist-lib/kotlin-host.cjs +332 -19
  123. package/dist-lib/menu.cjs +1 -1
  124. package/dist-lib/menu.mjs +1 -1
  125. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  126. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  127. package/dist-lib/metro-production-bundle.cjs +7 -7
  128. package/dist-lib/metro-production-bundle.mjs +5 -5
  129. package/dist-lib/metro.cjs +670 -250
  130. package/dist-lib/native-app-identity-project.cjs +2647 -0
  131. package/dist-lib/native-app-identity-project.mjs +1257 -0
  132. package/dist-lib/native-app-identity.cjs +304 -25
  133. package/dist-lib/native-app-identity.mjs +302 -25
  134. package/dist-lib/native-firebase-metadata.cjs +1 -1
  135. package/dist-lib/native-firebase-metadata.mjs +1 -1
  136. package/dist-lib/plist.cjs +1 -1
  137. package/dist-lib/plist.mjs +1 -1
  138. package/dist-lib/profiles.cjs +1 -1
  139. package/dist-lib/public-brand.cjs +1 -1
  140. package/dist-lib/react-native-host-modules.cjs +5 -1
  141. package/dist-lib/react-native-host-modules.mjs +5 -1
  142. package/dist-lib/scripts/dev-server-scanner.cjs +57 -32
  143. package/dist-lib/sdk.cjs +231 -51
  144. package/dist-lib/sdk.mjs +231 -51
  145. package/dist-lib/skills.cjs +4107 -1374
  146. package/dist-lib/swift-compile.cjs +290 -30
  147. package/dist-lib/swift-compile.mjs +290 -30
  148. package/dist-lib/swift-package.cjs +143 -12
  149. package/dist-lib/swift-package.mjs +137 -11
  150. package/dist-lib/swift-submit.cjs +47 -5
  151. package/dist-lib/swift-submit.mjs +42 -5
  152. package/dist-lib/swift-toolchain.cjs +7 -2
  153. package/dist-lib/swift.cjs +1 -1
  154. package/dist-lib/vite-swift.cjs +1392 -458
  155. package/dist-lib/vite.cjs +13 -17
  156. package/dist-lib/worklet-executable.cjs +248 -33
  157. package/dist-lib/worklet-executable.mjs +248 -33
  158. package/install.sh +10 -1
  159. package/kotlin/{AppSources → AndroidViewSources}/android/content/res/Resources.kt +9 -9
  160. package/kotlin/AndroidViewSources/android/graphics/Canvas.kt +20 -0
  161. package/kotlin/AndroidViewSources/android/view/View.kt +211 -0
  162. package/kotlin/AndroidViewSources/android/widget/FrameLayout.kt +61 -0
  163. package/kotlin/AndroidViewSources/android/widget/LinearLayout.kt +49 -0
  164. package/kotlin/AppSources/android/view/Window.kt +36 -0
  165. package/kotlin/AppSources/android/view/WindowInsets.kt +9 -0
  166. package/kotlin/AppSources/android/view/WindowInsetsController.kt +5 -0
  167. package/kotlin/AppSources/android/window/OnBackInvokedDispatcher.kt +48 -0
  168. package/kotlin/AppSources/androidx/activity/OnBackPressedDispatcher.kt +20 -5
  169. package/kotlin/AppSources/androidx/compose/foundation/layout/WindowInsets.kt +15 -0
  170. package/kotlin/AppSources/androidx/compose/ui/platform/ComposeView.kt +2 -1
  171. package/kotlin/AppSources/dev/peach/app/PeachApp.kt +42 -50
  172. package/kotlin/ComposeSources/PeachComposeHost.kt +200 -84
  173. package/kotlin/ExpoComposeSources/PeachAndroidView.kt +87 -0
  174. package/kotlin/ExpoComposeSources/PeachExpoViewMount.kt +24 -0
  175. package/kotlin/ExpoComposeSources/dev/peach/expo/PeachExpoCompose.kt +28 -0
  176. package/kotlin/ExpoComposeSources/expo/modules/kotlin/views/ExpoComposeView.kt +70 -0
  177. package/kotlin/ExpoSources/dev/peach/expo/PeachExpoRuntime.kt +513 -0
  178. package/kotlin/ExpoSources/dev/peach/expo/PeachExpoTypes.kt +173 -0
  179. package/kotlin/ExpoSources/expo/modules/kotlin/AppContext.kt +20 -0
  180. package/kotlin/ExpoSources/expo/modules/kotlin/Promise.kt +19 -0
  181. package/kotlin/ExpoSources/expo/modules/kotlin/classcomponent/ClassComponentBuilder.kt +198 -0
  182. package/kotlin/ExpoSources/expo/modules/kotlin/exception/CodedException.kt +126 -0
  183. package/kotlin/ExpoSources/expo/modules/kotlin/functions/Functions.kt +132 -0
  184. package/kotlin/ExpoSources/expo/modules/kotlin/jni/JavaScriptTypedArray.kt +81 -0
  185. package/kotlin/ExpoSources/expo/modules/kotlin/modules/Module.kt +98 -0
  186. package/kotlin/ExpoSources/expo/modules/kotlin/objects/ObjectDefinitionBuilder.kt +236 -0
  187. package/kotlin/ExpoSources/expo/modules/kotlin/records/Record.kt +12 -0
  188. package/kotlin/ExpoSources/expo/modules/kotlin/runtime/Runtime.kt +9 -0
  189. package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedObject.kt +50 -0
  190. package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedObjectRegistry.kt +57 -0
  191. package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedRef.kt +19 -0
  192. package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/ConcreteTypedArrays.kt +158 -0
  193. package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/GenericTypedArray.kt +8 -0
  194. package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/TypedArray.kt +29 -0
  195. package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/TypedArrayIterator.kt +9 -0
  196. package/kotlin/ExpoSources/expo/modules/kotlin/types/AnyType.kt +155 -0
  197. package/kotlin/ExpoSources/expo/modules/kotlin/types/Either.kt +91 -0
  198. package/kotlin/ExpoSources/expo/modules/kotlin/types/Enumerable.kt +6 -0
  199. package/kotlin/ExpoSources/expo/modules/kotlin/viewevent/ViewEvent.kt +54 -0
  200. package/kotlin/ExpoSources/expo/modules/kotlin/views/ExpoView.kt +23 -0
  201. package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +71 -0
  202. package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewProps.kt +35 -0
  203. package/kotlin/README.md +13 -3
  204. package/kotlin/Sources/android/os/Build.kt +17 -0
  205. package/kotlin/Sources/android/os/Handler.kt +35 -0
  206. package/kotlin/Sources/android/os/Looper.kt +17 -0
  207. package/kotlin/Sources/android/os/MessageQueue.kt +56 -0
  208. package/kotlin/Sources/android/os/SystemClock.kt +14 -0
  209. package/kotlin/Sources/android/util/Log.kt +64 -0
  210. package/kotlin/Sources/java/security/MessageDigest.kt +114 -0
  211. package/kotlin/Sources/kotlin/text/StringFormat.kt +9 -0
  212. package/kotlin/Sources/org/json/JSON.kt +44 -0
  213. package/kotlin/fixtures/counter/Counter.d.kt.ts +1 -0
  214. package/kotlin/fixtures/counter/Counter.kt +10 -3
  215. package/kotlin/fixtures/counter/CounterApp.native.tsx +1 -1
  216. package/kotlin/fixtures/counter/vite.config.ts +2 -2
  217. package/kotlin/fixtures/headless-counter/Headless.kt +7 -6
  218. package/kotlin/fixtures/import-animation/Animation.d.kt.ts +7 -0
  219. package/kotlin/fixtures/import-animation/Animation.kt +80 -0
  220. package/kotlin/fixtures/import-animation/ImportAnimation.native.tsx +13 -0
  221. package/kotlin/fixtures/import-animation/README.md +24 -0
  222. package/kotlin/fixtures/import-animation/app/_layout.tsx +4 -0
  223. package/kotlin/fixtures/import-animation/app/index+spa.tsx +1 -0
  224. package/kotlin/fixtures/import-animation/app/routes.d.ts +18 -0
  225. package/kotlin/fixtures/import-animation/package.json +23 -0
  226. package/kotlin/fixtures/import-animation/tsconfig.json +20 -0
  227. package/kotlin/fixtures/import-animation/vite.config.ts +20 -0
  228. package/kotlin/fixtures/import-editor/Editor.d.kt.ts +7 -0
  229. package/kotlin/fixtures/import-editor/Editor.kt +59 -0
  230. package/kotlin/fixtures/import-editor/ImportEditor.native.tsx +23 -0
  231. package/kotlin/fixtures/import-editor/README.md +27 -0
  232. package/kotlin/fixtures/import-editor/app/_layout.tsx +4 -0
  233. package/kotlin/fixtures/import-editor/app/index+spa.tsx +1 -0
  234. package/kotlin/fixtures/import-editor/package.json +23 -0
  235. package/kotlin/fixtures/import-editor/tsconfig.json +20 -0
  236. package/kotlin/fixtures/import-editor/vite.config.ts +20 -0
  237. package/kotlin/fixtures/import-effects/Effects.d.kt.ts +7 -0
  238. package/kotlin/fixtures/import-effects/Effects.kt +87 -0
  239. package/kotlin/fixtures/import-effects/ImportEffects.native.tsx +13 -0
  240. package/kotlin/fixtures/import-effects/README.md +19 -0
  241. package/kotlin/fixtures/import-effects/app/_layout.tsx +4 -0
  242. package/kotlin/fixtures/import-effects/app/index+spa.tsx +1 -0
  243. package/kotlin/fixtures/import-effects/package.json +23 -0
  244. package/kotlin/fixtures/import-effects/tsconfig.json +20 -0
  245. package/kotlin/fixtures/import-effects/vite.config.ts +20 -0
  246. package/kotlin/fixtures/import-layout/ImportLayout.native.tsx +13 -0
  247. package/kotlin/fixtures/import-layout/Layout.d.kt.ts +7 -0
  248. package/kotlin/fixtures/import-layout/Layout.kt +72 -0
  249. package/kotlin/fixtures/import-layout/README.md +24 -0
  250. package/kotlin/fixtures/import-layout/app/_layout.tsx +4 -0
  251. package/kotlin/fixtures/import-layout/app/index+spa.tsx +1 -0
  252. package/kotlin/fixtures/import-layout/package.json +23 -0
  253. package/kotlin/fixtures/import-layout/tsconfig.json +20 -0
  254. package/kotlin/fixtures/import-layout/vite.config.ts +20 -0
  255. package/kotlin/fixtures/import-navigation/ImportNavigation.native.tsx +18 -0
  256. package/kotlin/fixtures/import-navigation/Navigation.d.kt.ts +7 -0
  257. package/kotlin/fixtures/import-navigation/Navigation.kt +104 -0
  258. package/kotlin/fixtures/import-navigation/README.md +31 -0
  259. package/kotlin/fixtures/import-navigation/app/_layout.tsx +4 -0
  260. package/kotlin/fixtures/import-navigation/app/index+spa.tsx +1 -0
  261. package/kotlin/fixtures/import-navigation/package.json +23 -0
  262. package/kotlin/fixtures/import-navigation/tsconfig.json +20 -0
  263. package/kotlin/fixtures/import-navigation/vite.config.ts +20 -0
  264. package/kotlin/fixtures/import-overlays/ImportOverlays.native.tsx +29 -0
  265. package/kotlin/fixtures/import-overlays/Overlays.d.kt.ts +7 -0
  266. package/kotlin/fixtures/import-overlays/Overlays.kt +93 -0
  267. package/kotlin/fixtures/import-overlays/README.md +34 -0
  268. package/kotlin/fixtures/import-overlays/app/_layout.tsx +4 -0
  269. package/kotlin/fixtures/import-overlays/app/index+spa.tsx +1 -0
  270. package/kotlin/fixtures/import-overlays/package.json +23 -0
  271. package/kotlin/fixtures/import-overlays/tsconfig.json +20 -0
  272. package/kotlin/fixtures/import-overlays/vite.config.ts +20 -0
  273. package/kotlin/fixtures/import-scroll/ImportScroll.native.tsx +13 -0
  274. package/kotlin/fixtures/import-scroll/README.md +23 -0
  275. package/kotlin/fixtures/import-scroll/Scroll.d.kt.ts +7 -0
  276. package/kotlin/fixtures/import-scroll/Scroll.kt +91 -0
  277. package/kotlin/fixtures/import-scroll/app/_layout.tsx +4 -0
  278. package/kotlin/fixtures/import-scroll/app/index+spa.tsx +1 -0
  279. package/kotlin/fixtures/import-scroll/package.json +23 -0
  280. package/kotlin/fixtures/import-scroll/tsconfig.json +20 -0
  281. package/kotlin/fixtures/import-scroll/vite.config.ts +20 -0
  282. package/kotlin/fixtures/import-selection/ImportSelection.native.tsx +44 -0
  283. package/kotlin/fixtures/import-selection/README.md +32 -0
  284. package/kotlin/fixtures/import-selection/Selection.d.kt.ts +8 -0
  285. package/kotlin/fixtures/import-selection/Selection.kt +78 -0
  286. package/kotlin/fixtures/import-selection/app/_layout.tsx +4 -0
  287. package/kotlin/fixtures/import-selection/app/index+spa.tsx +1 -0
  288. package/kotlin/fixtures/import-selection/package.json +23 -0
  289. package/kotlin/fixtures/import-selection/tsconfig.json +20 -0
  290. package/kotlin/fixtures/import-selection/vite.config.ts +20 -0
  291. package/kotlin/fixtures/import-surfaces/ImportSurfaces.native.tsx +13 -0
  292. package/kotlin/fixtures/import-surfaces/README.md +22 -0
  293. package/kotlin/fixtures/import-surfaces/Surfaces.d.kt.ts +7 -0
  294. package/kotlin/fixtures/import-surfaces/Surfaces.kt +64 -0
  295. package/kotlin/fixtures/import-surfaces/app/_layout.tsx +4 -0
  296. package/kotlin/fixtures/import-surfaces/app/index+spa.tsx +1 -0
  297. package/kotlin/fixtures/import-surfaces/package.json +23 -0
  298. package/kotlin/fixtures/import-surfaces/tsconfig.json +20 -0
  299. package/kotlin/fixtures/import-surfaces/vite.config.ts +20 -0
  300. package/kotlin/fixtures/import-values/ImportValues.native.tsx +35 -0
  301. package/kotlin/fixtures/import-values/README.md +23 -0
  302. package/kotlin/fixtures/import-values/Values.d.kt.ts +11 -0
  303. package/kotlin/fixtures/import-values/Values.kt +66 -0
  304. package/kotlin/fixtures/import-values/app/_layout.tsx +4 -0
  305. package/kotlin/fixtures/import-values/app/index+spa.tsx +1 -0
  306. package/kotlin/fixtures/import-values/package.json +23 -0
  307. package/kotlin/fixtures/import-values/tsconfig.json +20 -0
  308. package/kotlin/fixtures/import-values/vite.config.ts +20 -0
  309. package/kotlin/fixtures/kotlin-app-variants/BarBehavior.kt +38 -0
  310. package/kotlin/fixtures/kotlin-app-variants/BarVisibility.kt +36 -0
  311. package/kotlin/fixtures/kotlin-app-variants/Ime.kt +3 -1
  312. package/kotlin/fixtures/kotlin-app-variants/TransientInsets.kt +50 -0
  313. package/kotlin/fork/NOTICE +6 -1
  314. package/kotlin/fork/README.md +15 -7
  315. package/kotlin/fork/build.sh +2 -0
  316. package/kotlin/fork/compose-worker-globals.patch +186 -4
  317. package/kotlin/fork/fork.json +2 -2
  318. package/kotlin/fork/skiko-worker-clock.patch +12 -0
  319. package/kotlin/toolchain.json +12 -12
  320. package/kotlin/tools/expo-types.main.kts +115 -0
  321. package/package.json +17 -23
  322. package/scripts/dev-server-scanner.ts +92 -66
  323. package/skills/contrast/SKILL.md +2 -2
  324. package/skills/peach-debug/SKILL.md +1 -1
  325. package/skills/peach-perf/SKILL.md +1 -1
  326. package/skills/peach-setup/SKILL.md +2 -1
  327. package/skills/peach-test/SKILL.md +8 -0
  328. package/src/assetCatalogContract.ts +43 -1
  329. package/src/bridge-contract-input.ts +46 -19
  330. package/src/bridge-contract.ts +0 -1
  331. package/src/bundle-channel.mjs +197 -84
  332. package/src/bundleGlobalFooter.ts +38 -0
  333. package/src/capture-contract.ts +107 -33
  334. package/src/cloud-contract.ts +5 -1
  335. package/src/cloud.ts +5 -2
  336. package/src/config.ts +22 -3
  337. package/src/configured-bundle-producer.ts +1 -1
  338. package/src/desktop-host-delivery.ts +95 -1
  339. package/src/expo-kotlin-bundle.ts +29 -0
  340. package/src/expo-kotlin-host.ts +201 -0
  341. package/src/expo-swift-host.ts +96 -76
  342. package/src/expoKotlinContract.ts +70 -0
  343. package/src/expoSwiftContract.ts +4 -25
  344. package/src/home-paths.ts +7 -4
  345. package/src/host/bridge-host.ts +23 -3
  346. package/src/host/fetch-proxy-handler.ts +13 -0
  347. package/src/host/fetch-proxy-overrides.ts +11 -0
  348. package/src/host/replacement-module-handler.ts +5 -2
  349. package/src/index.ts +3 -1
  350. package/src/kotlin-host.ts +463 -19
  351. package/src/metro-plugin.ts +56 -28
  352. package/src/metro-production-bundle.ts +2 -2
  353. package/src/native-app-identity-project.ts +190 -0
  354. package/src/native-app-identity.ts +367 -34
  355. package/src/native-firebase-config.ts +69 -15
  356. package/src/native-seam-manifest.ts +6 -0
  357. package/src/one-widget-discovery.ts +2 -1
  358. package/src/openstep-plist.ts +107 -0
  359. package/src/react-native-host-modules.ts +4 -0
  360. package/src/runtime-assets.ts +2 -2
  361. package/src/sim-client.ts +2 -2
  362. package/src/swift-binary-modules.ts +3 -1
  363. package/src/swift-compile.ts +286 -38
  364. package/src/swift-distribution-contract.ts +4 -0
  365. package/src/swift-distribution.lock.json +123 -12
  366. package/src/swift-distribution.ts +7 -3
  367. package/src/swift-host.ts +298 -83
  368. package/src/swift-package-manifest.ts +29 -2
  369. package/src/swift-package.ts +180 -10
  370. package/src/swift-packages.ts +4 -0
  371. package/src/swift-standin-emit.ts +4 -1
  372. package/src/swift-standins.ts +274 -15
  373. package/src/swift-submit.ts +62 -7
  374. package/src/swift-toolchain.ts +6 -1
  375. package/src/swiftContract.ts +126 -3
  376. package/src/vite-plugin-one.ts +13 -16
  377. package/src/vite-plugin-swift.ts +4 -5
  378. package/src/vite-plugin.ts +360 -144
  379. package/src/vite.d.ts +1 -1
  380. package/src/worker-system-chunks.ts +221 -0
  381. package/src/worklet-executable.ts +348 -38
  382. package/src/worklets-babel.ts +1 -1
  383. package/src/xcode-project.ts +243 -127
  384. package/dist-lib/agent-identity.cjs +0 -39
  385. package/dist-lib/agent-sessions.cjs +0 -760
  386. package/dist-lib/cli-constants.cjs +0 -32
  387. package/dist-lib/render-mode.cjs +0 -44
  388. package/kotlin/AppSources/android/view/View.kt +0 -74
  389. package/kotlin/AppSources/android/widget/FrameLayout.kt +0 -6
  390. package/src/render-mode.ts +0 -15
  391. /package/kotlin/{AppSources → AndroidViewSources}/android/content/Context.kt +0 -0
  392. /package/kotlin/{AppSources → AndroidViewSources}/android/content/res/Configuration.kt +0 -0
  393. /package/kotlin/{AppSources → AndroidViewSources}/android/graphics/Color.kt +0 -0
  394. /package/kotlin/{AppSources → AndroidViewSources}/android/util/DisplayMetrics.kt +0 -0
  395. /package/kotlin/{AppSources → AndroidViewSources}/dev/peach/app/JavaFormat.kt +0 -0
  396. /package/kotlin/{AppSources → Sources}/java/lang/Runnable.kt +0 -0
@@ -0,0 +1,13 @@
1
+ import { useState } from 'react'
2
+ import { Text, View } from 'react-native'
3
+ import { Scroll } from './Scroll.kt'
4
+
5
+ export default function Index() {
6
+ const [step, setStep] = useState(0)
7
+ return (
8
+ <View style={{ flex: 1, backgroundColor: '#fff' }}>
9
+ <Scroll title={`Scroll step ${step}`} onStep={setStep} />
10
+ <Text testID="scroll-react-step">React step: {step}</Text>
11
+ </View>
12
+ )
13
+ }
@@ -0,0 +1,23 @@
1
+ # Imported Compose scrolling
2
+
3
+ Run One in this fixture, then open its Android bundle in Peach on Pixel 8.
4
+ Build the native Android target on a remote builder. Import the same files in
5
+ Contrast with catalog versions materialized.
6
+
7
+ Tap `scroll-step` to scroll all five containers through their official state
8
+ APIs. The plain containers move to 180 and 80 physical pixels. LazyColumn,
9
+ LazyRow and LazyVerticalGrid move to index/offset pairs 5/8, 4/4 and 8/6.
10
+ The callback updates React and the imported title while Compose retains count.
11
+ The disabled action must preserve every value. The second enabled tap resets
12
+ every scroll state to zero and advances count to two. Capture all four states,
13
+ including visible indexed content. This fixture claims state and scroll-to
14
+ execution, without drag/fling timing or full-frame pixel fidelity.
15
+
16
+ RAN, 2026-10-11: fresh One Android API 37, Peach and Contrast Android import
17
+ runs pass the four states with identical offsets and visible item indices.
18
+ The [functional receipt](https://r2.sootsim.com/kotlin-evidence/import-scroll/916c4e8107ef1d5972d87c74dc24d331616d0edab675d9792e06905041b92171/proof.json)
19
+ binds the Kotlin source, compiler, native APK, captures and executed probes.
20
+ All 50 published objects pass SHA256 readback; a wrong offset and a disabled
21
+ callback change reject the saved verdict. Contrast uses the repository's
22
+ `CONTRAST_TEST_STABLE_WATCH=1` setup to preload its known dependencies before
23
+ navigation. Required CI delivery remains separate from this functional proof.
@@ -0,0 +1,7 @@
1
+ // generated by one typegen; edits will be replaced
2
+ import type { ReactElement } from 'react'
3
+
4
+ export declare function Scroll(props: {
5
+ title: string
6
+ onStep?: ((value0: number) => void) | null
7
+ }): ReactElement
@@ -0,0 +1,91 @@
1
+ package dev.contrast.kotlinscroll
2
+
3
+ import androidx.compose.foundation.background
4
+ import androidx.compose.foundation.horizontalScroll
5
+ import androidx.compose.foundation.layout.Arrangement
6
+ import androidx.compose.foundation.layout.Column
7
+ import androidx.compose.foundation.layout.Row
8
+ import androidx.compose.foundation.layout.fillMaxSize
9
+ import androidx.compose.foundation.layout.padding
10
+ import androidx.compose.foundation.layout.size
11
+ import androidx.compose.foundation.lazy.LazyColumn
12
+ import androidx.compose.foundation.lazy.LazyRow
13
+ import androidx.compose.foundation.lazy.rememberLazyListState
14
+ import androidx.compose.foundation.lazy.grid.GridCells
15
+ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
16
+ import androidx.compose.foundation.lazy.grid.rememberLazyGridState
17
+ import androidx.compose.foundation.rememberScrollState
18
+ import androidx.compose.foundation.verticalScroll
19
+ import androidx.compose.material3.Button
20
+ import androidx.compose.material3.MaterialTheme
21
+ import androidx.compose.material3.Surface
22
+ import androidx.compose.material3.Text
23
+ import androidx.compose.material3.lightColorScheme
24
+ import androidx.compose.runtime.Composable
25
+ import androidx.compose.runtime.getValue
26
+ import androidx.compose.runtime.mutableStateOf
27
+ import androidx.compose.runtime.remember
28
+ import androidx.compose.runtime.rememberCoroutineScope
29
+ import androidx.compose.runtime.setValue
30
+ import androidx.compose.ui.Modifier
31
+ import androidx.compose.ui.graphics.Color
32
+ import androidx.compose.ui.platform.testTag
33
+ import androidx.compose.ui.unit.dp
34
+ import kotlinx.coroutines.launch
35
+
36
+ @Composable
37
+ fun Scroll(title: String, onStep: ((Int) -> Unit)? = null) {
38
+ var count by remember { mutableStateOf(0) }
39
+ val vertical = rememberScrollState()
40
+ val horizontal = rememberScrollState()
41
+ val column = rememberLazyListState()
42
+ val row = rememberLazyListState()
43
+ val grid = rememberLazyGridState()
44
+ val scope = rememberCoroutineScope()
45
+ MaterialTheme(colorScheme = lightColorScheme()) {
46
+ Surface(Modifier.fillMaxSize()) {
47
+ Column(Modifier.fillMaxSize().padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
48
+ Text(title, Modifier.testTag("scroll-title"))
49
+ Text("Count: $count", Modifier.testTag("scroll-count"))
50
+ Column(Modifier.size(280.dp, 64.dp).verticalScroll(vertical).background(Color(0xFFEADDFF))) {
51
+ repeat(20) { Text("Vertical $it", Modifier.size(280.dp, 32.dp)) }
52
+ }
53
+ Row(Modifier.size(280.dp, 48.dp).horizontalScroll(horizontal).background(Color(0xFFE8DEF8))) {
54
+ repeat(20) { Text("Horizontal $it", Modifier.size(100.dp, 48.dp)) }
55
+ }
56
+ LazyColumn(Modifier.size(280.dp, 64.dp).background(Color(0xFFEADDFF)), state = column) {
57
+ items(30) { Text("Column $it", Modifier.size(280.dp, 32.dp)) }
58
+ }
59
+ LazyRow(Modifier.size(280.dp, 48.dp).background(Color(0xFFE8DEF8)), state = row) {
60
+ items(30) { Text("Row $it", Modifier.size(100.dp, 48.dp)) }
61
+ }
62
+ LazyVerticalGrid(columns = GridCells.Fixed(2), modifier = Modifier.size(280.dp, 64.dp).background(Color(0xFFEADDFF)), state = grid) {
63
+ items(30) { Text("Grid $it", Modifier.size(140.dp, 32.dp)) }
64
+ }
65
+ Button(
66
+ onClick = {
67
+ scope.launch {
68
+ val next = count + 1
69
+ val moved = next % 2 == 1
70
+ vertical.scrollTo(if (moved) 180 else 0)
71
+ horizontal.scrollTo(if (moved) 80 else 0)
72
+ column.scrollToItem(if (moved) 5 else 0, if (moved) 8 else 0)
73
+ row.scrollToItem(if (moved) 4 else 0, if (moved) 4 else 0)
74
+ grid.scrollToItem(if (moved) 8 else 0, if (moved) 6 else 0)
75
+ count = next
76
+ onStep?.invoke(next)
77
+ }
78
+ },
79
+ modifier = Modifier.testTag("scroll-step"),
80
+ ) { Text("Next scroll step") }
81
+ Button(onClick = { count += 1000; onStep?.invoke(count) }, enabled = false, modifier = Modifier.testTag("scroll-disabled")) {
82
+ Text("Disabled scroll step")
83
+ }
84
+ Text(
85
+ "vertical=${vertical.value};horizontal=${horizontal.value};column=${column.firstVisibleItemIndex},${column.firstVisibleItemScrollOffset};row=${row.firstVisibleItemIndex},${row.firstVisibleItemScrollOffset};grid=${grid.firstVisibleItemIndex},${grid.firstVisibleItemScrollOffset}",
86
+ Modifier.testTag("scroll-geometry"),
87
+ )
88
+ }
89
+ }
90
+ }
91
+ }
@@ -0,0 +1,4 @@
1
+ import { Slot } from 'one'
2
+ export default function Layout() {
3
+ return <Slot />
4
+ }
@@ -0,0 +1 @@
1
+ export { default } from '../ImportScroll.native'
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "peach-kotlin-import-scroll-fixture",
3
+ "private": true,
4
+ "type": "module",
5
+ "targets": [
6
+ "native"
7
+ ],
8
+ "dependencies": {
9
+ "@react-navigation/core": "catalog:",
10
+ "@react-navigation/native": "catalog:",
11
+ "one": "catalog:",
12
+ "react": "catalog:",
13
+ "react-native": "catalog:",
14
+ "react-native-reanimated": "catalog:",
15
+ "react-native-screens": "catalog:",
16
+ "react-native-worklets": "catalog:"
17
+ },
18
+ "devDependencies": {
19
+ "@react-native-community/template": "catalog:",
20
+ "peachsim": "workspace:*",
21
+ "vite": "catalog:"
22
+ }
23
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "paths": {
4
+ "~/*": ["./*"]
5
+ },
6
+ "strict": true,
7
+ "allowArbitraryExtensions": true,
8
+ "rootDir": ".",
9
+ "module": "Preserve",
10
+ // allows react-native style imports without path extensions, for compat with platform-specific files
11
+ "moduleResolution": "Bundler",
12
+ "preserveSymlinks": true,
13
+ "skipLibCheck": true,
14
+ "jsx": "react-jsx",
15
+ "noImplicitAny": false,
16
+ "types": ["node", "react", "vite/client"],
17
+ "lib": ["dom", "esnext"]
18
+ },
19
+ "exclude": ["node_modules", "**/test", "**/dist", "**/types", "**/__tests__"]
20
+ }
@@ -0,0 +1,20 @@
1
+ import { one } from 'one/vite'
2
+ import { peachPlugin } from 'peachsim/vite'
3
+ export default {
4
+ root: import.meta.dirname,
5
+ plugins: [
6
+ one({
7
+ web: { defaultRenderMode: 'spa' },
8
+ native: {
9
+ bundler: 'vite',
10
+ app: {
11
+ name: 'KotlinScroll',
12
+ scheme: 'kotlinscroll',
13
+ android: { applicationId: 'dev.contrast.kotlinscroll' },
14
+ },
15
+ },
16
+ }),
17
+ peachPlugin(),
18
+ ],
19
+ server: { host: '0.0.0.0' },
20
+ }
@@ -0,0 +1,44 @@
1
+ import { useState } from 'react'
2
+ import { Pressable, Text, View } from 'react-native'
3
+ import { Selection } from './Selection.kt'
4
+
5
+ type SelectionEvent = [string, boolean, number]
6
+
7
+ export default function Index() {
8
+ const [title, setTitle] = useState('Imported selection')
9
+ const [enabled, setEnabled] = useState(true)
10
+ const [events, setEvents] = useState<SelectionEvent[]>([])
11
+ return (
12
+ <View style={{ flex: 1, paddingTop: 48, backgroundColor: '#fff' }}>
13
+ <View style={{ flex: 1 }}>
14
+ <Selection
15
+ title={title}
16
+ enabled={enabled}
17
+ onSelection={(source, value, count) =>
18
+ setEvents((previous) => [...previous, [source, value, count]])
19
+ }
20
+ />
21
+ </View>
22
+ <View style={{ height: 200, padding: 24 }}>
23
+ <Text testID="selection-props">{JSON.stringify({ title, enabled })}</Text>
24
+ <Text testID="selection-events">{JSON.stringify(events)}</Text>
25
+ <Pressable
26
+ testID="selection-title"
27
+ onPress={() =>
28
+ setTitle((value) =>
29
+ value === 'Imported selection' ? 'Updated selection' : 'Imported selection',
30
+ )
31
+ }
32
+ >
33
+ <Text>Update title</Text>
34
+ </Pressable>
35
+ <Pressable
36
+ testID="selection-enabled"
37
+ onPress={() => setEnabled((value) => !value)}
38
+ >
39
+ <Text>{enabled ? 'Disable controls' : 'Enable controls'}</Text>
40
+ </Pressable>
41
+ </View>
42
+ </View>
43
+ )
44
+ }
@@ -0,0 +1,32 @@
1
+ # Imported Compose selection controls
2
+
3
+ This fixture imports a public composable into a React Native app and reports
4
+ Switch, Checkbox, and RadioButton callbacks to React. Compose retains its
5
+ selection and callback count when React changes the title or enabled prop.
6
+
7
+ Run One here with `bunx one dev --port 8081`, then open that port with
8
+ `peach open 8081 --device pixel-8`. Generate native Android with
9
+ `bunx one prebuild --platform android`; build `android/` with
10
+ `./gradlew assembleDebug` on the repository's remote builder.
11
+
12
+ Toggle the React title twice before touching a native control. Tap Switch,
13
+ update the title, tap Checkbox, then RadioButton. Disable the controls and tap
14
+ Switch: neither Compose state nor React events may change. Enable them and
15
+ tap Checkbox again. The final state is `Updated selection|false|4|true`, and
16
+ `selection-events` contains
17
+ `[["switch",true,1],["checkbox",false,2],["radio",true,3],["checkbox",false,4]]`.
18
+
19
+ RAN 2026-10-11: Android debug and Kotlin/Wasm builds passed, followed in order
20
+ by One Android, Peach, and Contrast's native bundle producer. All eleven
21
+ observed states and the callback tuples above matched across the three hosts.
22
+ Peach and Contrast reported no preview errors. Contrast compiled `Selection.kt`
23
+ through its Kotlin import route and produced a complete bundle graph.
24
+
25
+ These runs used One `2.0.0-0.canary.1791724440037`, source
26
+ `65f7d27e6e6cbf33e94e41de7b8667c13c6a6077`, whose HMR socket uses the native
27
+ bundle server's origin. The earlier canary's connection-error toast intercepted
28
+ the React footer tap on Android. A separate direct Android tap now changes the
29
+ title, and the full interaction then passes on the unchanged Android native
30
+ sources. This establishes import and interaction behavior; it does not grade
31
+ pixels or the signed-in editor. Hashes, captures, and receipts are retained in
32
+ task `t-mv3qgkej-1kh0`.
@@ -0,0 +1,8 @@
1
+ // generated by one typegen; edits will be replaced
2
+ import type { ReactElement } from 'react'
3
+
4
+ export declare function Selection(props: {
5
+ title: string
6
+ enabled: boolean
7
+ onSelection?: ((value0: string, value1: boolean, value2: number) => void) | null
8
+ }): ReactElement
@@ -0,0 +1,78 @@
1
+ package dev.contrast.kotlinselection
2
+
3
+ import androidx.compose.foundation.layout.Arrangement
4
+ import androidx.compose.foundation.layout.Column
5
+ import androidx.compose.foundation.layout.Row
6
+ import androidx.compose.foundation.layout.fillMaxSize
7
+ import androidx.compose.foundation.layout.padding
8
+ import androidx.compose.material3.Checkbox
9
+ import androidx.compose.material3.MaterialTheme
10
+ import androidx.compose.material3.RadioButton
11
+ import androidx.compose.material3.Surface
12
+ import androidx.compose.material3.Switch
13
+ import androidx.compose.material3.Text
14
+ import androidx.compose.material3.lightColorScheme
15
+ import androidx.compose.runtime.Composable
16
+ import androidx.compose.runtime.getValue
17
+ import androidx.compose.runtime.mutableStateOf
18
+ import androidx.compose.runtime.remember
19
+ import androidx.compose.runtime.setValue
20
+ import androidx.compose.ui.Alignment
21
+ import androidx.compose.ui.Modifier
22
+ import androidx.compose.ui.platform.testTag
23
+ import androidx.compose.ui.semantics.contentDescription
24
+ import androidx.compose.ui.semantics.semantics
25
+ import androidx.compose.ui.unit.dp
26
+
27
+ @Composable
28
+ fun Selection(
29
+ title: String,
30
+ enabled: Boolean,
31
+ onSelection: ((String, Boolean, Int) -> Unit)? = null,
32
+ ) {
33
+ var selected by remember { mutableStateOf(false) }
34
+ var changes by remember { mutableStateOf(0) }
35
+ fun change(source: String, value: Boolean) {
36
+ selected = value
37
+ changes += 1
38
+ onSelection?.invoke(source, value, changes)
39
+ }
40
+ MaterialTheme(colorScheme = lightColorScheme()) {
41
+ Surface(Modifier.fillMaxSize()) {
42
+ Column(
43
+ Modifier.fillMaxSize().padding(24.dp),
44
+ verticalArrangement = Arrangement.spacedBy(16.dp),
45
+ ) {
46
+ Text(title, style = MaterialTheme.typography.headlineSmall)
47
+ Text("$title|$selected|$changes|$enabled", Modifier.testTag("selection-state"))
48
+ Row(verticalAlignment = Alignment.CenterVertically) {
49
+ Switch(
50
+ checked = selected,
51
+ enabled = enabled,
52
+ onCheckedChange = { change("switch", it) },
53
+ modifier = Modifier.testTag("selection-switch").semantics { contentDescription = "selection-switch" },
54
+ )
55
+ Text("Switch")
56
+ }
57
+ Row(verticalAlignment = Alignment.CenterVertically) {
58
+ Checkbox(
59
+ checked = selected,
60
+ enabled = enabled,
61
+ onCheckedChange = { change("checkbox", it) },
62
+ modifier = Modifier.testTag("selection-checkbox").semantics { contentDescription = "selection-checkbox" },
63
+ )
64
+ Text("Checkbox")
65
+ }
66
+ Row(verticalAlignment = Alignment.CenterVertically) {
67
+ RadioButton(
68
+ selected = selected,
69
+ enabled = enabled,
70
+ onClick = { change("radio", !selected) },
71
+ modifier = Modifier.testTag("selection-radio").semantics { contentDescription = "selection-radio" },
72
+ )
73
+ Text("Radio button")
74
+ }
75
+ }
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,4 @@
1
+ import { Slot } from 'one'
2
+ export default function Layout() {
3
+ return <Slot />
4
+ }
@@ -0,0 +1 @@
1
+ export { default } from '../ImportSelection.native'
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "peach-kotlin-import-selection-fixture",
3
+ "private": true,
4
+ "type": "module",
5
+ "targets": [
6
+ "native"
7
+ ],
8
+ "dependencies": {
9
+ "@react-navigation/core": "catalog:",
10
+ "@react-navigation/native": "catalog:",
11
+ "one": "catalog:",
12
+ "react": "catalog:",
13
+ "react-native": "catalog:",
14
+ "react-native-reanimated": "catalog:",
15
+ "react-native-screens": "catalog:",
16
+ "react-native-worklets": "catalog:"
17
+ },
18
+ "devDependencies": {
19
+ "@react-native-community/template": "catalog:",
20
+ "peachsim": "workspace:*",
21
+ "vite": "catalog:"
22
+ }
23
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "paths": {
4
+ "~/*": ["./*"]
5
+ },
6
+ "strict": true,
7
+ "allowArbitraryExtensions": true,
8
+ "rootDir": ".",
9
+ "module": "Preserve",
10
+ // allows react-native style imports without path extensions, for compat with platform-specific files
11
+ "moduleResolution": "Bundler",
12
+ "preserveSymlinks": true,
13
+ "skipLibCheck": true,
14
+ "jsx": "react-jsx",
15
+ "noImplicitAny": false,
16
+ "types": ["node", "react", "vite/client"],
17
+ "lib": ["dom", "esnext"]
18
+ },
19
+ "exclude": ["node_modules", "**/test", "**/dist", "**/types", "**/__tests__"]
20
+ }
@@ -0,0 +1,20 @@
1
+ import { one } from 'one/vite'
2
+ import { peachPlugin } from 'peachsim/vite'
3
+ export default {
4
+ root: import.meta.dirname,
5
+ plugins: [
6
+ one({
7
+ web: { defaultRenderMode: 'spa' },
8
+ native: {
9
+ bundler: 'vite',
10
+ app: {
11
+ name: 'KotlinSelection',
12
+ scheme: 'kotlinselection',
13
+ android: { applicationId: 'dev.contrast.kotlinselection' },
14
+ },
15
+ },
16
+ }),
17
+ peachPlugin(),
18
+ ],
19
+ server: { host: '0.0.0.0' },
20
+ }
@@ -0,0 +1,13 @@
1
+ import { useState } from 'react'
2
+ import { Text, View } from 'react-native'
3
+ import { Surfaces } from './Surfaces.kt'
4
+
5
+ export default function Index() {
6
+ const [step, setStep] = useState(0)
7
+ return (
8
+ <View style={{ flex: 1, backgroundColor: '#fff' }}>
9
+ <Surfaces title={`Surfaces step ${step}`} onStep={setStep} />
10
+ <Text testID="surfaces-react-step">React step: {step}</Text>
11
+ </View>
12
+ )
13
+ }
@@ -0,0 +1,22 @@
1
+ # Imported Compose surfaces
2
+
3
+ Run One in this fixture, then open its Android bundle in Peach on Pixel 8.
4
+ Build the native Android target on a remote builder. Import the same files in
5
+ Contrast with catalog versions materialized.
6
+
7
+ Tap `surfaces-step` to alternate Material light and dark color schemes. The
8
+ callback updates React and the imported title while Compose retains count.
9
+ Capture the rounded Surface, cut corner Card and horizontal divider in all
10
+ four states: light zero, dark one, disabled one and restored light two.
11
+ The disabled button must preserve count and every palette value. Read the
12
+ actual color scheme ARGB values on native Android and require both imported
13
+ hosts to match. These checks prove execution and state, without a pixel grade.
14
+
15
+ RAN, 2026-10-11: fresh One Android API 37, Peach and Contrast Android import
16
+ runs pass all four states with identical palette readbacks and callback values.
17
+ The [functional receipt](https://r2.sootsim.com/kotlin-evidence/import-surfaces/1575299a492a37b497f5e923be69b865c2fae9c81d62b448810bed330596d052/proof.json)
18
+ binds Kotlin source, compiler, native APK, captures and executed probes.
19
+ All 50 published objects pass SHA256 readback. A wrong surface color and a
20
+ disabled callback change reject the saved verdict. Required CI delivery remains
21
+ separate from this functional proof. The existing preview shell chrome and
22
+ native debug HMR warning remain in captures; their fidelity is unclaimed.
@@ -0,0 +1,7 @@
1
+ // generated by one typegen; edits will be replaced
2
+ import type { ReactElement } from 'react'
3
+
4
+ export declare function Surfaces(props: {
5
+ title: string
6
+ onStep?: ((value0: number) => void) | null
7
+ }): ReactElement
@@ -0,0 +1,64 @@
1
+ package dev.contrast.kotlinsurfaces
2
+
3
+ import androidx.compose.foundation.layout.Arrangement
4
+ import androidx.compose.foundation.layout.Column
5
+ import androidx.compose.foundation.layout.fillMaxSize
6
+ import androidx.compose.foundation.layout.padding
7
+ import androidx.compose.foundation.layout.size
8
+ import androidx.compose.foundation.shape.CutCornerShape
9
+ import androidx.compose.foundation.shape.RoundedCornerShape
10
+ import androidx.compose.material3.Button
11
+ import androidx.compose.material3.Card
12
+ import androidx.compose.material3.CardDefaults
13
+ import androidx.compose.material3.HorizontalDivider
14
+ import androidx.compose.material3.MaterialTheme
15
+ import androidx.compose.material3.Surface
16
+ import androidx.compose.material3.Text
17
+ import androidx.compose.material3.darkColorScheme
18
+ import androidx.compose.material3.lightColorScheme
19
+ import androidx.compose.runtime.Composable
20
+ import androidx.compose.runtime.getValue
21
+ import androidx.compose.runtime.mutableStateOf
22
+ import androidx.compose.runtime.remember
23
+ import androidx.compose.runtime.setValue
24
+ import androidx.compose.ui.Modifier
25
+ import androidx.compose.ui.graphics.toArgb
26
+ import androidx.compose.ui.platform.testTag
27
+ import androidx.compose.ui.unit.dp
28
+
29
+ @Composable
30
+ fun Surfaces(title: String, onStep: ((Int) -> Unit)? = null) {
31
+ var count by remember { mutableStateOf(0) }
32
+ val dark = count % 2 == 1
33
+ val scheme = if (dark) darkColorScheme() else lightColorScheme()
34
+ MaterialTheme(colorScheme = scheme) {
35
+ Surface(Modifier.fillMaxSize()) {
36
+ Column(Modifier.fillMaxSize().padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
37
+ Text(title, Modifier.testTag("surfaces-title"))
38
+ Text("Count: $count", Modifier.testTag("surfaces-count"))
39
+ Surface(
40
+ modifier = Modifier.size(280.dp, 64.dp).testTag("surfaces-rounded"),
41
+ shape = RoundedCornerShape(12.dp),
42
+ color = scheme.primary,
43
+ contentColor = scheme.onPrimary,
44
+ ) { Text("Rounded surface", Modifier.padding(12.dp)) }
45
+ Card(
46
+ modifier = Modifier.size(280.dp, 64.dp).testTag("surfaces-cut"),
47
+ shape = CutCornerShape(8.dp),
48
+ colors = CardDefaults.cardColors(containerColor = scheme.secondaryContainer),
49
+ ) { Text("Cut corner card", Modifier.padding(12.dp)) }
50
+ HorizontalDivider(Modifier.size(280.dp, 2.dp).testTag("surfaces-divider"), thickness = 2.dp)
51
+ Button(onClick = { count += 1; onStep?.invoke(count) }, modifier = Modifier.testTag("surfaces-step")) {
52
+ Text("Next surfaces step")
53
+ }
54
+ Button(onClick = { count += 1000; onStep?.invoke(count) }, enabled = false, modifier = Modifier.testTag("surfaces-disabled")) {
55
+ Text("Disabled surfaces step")
56
+ }
57
+ Text(
58
+ "dark=${if (dark) 1 else 0};surface=${scheme.surface.toArgb()};onSurface=${scheme.onSurface.toArgb()};primary=${scheme.primary.toArgb()};secondaryContainer=${scheme.secondaryContainer.toArgb()}",
59
+ Modifier.testTag("surfaces-palette"),
60
+ )
61
+ }
62
+ }
63
+ }
64
+ }
@@ -0,0 +1,4 @@
1
+ import { Slot } from 'one'
2
+ export default function Layout() {
3
+ return <Slot />
4
+ }
@@ -0,0 +1 @@
1
+ export { default } from '../ImportSurfaces.native'
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "peach-kotlin-import-surfaces-fixture",
3
+ "private": true,
4
+ "type": "module",
5
+ "targets": [
6
+ "native"
7
+ ],
8
+ "dependencies": {
9
+ "@react-navigation/core": "catalog:",
10
+ "@react-navigation/native": "catalog:",
11
+ "one": "catalog:",
12
+ "react": "catalog:",
13
+ "react-native": "catalog:",
14
+ "react-native-reanimated": "catalog:",
15
+ "react-native-screens": "catalog:",
16
+ "react-native-worklets": "catalog:"
17
+ },
18
+ "devDependencies": {
19
+ "@react-native-community/template": "catalog:",
20
+ "peachsim": "workspace:*",
21
+ "vite": "catalog:"
22
+ }
23
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "paths": {
4
+ "~/*": ["./*"]
5
+ },
6
+ "strict": true,
7
+ "allowArbitraryExtensions": true,
8
+ "rootDir": ".",
9
+ "module": "Preserve",
10
+ // allows react-native style imports without path extensions, for compat with platform-specific files
11
+ "moduleResolution": "Bundler",
12
+ "preserveSymlinks": true,
13
+ "skipLibCheck": true,
14
+ "jsx": "react-jsx",
15
+ "noImplicitAny": false,
16
+ "types": ["node", "react", "vite/client"],
17
+ "lib": ["dom", "esnext"]
18
+ },
19
+ "exclude": ["node_modules", "**/test", "**/dist", "**/types", "**/__tests__"]
20
+ }
@@ -0,0 +1,20 @@
1
+ import { one } from 'one/vite'
2
+ import { peachPlugin } from 'peachsim/vite'
3
+ export default {
4
+ root: import.meta.dirname,
5
+ plugins: [
6
+ one({
7
+ web: { defaultRenderMode: 'spa' },
8
+ native: {
9
+ bundler: 'vite',
10
+ app: {
11
+ name: 'KotlinSurfaces',
12
+ scheme: 'kotlinsurfaces',
13
+ android: { applicationId: 'dev.contrast.kotlinsurfaces' },
14
+ },
15
+ },
16
+ }),
17
+ peachPlugin(),
18
+ ],
19
+ server: { host: '0.0.0.0' },
20
+ }