rnxsim 0.1.442 → 0.1.444

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 (73) hide show
  1. package/cli/bin.ts +3 -1
  2. package/cli/cloud-client.ts +153 -17
  3. package/cli/cloud-dispatch.ts +15 -0
  4. package/cli/cloud-session.ts +69 -17
  5. package/cli/commands/box/bundle-plane.ts +71 -0
  6. package/cli/commands/box.ts +274 -115
  7. package/cli/commands/control.ts +1 -137
  8. package/cli/commands/flow.ts +1 -1
  9. package/cli/commands/inspect/list.ts +119 -2
  10. package/cli/commands/inspect.ts +3 -2
  11. package/cli/commands/platform.ts +95 -12
  12. package/cli/commands/reset.ts +7 -3
  13. package/cli/commands/state.ts +7 -3
  14. package/cli/flow-export.ts +55 -0
  15. package/cli/flow-session.ts +0 -47
  16. package/cli/outbound-endpoints.ts +7 -0
  17. package/cli/rnx-in-process.ts +98 -0
  18. package/cli/ws-bridge.ts +30 -0
  19. package/detox/jest-setup-after-env.cjs +4 -0
  20. package/detox/record-block-execution.cjs +78 -0
  21. package/dist-lib/agent-daemon-client.cjs +1 -1
  22. package/dist-lib/agent-events.cjs +1 -1
  23. package/dist-lib/agent-identity.cjs +1 -1
  24. package/dist-lib/agent-sessions.cjs +1 -1
  25. package/dist-lib/attached-projects.cjs +1 -1
  26. package/dist-lib/auth/shared-session.cjs +1 -1
  27. package/dist-lib/backend-origin.cjs +1 -1
  28. package/dist-lib/beta.cjs +1 -1
  29. package/dist-lib/beta.mjs +1 -1
  30. package/dist-lib/bridge-constants.cjs +1 -1
  31. package/dist-lib/bridge-contract-input.cjs +1 -1
  32. package/dist-lib/bridge-contract-input.mjs +1 -1
  33. package/dist-lib/bridge-contract.cjs +1 -1
  34. package/dist-lib/bridge-contract.mjs +1 -1
  35. package/dist-lib/capture-contract.cjs +1 -1
  36. package/dist-lib/capture-contract.mjs +1 -1
  37. package/dist-lib/cli-constants.cjs +1 -1
  38. package/dist-lib/cloud-contract.cjs +1 -1
  39. package/dist-lib/cloud-contract.mjs +1 -1
  40. package/dist-lib/cloud.cjs +1 -1
  41. package/dist-lib/cloud.mjs +1 -1
  42. package/dist-lib/config.cjs +1 -1
  43. package/dist-lib/detox/index.cjs +69 -14
  44. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  45. package/dist-lib/home-paths.cjs +17 -1
  46. package/dist-lib/host/bridge-host.cjs +43 -32
  47. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  48. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  49. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  50. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  51. package/dist-lib/host/websocket-proxy.cjs +1 -1
  52. package/dist-lib/index.cjs +1 -3
  53. package/dist-lib/jump-to-source-babel.cjs +1 -1
  54. package/dist-lib/menu.cjs +10 -19
  55. package/dist-lib/menu.mjs +10 -19
  56. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  57. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  58. package/dist-lib/metro-production-bundle.cjs +1 -1
  59. package/dist-lib/metro-production-bundle.mjs +1 -1
  60. package/dist-lib/metro.cjs +1 -1
  61. package/dist-lib/profiles.cjs +1 -1
  62. package/dist-lib/public-brand.cjs +1 -1
  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/render-mode.cjs +1 -1
  66. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  67. package/dist-lib/sdk.cjs +1 -1
  68. package/dist-lib/sdk.mjs +1 -1
  69. package/dist-lib/skills.cjs +586 -269
  70. package/dist-lib/vite.cjs +1 -1
  71. package/package.json +8 -1
  72. package/src/home-paths.ts +31 -1
  73. package/src/menu.ts +8 -17
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.442 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.444 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -89,6 +89,16 @@ function assertGpuBrowserCommand(command, runtime = currentRuntime()) {
89
89
  `[reap-browser] Chrome process did not retain the required ${angle} GPU arguments`
90
90
  );
91
91
  }
92
+ for (const name2 of ["--enable-features=", "--disable-features="]) {
93
+ const lists = args.filter((arg) => arg.startsWith(name2)).map((arg) => arg.slice(name2.length).split(",").filter(Boolean));
94
+ const kept = new Set(lists.at(-1) ?? []);
95
+ const dropped = lists.slice(0, -1).flat().filter((feature) => !kept.has(feature));
96
+ if (dropped.length > 0) {
97
+ throw new Error(
98
+ `[reap-browser] Chrome keeps only its last ${name2.slice(0, -1)} switch, which dropped ${dropped.join(",")}; add them to the merged list in scripts/lib/reap-browser.ts`
99
+ );
100
+ }
101
+ }
92
102
  if (runtime.platform === "darwin" && command.includes("/Applications/Google Chrome.app/")) {
93
103
  throw new Error(
94
104
  "[reap-browser] refused the user's installed Google Chrome; use Playwright channel chromium"
@@ -361,6 +371,26 @@ function gpuChromeArgs(platform = process.platform) {
361
371
  "--ignore-gpu-blocklist"
362
372
  ];
363
373
  }
374
+ function mergeFeatureSwitches(args, enabled = []) {
375
+ const enable = /* @__PURE__ */ new Set([...PLAYWRIGHT_ENABLED_FEATURES, ...enabled]);
376
+ const disable = /* @__PURE__ */ new Set([...PLAYWRIGHT_DISABLED_FEATURES, ...DISABLED_FEATURES]);
377
+ const rest = [];
378
+ for (const arg of args) {
379
+ const match = /^--(enable|disable)-features=(.*)$/.exec(arg);
380
+ if (!match) {
381
+ rest.push(arg);
382
+ continue;
383
+ }
384
+ for (const feature of match[2].split(",")) {
385
+ if (feature) (match[1] === "enable" ? enable : disable).add(feature);
386
+ }
387
+ }
388
+ return [
389
+ ...rest,
390
+ `--enable-features=${[...enable].join(",")}`,
391
+ `--disable-features=${[...disable].join(",")}`
392
+ ];
393
+ }
364
394
  function gpuChromeLaunchOptions(opts = {}, runtime = currentRuntime()) {
365
395
  const callerArgs = Array.isArray(opts.args) ? opts.args : [];
366
396
  const unsafe = callerArgs.find(isSoftwareRendererArgument);
@@ -401,7 +431,10 @@ function gpuChromeLaunchOptions(opts = {}, runtime = currentRuntime()) {
401
431
  // com.google.chrome.for.testing, so automation cannot become the target of
402
432
  // Dock open/quit events intended for the user's com.google.Chrome browser.
403
433
  channel: "chromium",
404
- args: [...unmanagedCallerArgs, ...gpuChromeArgs(runtime.platform)],
434
+ args: mergeFeatureSwitches([
435
+ ...unmanagedCallerArgs,
436
+ ...gpuChromeArgs(runtime.platform)
437
+ ]),
405
438
  ignoreDefaultArgs: ignoredDefaults
406
439
  };
407
440
  }
@@ -449,21 +482,23 @@ function softwareChromeLaunchOptions(opts) {
449
482
  }
450
483
  const callerArgs = Array.isArray(opts.args) ? opts.args.map(String) : [];
451
484
  const unmanagedCallerArgs = callerArgs.filter((arg) => {
452
- return !arg.startsWith("--use-angle=") && arg !== "--enable-gpu" && arg !== "--enable-gpu-rasterization" && arg !== "--enable-zero-copy" && arg !== "--ignore-gpu-blocklist" && !/^--enable-unsafe-webgpu(?:=.*)?$/i.test(arg) && !/^--enable-features=(?:Vulkan|WebGPU)(?:,(?:Vulkan|WebGPU))*$/i.test(arg) && !/^--enable-unsafe-swiftshader(?:=.*)?$/i.test(arg);
485
+ return !arg.startsWith("--use-angle=") && arg !== "--enable-gpu" && arg !== "--enable-gpu-rasterization" && arg !== "--enable-zero-copy" && arg !== "--ignore-gpu-blocklist" && !/^--enable-unsafe-webgpu(?:=.*)?$/i.test(arg) && !/^--enable-unsafe-swiftshader(?:=.*)?$/i.test(arg);
453
486
  });
454
487
  const software = {
455
488
  ...opts,
456
- args: [
457
- ...unmanagedCallerArgs,
458
- "--use-angle=swiftshader",
459
- "--enable-unsafe-swiftshader",
460
- // playwright's bundled software chromium exposes no navigator.gpu without
461
- // these two, and the compositor's only backend is webgpu. emitted here
462
- // rather than per caller so a hosted-linux launch and a local gpu launch
463
- // agree on what a sim needs.
464
- "--enable-unsafe-webgpu",
465
- "--enable-features=Vulkan"
466
- ]
489
+ // playwright's bundled software chromium exposes no navigator.gpu without
490
+ // --enable-unsafe-webgpu plus the Vulkan feature, and the compositor's only
491
+ // backend is webgpu. emitted here rather than per caller so a hosted-linux
492
+ // launch and a local gpu launch agree on what a sim needs.
493
+ args: mergeFeatureSwitches(
494
+ [
495
+ ...unmanagedCallerArgs,
496
+ "--use-angle=swiftshader",
497
+ "--enable-unsafe-swiftshader",
498
+ "--enable-unsafe-webgpu"
499
+ ],
500
+ ["Vulkan"]
501
+ )
467
502
  };
468
503
  delete software.channel;
469
504
  delete software.executablePath;
@@ -478,7 +513,7 @@ async function launchReapedChrome(launch3, opts = {}, rendererTarget, policy = {
478
513
  policy.processIdentity
479
514
  );
480
515
  }
481
- var import_node_child_process, discoveredChromePids, discoveredChromeProcesses, reapPids, installed, signalShutdownClaimed;
516
+ var import_node_child_process, discoveredChromePids, discoveredChromeProcesses, reapPids, installed, signalShutdownClaimed, PLAYWRIGHT_DISABLED_FEATURES, PLAYWRIGHT_ENABLED_FEATURES, DISABLED_FEATURES;
482
517
  var init_reap_browser = __esm({
483
518
  "../../scripts/lib/reap-browser.ts"() {
484
519
  "use strict";
@@ -488,6 +523,72 @@ var init_reap_browser = __esm({
488
523
  reapPids = /* @__PURE__ */ new Map();
489
524
  installed = false;
490
525
  signalShutdownClaimed = false;
526
+ PLAYWRIGHT_DISABLED_FEATURES = [
527
+ "AvoidUnnecessaryBeforeUnloadCheckSync",
528
+ "BoundaryEventDispatchTracksNodeRemoval",
529
+ "DestroyProfileOnBrowserClose",
530
+ "DialMediaRouteProvider",
531
+ "GlobalMediaControls",
532
+ "HttpsUpgrades",
533
+ "LensOverlay",
534
+ "MediaRouter",
535
+ "PaintHolding",
536
+ "ThirdPartyStoragePartitioning",
537
+ "Translate",
538
+ "AutoDeElevate",
539
+ "RenderDocument",
540
+ "OptimizationHints",
541
+ "msForceBrowserSignIn",
542
+ "msEdgeUpdateLaunchServicesPreferredVersion"
543
+ ];
544
+ PLAYWRIGHT_ENABLED_FEATURES = ["CDPScreenshotNewSurface"];
545
+ DISABLED_FEATURES = ["NetworkTimeServiceQuerying"];
546
+ }
547
+ });
548
+
549
+ // ../compat/src/capability-outcomes.ts
550
+ function aggregateCompatibilityOutcomes(contributions) {
551
+ let total = 0;
552
+ let passing = 0;
553
+ let assessed = 0;
554
+ let estimated = 0;
555
+ let hasMeasured = false;
556
+ let hasEstimated = false;
557
+ for (const entry of contributions) {
558
+ if (!Number.isFinite(entry.weight) || entry.weight < 0)
559
+ throw new Error("invalid package weight");
560
+ total += entry.weight;
561
+ if (entry.source === "measured") {
562
+ hasMeasured = true;
563
+ if (!entry.assessment) throw new Error("measured contribution requires assessment");
564
+ const measure = entry.assessment;
565
+ if (measure.totalWeight > 0) {
566
+ passing += entry.weight * measure.passedWeight / measure.totalWeight;
567
+ assessed += entry.weight * measure.assessedWeight / measure.totalWeight;
568
+ }
569
+ } else if (entry.source === "estimated") {
570
+ hasEstimated = true;
571
+ if (entry.estimate !== null) {
572
+ if (!Number.isFinite(entry.estimate) || entry.estimate < 0 || entry.estimate > 1)
573
+ throw new Error("invalid compatibility estimate");
574
+ passing += entry.weight * entry.estimate;
575
+ estimated += entry.weight;
576
+ }
577
+ }
578
+ }
579
+ return {
580
+ compatibility: assessed + estimated === 0 ? null : passing / (assessed + estimated),
581
+ assessed: total === 0 ? 0 : assessed / total,
582
+ estimated: total === 0 ? 0 : estimated / total,
583
+ source: hasMeasured && hasEstimated ? "mixed" : hasEstimated ? "estimated" : "measured"
584
+ };
585
+ }
586
+ function formatCompatibilityPercent(percent) {
587
+ return percent > 0 && percent < 0.1 ? "<0.1" : String(Number(percent.toFixed(1)));
588
+ }
589
+ var init_capability_outcomes = __esm({
590
+ "../compat/src/capability-outcomes.ts"() {
591
+ "use strict";
491
592
  }
492
593
  });
493
594
 
@@ -496,6 +597,7 @@ var UNKNOWN_RNX_SUPPORT;
496
597
  var init_native_evidence = __esm({
497
598
  "../compat/src/native-evidence.ts"() {
498
599
  "use strict";
600
+ init_capability_outcomes();
499
601
  UNKNOWN_RNX_SUPPORT = {
500
602
  level: "unknown",
501
603
  coverage: null,
@@ -515,26 +617,26 @@ var init_capability_inventory_coverage = __esm({
515
617
  "react-native": {
516
618
  combined: {
517
619
  raw: {
518
- covered: 0,
519
- ratio: 0,
620
+ covered: 7,
621
+ ratio: 0.00444162436548,
520
622
  total: 1576
521
623
  },
522
624
  weighted: {
523
- covered: 0,
524
- ratio: 0,
525
- total: 11841
625
+ covered: 0.00692770149447,
626
+ ratio: 0.00140695129709,
627
+ total: 4.92390995252
526
628
  }
527
629
  },
528
630
  semantic: {
529
631
  raw: {
530
- covered: 0,
531
- ratio: 0,
632
+ covered: 7,
633
+ ratio: 0.00623330365093,
532
634
  total: 1123
533
635
  },
534
636
  weighted: {
535
- covered: 0,
536
- ratio: 0,
537
- total: 7842
637
+ covered: 0.00692770149447,
638
+ ratio: 0.00274128218603,
639
+ total: 2.52717561504
538
640
  }
539
641
  },
540
642
  visual: {
@@ -546,7 +648,7 @@ var init_capability_inventory_coverage = __esm({
546
648
  weighted: {
547
649
  covered: 0,
548
650
  ratio: 0,
549
- total: 3999
651
+ total: 2.39673433748
550
652
  }
551
653
  },
552
654
  byPlatform: {
@@ -560,7 +662,7 @@ var init_capability_inventory_coverage = __esm({
560
662
  weighted: {
561
663
  covered: 0,
562
664
  ratio: 0,
563
- total: 10747
665
+ total: 4.82231702104
564
666
  }
565
667
  },
566
668
  semantic: {
@@ -572,7 +674,7 @@ var init_capability_inventory_coverage = __esm({
572
674
  weighted: {
573
675
  covered: 0,
574
676
  ratio: 0,
575
- total: 6998
677
+ total: 2.46477911515
576
678
  }
577
679
  },
578
680
  visual: {
@@ -584,33 +686,33 @@ var init_capability_inventory_coverage = __esm({
584
686
  weighted: {
585
687
  covered: 0,
586
688
  ratio: 0,
587
- total: 3749
689
+ total: 2.35753790589
588
690
  }
589
691
  }
590
692
  },
591
693
  ios: {
592
694
  combined: {
593
695
  raw: {
594
- covered: 0,
595
- ratio: 0,
696
+ covered: 213,
697
+ ratio: 0.153127246585,
596
698
  total: 1391
597
699
  },
598
700
  weighted: {
599
- covered: 0,
600
- ratio: 0,
601
- total: 10787
701
+ covered: 1.38498343762,
702
+ ratio: 0.289659691768,
703
+ total: 4.78141583721
602
704
  }
603
705
  },
604
706
  semantic: {
605
707
  raw: {
606
- covered: 0,
607
- ratio: 0,
708
+ covered: 213,
709
+ ratio: 0.213855421687,
608
710
  total: 996
609
711
  },
610
712
  weighted: {
611
- covered: 0,
612
- ratio: 0,
613
- total: 7077
713
+ covered: 1.38498343762,
714
+ ratio: 0.578085386368,
715
+ total: 2.39581119032
614
716
  }
615
717
  },
616
718
  visual: {
@@ -622,7 +724,7 @@ var init_capability_inventory_coverage = __esm({
622
724
  weighted: {
623
725
  covered: 0,
624
726
  ratio: 0,
625
- total: 3710
727
+ total: 2.38560464689
626
728
  }
627
729
  }
628
730
  }
@@ -638,7 +740,7 @@ var init_capability_inventory_coverage = __esm({
638
740
  weighted: {
639
741
  covered: 0,
640
742
  ratio: 0,
641
- total: 734
743
+ total: 5.68951644615
642
744
  }
643
745
  },
644
746
  semantic: {
@@ -650,7 +752,7 @@ var init_capability_inventory_coverage = __esm({
650
752
  weighted: {
651
753
  covered: 0,
652
754
  ratio: 0,
653
- total: 379
755
+ total: 4.25353097536
654
756
  }
655
757
  },
656
758
  visual: {
@@ -662,7 +764,7 @@ var init_capability_inventory_coverage = __esm({
662
764
  weighted: {
663
765
  covered: 0,
664
766
  ratio: 0,
665
- total: 355
767
+ total: 1.43598547079
666
768
  }
667
769
  },
668
770
  byPlatform: {
@@ -676,7 +778,7 @@ var init_capability_inventory_coverage = __esm({
676
778
  weighted: {
677
779
  covered: 0,
678
780
  ratio: 0,
679
- total: 734
781
+ total: 5.68951644615
680
782
  }
681
783
  },
682
784
  semantic: {
@@ -688,7 +790,7 @@ var init_capability_inventory_coverage = __esm({
688
790
  weighted: {
689
791
  covered: 0,
690
792
  ratio: 0,
691
- total: 379
793
+ total: 4.25353097536
692
794
  }
693
795
  },
694
796
  visual: {
@@ -700,7 +802,7 @@ var init_capability_inventory_coverage = __esm({
700
802
  weighted: {
701
803
  covered: 0,
702
804
  ratio: 0,
703
- total: 355
805
+ total: 1.43598547079
704
806
  }
705
807
  }
706
808
  },
@@ -714,7 +816,7 @@ var init_capability_inventory_coverage = __esm({
714
816
  weighted: {
715
817
  covered: 0,
716
818
  ratio: 0,
717
- total: 734
819
+ total: 5.68951644615
718
820
  }
719
821
  },
720
822
  semantic: {
@@ -726,7 +828,7 @@ var init_capability_inventory_coverage = __esm({
726
828
  weighted: {
727
829
  covered: 0,
728
830
  ratio: 0,
729
- total: 379
831
+ total: 4.25353097536
730
832
  }
731
833
  },
732
834
  visual: {
@@ -738,7 +840,7 @@ var init_capability_inventory_coverage = __esm({
738
840
  weighted: {
739
841
  covered: 0,
740
842
  ratio: 0,
741
- total: 355
843
+ total: 1.43598547079
742
844
  }
743
845
  }
744
846
  }
@@ -754,7 +856,7 @@ var init_capability_inventory_coverage = __esm({
754
856
  weighted: {
755
857
  covered: 0,
756
858
  ratio: 0,
757
- total: 389
859
+ total: 7.7344109777
758
860
  }
759
861
  },
760
862
  semantic: {
@@ -766,7 +868,7 @@ var init_capability_inventory_coverage = __esm({
766
868
  weighted: {
767
869
  covered: 0,
768
870
  ratio: 0,
769
- total: 317
871
+ total: 4.998
770
872
  }
771
873
  },
772
874
  visual: {
@@ -778,7 +880,7 @@ var init_capability_inventory_coverage = __esm({
778
880
  weighted: {
779
881
  covered: 0,
780
882
  ratio: 0,
781
- total: 72
883
+ total: 2.7364109777
782
884
  }
783
885
  },
784
886
  byPlatform: {
@@ -792,7 +894,7 @@ var init_capability_inventory_coverage = __esm({
792
894
  weighted: {
793
895
  covered: 0,
794
896
  ratio: 0,
795
- total: 389
897
+ total: 7.7344109777
796
898
  }
797
899
  },
798
900
  semantic: {
@@ -804,7 +906,7 @@ var init_capability_inventory_coverage = __esm({
804
906
  weighted: {
805
907
  covered: 0,
806
908
  ratio: 0,
807
- total: 317
909
+ total: 4.998
808
910
  }
809
911
  },
810
912
  visual: {
@@ -816,7 +918,7 @@ var init_capability_inventory_coverage = __esm({
816
918
  weighted: {
817
919
  covered: 0,
818
920
  ratio: 0,
819
- total: 72
921
+ total: 2.7364109777
820
922
  }
821
923
  }
822
924
  },
@@ -830,7 +932,7 @@ var init_capability_inventory_coverage = __esm({
830
932
  weighted: {
831
933
  covered: 0,
832
934
  ratio: 0,
833
- total: 389
935
+ total: 7.7344109777
834
936
  }
835
937
  },
836
938
  semantic: {
@@ -842,7 +944,7 @@ var init_capability_inventory_coverage = __esm({
842
944
  weighted: {
843
945
  covered: 0,
844
946
  ratio: 0,
845
- total: 317
947
+ total: 4.998
846
948
  }
847
949
  },
848
950
  visual: {
@@ -854,7 +956,7 @@ var init_capability_inventory_coverage = __esm({
854
956
  weighted: {
855
957
  covered: 0,
856
958
  ratio: 0,
857
- total: 72
959
+ total: 2.7364109777
858
960
  }
859
961
  }
860
962
  }
@@ -870,7 +972,7 @@ var init_capability_inventory_coverage = __esm({
870
972
  weighted: {
871
973
  covered: 0,
872
974
  ratio: 0,
873
- total: 2526
975
+ total: 7.61737830756
874
976
  }
875
977
  },
876
978
  semantic: {
@@ -882,7 +984,7 @@ var init_capability_inventory_coverage = __esm({
882
984
  weighted: {
883
985
  covered: 0,
884
986
  ratio: 0,
885
- total: 1331
987
+ total: 4.15717529811
886
988
  }
887
989
  },
888
990
  visual: {
@@ -894,7 +996,7 @@ var init_capability_inventory_coverage = __esm({
894
996
  weighted: {
895
997
  covered: 0,
896
998
  ratio: 0,
897
- total: 1195
999
+ total: 3.46020300945
898
1000
  }
899
1001
  },
900
1002
  byPlatform: {
@@ -908,7 +1010,7 @@ var init_capability_inventory_coverage = __esm({
908
1010
  weighted: {
909
1011
  covered: 0,
910
1012
  ratio: 0,
911
- total: 2526
1013
+ total: 7.61737830756
912
1014
  }
913
1015
  },
914
1016
  semantic: {
@@ -920,7 +1022,7 @@ var init_capability_inventory_coverage = __esm({
920
1022
  weighted: {
921
1023
  covered: 0,
922
1024
  ratio: 0,
923
- total: 1331
1025
+ total: 4.15717529811
924
1026
  }
925
1027
  },
926
1028
  visual: {
@@ -932,7 +1034,7 @@ var init_capability_inventory_coverage = __esm({
932
1034
  weighted: {
933
1035
  covered: 0,
934
1036
  ratio: 0,
935
- total: 1195
1037
+ total: 3.46020300945
936
1038
  }
937
1039
  }
938
1040
  },
@@ -946,7 +1048,7 @@ var init_capability_inventory_coverage = __esm({
946
1048
  weighted: {
947
1049
  covered: 0,
948
1050
  ratio: 0,
949
- total: 2526
1051
+ total: 7.61737830756
950
1052
  }
951
1053
  },
952
1054
  semantic: {
@@ -958,7 +1060,7 @@ var init_capability_inventory_coverage = __esm({
958
1060
  weighted: {
959
1061
  covered: 0,
960
1062
  ratio: 0,
961
- total: 1331
1063
+ total: 4.15717529811
962
1064
  }
963
1065
  },
964
1066
  visual: {
@@ -970,7 +1072,7 @@ var init_capability_inventory_coverage = __esm({
970
1072
  weighted: {
971
1073
  covered: 0,
972
1074
  ratio: 0,
973
- total: 1195
1075
+ total: 3.46020300945
974
1076
  }
975
1077
  }
976
1078
  }
@@ -986,7 +1088,7 @@ var init_capability_inventory_coverage = __esm({
986
1088
  weighted: {
987
1089
  covered: 0,
988
1090
  ratio: 0,
989
- total: 519
1091
+ total: 7.9894117647
990
1092
  }
991
1093
  },
992
1094
  semantic: {
@@ -998,7 +1100,7 @@ var init_capability_inventory_coverage = __esm({
998
1100
  weighted: {
999
1101
  covered: 0,
1000
1102
  ratio: 0,
1001
- total: 267
1103
+ total: 4.00352941176
1002
1104
  }
1003
1105
  },
1004
1106
  visual: {
@@ -1010,7 +1112,7 @@ var init_capability_inventory_coverage = __esm({
1010
1112
  weighted: {
1011
1113
  covered: 0,
1012
1114
  ratio: 0,
1013
- total: 252
1115
+ total: 3.98588235294
1014
1116
  }
1015
1117
  },
1016
1118
  byPlatform: {
@@ -1024,7 +1126,7 @@ var init_capability_inventory_coverage = __esm({
1024
1126
  weighted: {
1025
1127
  covered: 0,
1026
1128
  ratio: 0,
1027
- total: 519
1129
+ total: 7.9894117647
1028
1130
  }
1029
1131
  },
1030
1132
  semantic: {
@@ -1036,7 +1138,7 @@ var init_capability_inventory_coverage = __esm({
1036
1138
  weighted: {
1037
1139
  covered: 0,
1038
1140
  ratio: 0,
1039
- total: 267
1141
+ total: 4.00352941176
1040
1142
  }
1041
1143
  },
1042
1144
  visual: {
@@ -1048,7 +1150,7 @@ var init_capability_inventory_coverage = __esm({
1048
1150
  weighted: {
1049
1151
  covered: 0,
1050
1152
  ratio: 0,
1051
- total: 252
1153
+ total: 3.98588235294
1052
1154
  }
1053
1155
  }
1054
1156
  },
@@ -1062,7 +1164,7 @@ var init_capability_inventory_coverage = __esm({
1062
1164
  weighted: {
1063
1165
  covered: 0,
1064
1166
  ratio: 0,
1065
- total: 519
1167
+ total: 7.9894117647
1066
1168
  }
1067
1169
  },
1068
1170
  semantic: {
@@ -1074,7 +1176,7 @@ var init_capability_inventory_coverage = __esm({
1074
1176
  weighted: {
1075
1177
  covered: 0,
1076
1178
  ratio: 0,
1077
- total: 267
1179
+ total: 4.00352941176
1078
1180
  }
1079
1181
  },
1080
1182
  visual: {
@@ -1086,7 +1188,7 @@ var init_capability_inventory_coverage = __esm({
1086
1188
  weighted: {
1087
1189
  covered: 0,
1088
1190
  ratio: 0,
1089
- total: 252
1191
+ total: 3.98588235294
1090
1192
  }
1091
1193
  }
1092
1194
  }
@@ -1102,7 +1204,7 @@ var init_capability_inventory_coverage = __esm({
1102
1204
  weighted: {
1103
1205
  covered: 0,
1104
1206
  ratio: 0,
1105
- total: 932
1207
+ total: 4.1022362527
1106
1208
  }
1107
1209
  },
1108
1210
  semantic: {
@@ -1114,7 +1216,7 @@ var init_capability_inventory_coverage = __esm({
1114
1216
  weighted: {
1115
1217
  covered: 0,
1116
1218
  ratio: 0,
1117
- total: 154
1219
+ total: 0.0952595085136
1118
1220
  }
1119
1221
  },
1120
1222
  visual: {
@@ -1126,7 +1228,7 @@ var init_capability_inventory_coverage = __esm({
1126
1228
  weighted: {
1127
1229
  covered: 0,
1128
1230
  ratio: 0,
1129
- total: 778
1231
+ total: 4.00697674419
1130
1232
  }
1131
1233
  },
1132
1234
  byPlatform: {
@@ -1140,7 +1242,7 @@ var init_capability_inventory_coverage = __esm({
1140
1242
  weighted: {
1141
1243
  covered: 0,
1142
1244
  ratio: 0,
1143
- total: 932
1245
+ total: 4.1022362527
1144
1246
  }
1145
1247
  },
1146
1248
  semantic: {
@@ -1152,7 +1254,7 @@ var init_capability_inventory_coverage = __esm({
1152
1254
  weighted: {
1153
1255
  covered: 0,
1154
1256
  ratio: 0,
1155
- total: 154
1257
+ total: 0.0952595085136
1156
1258
  }
1157
1259
  },
1158
1260
  visual: {
@@ -1164,7 +1266,7 @@ var init_capability_inventory_coverage = __esm({
1164
1266
  weighted: {
1165
1267
  covered: 0,
1166
1268
  ratio: 0,
1167
- total: 778
1269
+ total: 4.00697674419
1168
1270
  }
1169
1271
  }
1170
1272
  },
@@ -1178,7 +1280,7 @@ var init_capability_inventory_coverage = __esm({
1178
1280
  weighted: {
1179
1281
  covered: 0,
1180
1282
  ratio: 0,
1181
- total: 932
1283
+ total: 4.1022362527
1182
1284
  }
1183
1285
  },
1184
1286
  semantic: {
@@ -1190,7 +1292,7 @@ var init_capability_inventory_coverage = __esm({
1190
1292
  weighted: {
1191
1293
  covered: 0,
1192
1294
  ratio: 0,
1193
- total: 154
1295
+ total: 0.0952595085136
1194
1296
  }
1195
1297
  },
1196
1298
  visual: {
@@ -1202,7 +1304,7 @@ var init_capability_inventory_coverage = __esm({
1202
1304
  weighted: {
1203
1305
  covered: 0,
1204
1306
  ratio: 0,
1205
- total: 778
1307
+ total: 4.00697674419
1206
1308
  }
1207
1309
  }
1208
1310
  }
@@ -1212,12 +1314,165 @@ var init_capability_inventory_coverage = __esm({
1212
1314
  }
1213
1315
  });
1214
1316
 
1317
+ // ../compat/src/generated/capability-outcomes.ts
1318
+ var CAPABILITY_PACKAGE_OUTCOMES;
1319
+ var init_capability_outcomes2 = __esm({
1320
+ "../compat/src/generated/capability-outcomes.ts"() {
1321
+ "use strict";
1322
+ CAPABILITY_PACKAGE_OUTCOMES = {
1323
+ "react-native": {
1324
+ exactTestedVersion: "0.86.2",
1325
+ supportedVersionRange: "0.86.x",
1326
+ byPlatform: {
1327
+ android: {
1328
+ passedWeight: 0,
1329
+ failedWeight: 0,
1330
+ unassessedWeight: 0.9703987341344257,
1331
+ totalWeight: 0.9703987341344257,
1332
+ assessedWeight: 0,
1333
+ compatibility: null,
1334
+ assessed: 0
1335
+ },
1336
+ ios: {
1337
+ passedWeight: 0,
1338
+ failedWeight: 0,
1339
+ unassessedWeight: 0.957145688695477,
1340
+ totalWeight: 0.957145688695477,
1341
+ assessedWeight: 0,
1342
+ compatibility: null,
1343
+ assessed: 0
1344
+ }
1345
+ }
1346
+ },
1347
+ "react-native-gesture-handler": {
1348
+ exactTestedVersion: "2.32.0",
1349
+ supportedVersionRange: ">=2.30.0",
1350
+ byPlatform: {
1351
+ android: {
1352
+ passedWeight: 0,
1353
+ failedWeight: 0,
1354
+ unassessedWeight: 0.9999999999997249,
1355
+ totalWeight: 0.9999999999997249,
1356
+ assessedWeight: 0,
1357
+ compatibility: null,
1358
+ assessed: 0
1359
+ },
1360
+ ios: {
1361
+ passedWeight: 0,
1362
+ failedWeight: 0,
1363
+ unassessedWeight: 0.9999999999997249,
1364
+ totalWeight: 0.9999999999997249,
1365
+ assessedWeight: 0,
1366
+ compatibility: null,
1367
+ assessed: 0
1368
+ }
1369
+ }
1370
+ },
1371
+ "react-native-keyboard-controller": {
1372
+ exactTestedVersion: "1.21.11",
1373
+ supportedVersionRange: ">=1.0.0",
1374
+ byPlatform: {
1375
+ android: {
1376
+ passedWeight: 0,
1377
+ failedWeight: 0,
1378
+ unassessedWeight: 0.9999999999999856,
1379
+ totalWeight: 0.9999999999999856,
1380
+ assessedWeight: 0,
1381
+ compatibility: null,
1382
+ assessed: 0
1383
+ },
1384
+ ios: {
1385
+ passedWeight: 0,
1386
+ failedWeight: 0,
1387
+ unassessedWeight: 0.9999999999999856,
1388
+ totalWeight: 0.9999999999999856,
1389
+ assessedWeight: 0,
1390
+ compatibility: null,
1391
+ assessed: 0
1392
+ }
1393
+ }
1394
+ },
1395
+ "react-native-reanimated": {
1396
+ exactTestedVersion: "4.5.1",
1397
+ supportedVersionRange: ">=4.0.0",
1398
+ byPlatform: {
1399
+ android: {
1400
+ passedWeight: 0,
1401
+ failedWeight: 0,
1402
+ unassessedWeight: 0.9999999999999165,
1403
+ totalWeight: 0.9999999999999165,
1404
+ assessedWeight: 0,
1405
+ compatibility: null,
1406
+ assessed: 0
1407
+ },
1408
+ ios: {
1409
+ passedWeight: 0,
1410
+ failedWeight: 0,
1411
+ unassessedWeight: 0.9999999999999165,
1412
+ totalWeight: 0.9999999999999165,
1413
+ assessedWeight: 0,
1414
+ compatibility: null,
1415
+ assessed: 0
1416
+ }
1417
+ }
1418
+ },
1419
+ "react-native-screens": {
1420
+ exactTestedVersion: "4.26.2",
1421
+ supportedVersionRange: ">=4.0.0",
1422
+ byPlatform: {
1423
+ android: {
1424
+ passedWeight: 0,
1425
+ failedWeight: 0,
1426
+ unassessedWeight: 0.9999999999996853,
1427
+ totalWeight: 0.9999999999996853,
1428
+ assessedWeight: 0,
1429
+ compatibility: null,
1430
+ assessed: 0
1431
+ },
1432
+ ios: {
1433
+ passedWeight: 0,
1434
+ failedWeight: 0,
1435
+ unassessedWeight: 0.9999999999996853,
1436
+ totalWeight: 0.9999999999996853,
1437
+ assessedWeight: 0,
1438
+ compatibility: null,
1439
+ assessed: 0
1440
+ }
1441
+ }
1442
+ },
1443
+ "react-native-svg": {
1444
+ exactTestedVersion: "15.15.4",
1445
+ supportedVersionRange: ">=13.0.0",
1446
+ byPlatform: {
1447
+ android: {
1448
+ passedWeight: 0,
1449
+ failedWeight: 0,
1450
+ unassessedWeight: 0.9999999999999477,
1451
+ totalWeight: 0.9999999999999477,
1452
+ assessedWeight: 0,
1453
+ compatibility: null,
1454
+ assessed: 0
1455
+ },
1456
+ ios: {
1457
+ passedWeight: 0,
1458
+ failedWeight: 0,
1459
+ unassessedWeight: 0.9999999999999477,
1460
+ totalWeight: 0.9999999999999477,
1461
+ assessedWeight: 0,
1462
+ compatibility: null,
1463
+ assessed: 0
1464
+ }
1465
+ }
1466
+ }
1467
+ };
1468
+ }
1469
+ });
1470
+
1215
1471
  // ../compat/src/generated/react-native-root-export-coverage.ts
1216
- var REACT_NATIVE_ROOT_EXPORT_WILL_IT_WORK_COVERAGE, REACT_NATIVE_ROOT_EXPORT_STRICT_COVERAGE;
1472
+ var REACT_NATIVE_ROOT_EXPORT_STRICT_COVERAGE;
1217
1473
  var init_react_native_root_export_coverage = __esm({
1218
1474
  "../compat/src/generated/react-native-root-export-coverage.ts"() {
1219
1475
  "use strict";
1220
- REACT_NATIVE_ROOT_EXPORT_WILL_IT_WORK_COVERAGE = 0.99;
1221
1476
  REACT_NATIVE_ROOT_EXPORT_STRICT_COVERAGE = 0.765;
1222
1477
  }
1223
1478
  });
@@ -1385,7 +1640,7 @@ var init_supported_native_packages = __esm({
1385
1640
  "expo-document-picker",
1386
1641
  // preset+coverage
1387
1642
  "expo-file-system",
1388
- // coverage
1643
+ // preset+coverage
1389
1644
  "expo-font",
1390
1645
  // preset+coverage
1391
1646
  "expo-gl",
@@ -1493,7 +1748,7 @@ var init_supported_native_packages = __esm({
1493
1748
  "posthog-react-native-session-replay",
1494
1749
  // preset+coverage
1495
1750
  "react-native",
1496
- // preset+visual-proof+coverage
1751
+ // preset+visual-proof
1497
1752
  "react-native-actions-shortcuts",
1498
1753
  // coverage
1499
1754
  "react-native-adjust",
@@ -1539,7 +1794,7 @@ var init_supported_native_packages = __esm({
1539
1794
  "react-native-fs",
1540
1795
  // coverage
1541
1796
  "react-native-gesture-handler",
1542
- // preset+visual-proof+coverage
1797
+ // preset
1543
1798
  "react-native-get-device-locale",
1544
1799
  // coverage
1545
1800
  "react-native-get-location",
@@ -1617,7 +1872,7 @@ var init_supported_native_packages = __esm({
1617
1872
  "react-native-randombytes",
1618
1873
  // coverage
1619
1874
  "react-native-reanimated",
1620
- // preset+visual-proof+coverage
1875
+ // preset+visual-proof
1621
1876
  "react-native-restart",
1622
1877
  // coverage
1623
1878
  "react-native-restart-newarch",
@@ -1629,7 +1884,7 @@ var init_supported_native_packages = __esm({
1629
1884
  "react-native-screen-corner-radius",
1630
1885
  // coverage
1631
1886
  "react-native-screens",
1632
- // preset+visual-proof+coverage
1887
+ // preset+visual-proof
1633
1888
  "react-native-securerandom",
1634
1889
  // coverage
1635
1890
  "react-native-settings",
@@ -1743,6 +1998,7 @@ var init_registry = __esm({
1743
1998
  "../compat/src/registry.ts"() {
1744
1999
  "use strict";
1745
2000
  init_capability_inventory_coverage();
2001
+ init_capability_outcomes2();
1746
2002
  init_react_native_root_export_coverage();
1747
2003
  init_react_native_webview_coverage();
1748
2004
  init_unsupported_packages();
@@ -1777,14 +2033,12 @@ var init_registry = __esm({
1777
2033
  versions: [
1778
2034
  {
1779
2035
  range: ">=0.86.0 <0.87.0",
1780
- // generated from audited RN 0.86.2 root exports. coverage answers whether
1781
- // measured real-app use works; strictCoverage gives every export equal
1782
- // weight. regenerate both with
1783
- // `bun scripts/measure-capability-usage.ts --root-exports`. neither changes
1784
- // proofCoverage, which measures how much proof exists.
1785
- coverage: REACT_NATIVE_ROOT_EXPORT_WILL_IT_WORK_COVERAGE,
2036
+ // outcomes measure declared scenarios; strictCoverage remains an
2037
+ // independent equal-export implementation estimate.
2038
+ coverage: CAPABILITY_PACKAGE_OUTCOMES["react-native"].byPlatform.ios.compatibility,
1786
2039
  strictCoverage: REACT_NATIVE_ROOT_EXPORT_STRICT_COVERAGE,
1787
- coverageSource: "estimated",
2040
+ coverageSource: "measured",
2041
+ outcomes: CAPABILITY_PACKAGE_OUTCOMES["react-native"],
1788
2042
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native"],
1789
2043
  note: "React Native 0.86 root surface with useful core rendering, input, scrolling, animation, list, platform, and native-module behavior",
1790
2044
  working: "all 99 React Native 0.86.2 public runtime root export names; flex and absolute layout, text shaping and wrapping, image loading and resize modes, touch and responder routing, controlled text input and keyboard presentation, vertical and horizontal scrolling with paging/snapping/sticky and maintained content, windowed/inverted/horizontal lists, common Animated graphs and composition, core LayoutAnimation create/update/delete geometry, alerts and action sheets, live platform/dimension/appearance state, and explicit native-module lookup",
@@ -1805,8 +2059,9 @@ var init_registry = __esm({
1805
2059
  },
1806
2060
  {
1807
2061
  range: ">=4.0.0 <5.0.0",
1808
- coverage: 0.97,
1809
- coverageSource: "estimated",
2062
+ coverage: CAPABILITY_PACKAGE_OUTCOMES["react-native-reanimated"].byPlatform.ios.compatibility,
2063
+ coverageSource: "measured",
2064
+ outcomes: CAPABILITY_PACKAGE_OUTCOMES["react-native-reanimated"],
1810
2065
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-reanimated"],
1811
2066
  note: "core animations, gestures, scroll, layout transitions, common CSS opacity, transform, and processed-color transitions and keyframes, keyboard, sensors, reduced motion, native view property reads, and direct static style snapshots",
1812
2067
  working: "useSharedValue, useAnimatedStyle/Props/Reaction, useDerivedValue, useAnimatedScrollHandler, useScrollViewOffset, useFrameCallback, useAnimatedRef, useAnimatedKeyboard, useAnimatedSensor, useReducedMotion, entering/exiting/layout transitions, css/createCSSAnimatedComponent with cubicBezier/linear/steps timing for common opacity and transform transitions, opacity and transform keyframes with retained forwards fill, withTiming/Spring/Decay/Delay/Sequence/Repeat/Clamp, interpolate, interpolateColor, runOnJS/UI, measure, scrollTo, getViewProp (layout, opacity, zIndex, backgroundColor, boxShadow), direct setViewStyle snapshots, Easing, createAnimatedComponent, Animated.View/Text/Image/ScrollView/FlatList",
@@ -1822,12 +2077,12 @@ var init_registry = __esm({
1822
2077
  { range: ">=2.0.0 <2.30.0", coverage: 0.7, note: "tap, pan, long press" },
1823
2078
  {
1824
2079
  range: ">=2.30.0 <3.0.0",
1825
- coverage: 0.9,
1826
- coverageSource: "estimated",
2080
+ coverage: CAPABILITY_PACKAGE_OUTCOMES["react-native-gesture-handler"].byPlatform.ios.compatibility,
2081
+ coverageSource: "measured",
2082
+ outcomes: CAPABILITY_PACKAGE_OUTCOMES["react-native-gesture-handler"],
1827
2083
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-gesture-handler"],
1828
2084
  note: "tap, pan, pinch, rotation, fling, long press, race, manual, simultaneous, force touch unavailable-hardware parity",
1829
- working: "GestureDetector, Gesture.Tap/Pan/Pinch/Rotation/Fling/LongPress/ForceTouch/Manual/Race/Simultaneous/Exclusive/Hover, ForceTouchGestureHandler unavailable-hardware fallback (children render, forceTouchAvailable false, no force events), simultaneousWithExternalGesture/requireExternalGestureToFail/blocksExternalGesture, ScrollView/FlatList, Switch/RefreshControl, Pressable/Text, Touchables, BaseButton/RawButton/RectButton/BorderlessButton/PureNativeButton, Swipeable, ReanimatedSwipeable, DrawerLayout (the upstream component running on this seam: renderNavigationView, drawerPosition/drawerType/drawerWidth/edgeWidth, openDrawer/closeDrawer, edge-swipe drag, onDrawerOpen/onDrawerClose/onDrawerStateChanged), GestureHandlerRootView, createNativeWrapper, gestureHandlerRootHOC, PointerType/MouseButton/HoverEffect exports, velocity tracking, activeOffsets, multi-tap",
1830
- missing: "Force Touch recognition is unavailable because browser pointer input has no pressure signal; both public APIs expose the upstream unavailable-hardware behavior instead of inventing force events"
2085
+ working: "GestureDetector, Gesture.Tap/Pan/Pinch/Rotation/Fling/LongPress/ForceTouch/Manual/Race/Simultaneous/Exclusive/Hover, ForceTouchGestureHandler unavailable-hardware fallback (children render, forceTouchAvailable false, no force events), simultaneousWithExternalGesture/requireExternalGestureToFail/blocksExternalGesture, ScrollView/FlatList, Switch/RefreshControl, Pressable/Text, Touchables, BaseButton/RawButton/RectButton/BorderlessButton/PureNativeButton, Swipeable, ReanimatedSwipeable, DrawerLayout (the upstream component running on this seam: renderNavigationView, drawerPosition/drawerType/drawerWidth/edgeWidth, openDrawer/closeDrawer, edge-swipe drag, onDrawerOpen/onDrawerClose/onDrawerStateChanged), GestureHandlerRootView, createNativeWrapper, gestureHandlerRootHOC, PointerType/MouseButton/HoverEffect exports, velocity tracking, activeOffsets, multi-tap"
1831
2086
  }
1832
2087
  ]
1833
2088
  },
@@ -1839,12 +2094,13 @@ var init_registry = __esm({
1839
2094
  { range: ">=3.0.0 <4.0.0", coverage: 0.6, note: "basic screen container" },
1840
2095
  {
1841
2096
  range: ">=4.0.0",
1842
- coverage: 0.9,
1843
- coverageSource: "estimated",
2097
+ coverage: CAPABILITY_PACKAGE_OUTCOMES["react-native-screens"].byPlatform.ios.compatibility,
2098
+ coverageSource: "measured",
2099
+ outcomes: CAPABILITY_PACKAGE_OUTCOMES["react-native-screens"],
1844
2100
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-screens"],
1845
2101
  note: "screen container, stack, header config, search bar, navigation props",
1846
- working: "Screen, ScreenContainer, ScreenStack, enableFreeze/freezeEnabled with delayed React freeze, Android modal/pageSheet push fallback, Android statusBarHidden/statusBarStyle/navigationBarHidden traits, push/pop slide, replaceAnimation push/pop direction, zoom/fade/fade_from_bottom transitions, edge swipe-back, parallax behind-screen, large title collapse, header (back button, inline/large title, custom left/center/right/search bar subviews, native header bar buttons/menus/badges, crossfade), formSheet custom initial detents/corner radius/grabber/undimmed range and stacked sheets, useHeaderHeight, useTransitionProgress, FullWindowOverlay, SearchBar, Tabs.Host/Screen, lifecycle callbacks (onAppear/onDisappear/onWillAppear/onWillDisappear), onDismissed",
1847
- missing: "interactive drag between formSheet detents, integrated search bar placements"
2102
+ working: "Screen, ScreenContainer, ScreenStack, enableFreeze/freezeEnabled with delayed React freeze, Android modal/pageSheet push fallback, Android statusBarHidden/statusBarStyle/navigationBarHidden traits, push/pop slide, replaceAnimation push/pop direction, zoom/fade/fade_from_bottom transitions, edge swipe-back, parallax behind-screen, large title collapse, header (back button, inline/large title, custom left/center/right/search bar subviews, native header bar buttons/menus/badges, crossfade), formSheet custom initial detents/corner radius/grabber/undimmed range and stacked sheets, useHeaderHeight, useTransitionProgress, FullWindowOverlay, SearchBar with stacked and iOS 26 automatic/inline/integrated/integratedCentered/integratedButton toolbar placement, Tabs.Host/Screen, lifecycle callbacks (onAppear/onDisappear/onWillAppear/onWillDisappear), onDismissed",
2103
+ missing: "interactive drag between formSheet detents"
1848
2104
  }
1849
2105
  ]
1850
2106
  },
@@ -1869,12 +2125,13 @@ var init_registry = __esm({
1869
2125
  versions: [
1870
2126
  {
1871
2127
  range: ">=13.0.0",
1872
- coverage: 0.85,
1873
- coverageSource: "estimated",
2128
+ coverage: CAPABILITY_PACKAGE_OUTCOMES["react-native-svg"].byPlatform.ios.compatibility,
2129
+ coverageSource: "measured",
2130
+ outcomes: CAPABILITY_PACKAGE_OUTCOMES["react-native-svg"],
1874
2131
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-svg"],
1875
- note: "full CanvasKit rendering for shapes/text/XML; SVG filter elements skipped",
1876
- working: "Svg, Path, Circle, Rect, Line, Ellipse, Polygon, Polyline, G, Text, TSpan, Defs, LinearGradient and RadialGradient with objectBoundingBox/userSpaceOnUse coordinates, focal points and gradientTransform, Stop, SvgXml, SvgUri, SvgFromXml, SvgCss, shape transforms, fill/stroke/opacity/dasharray, currentColor, viewBox scaling",
1877
- missing: "SVG filter primitives (Filter, FeBlend, FeColorMatrix, FeGaussianBlur, FeComposite, etc) are skipped; ClipPath, Mask, Use, Pattern, Symbol, Marker, ForeignObject, TextPath, and Image are also skipped by the renderer"
2132
+ note: "full CanvasKit rendering for shapes, text, XML, gradients, references, masks, clipping, and images; SVG filter elements skipped",
2133
+ working: "Svg, Path, Circle, Rect, Line, Ellipse, Polygon, Polyline, G, Text, TSpan, Defs, LinearGradient and RadialGradient with objectBoundingBox/userSpaceOnUse coordinates, focal points and gradientTransform, Stop, Mask, ClipPath, Image, Use and Symbol references, SvgXml, SvgUri, SvgAst, SvgFromXml, SvgCss, parse, fetchText, camelCase, shape transforms, fill/stroke/opacity/dasharray, currentColor, viewBox scaling",
2134
+ missing: "SVG filter primitives (Filter, FeBlend, FeColorMatrix, FeGaussianBlur, FeComposite, etc), Pattern, Marker, ForeignObject, and TextPath are skipped by the renderer"
1878
2135
  }
1879
2136
  ]
1880
2137
  },
@@ -1986,8 +2243,9 @@ var init_registry = __esm({
1986
2243
  versions: [
1987
2244
  {
1988
2245
  range: ">=1.0.0",
1989
- coverage: 0.88,
1990
- coverageSource: "estimated",
2246
+ coverage: CAPABILITY_PACKAGE_OUTCOMES["react-native-keyboard-controller"].byPlatform.ios.compatibility,
2247
+ coverageSource: "measured",
2248
+ outcomes: CAPABILITY_PACKAGE_OUTCOMES["react-native-keyboard-controller"],
1991
2249
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-keyboard-controller"],
1992
2250
  note: "native bindings stubbed (KeyboardControllerNative, KeyboardEvents, FocusedInputEvents, WindowDimensionsEvents, KeyboardControllerView + sibling native views); upstream pure-JS components, hooks, animated module, and KeyboardAvoidingView resolve from node_modules unchanged",
1993
2251
  working: "every upstream JS export runs through reanimated worklets; Android KeyboardGestureArea drives the existing keyboard owner through drag progress, velocity/distance settling, cancellation, focus retention, and cleanup; supported exports include KeyboardProvider, KeyboardAvoidingView, KeyboardStickyView, KeyboardAwareScrollView, KeyboardToolbar, KeyboardGestureArea, useReanimatedKeyboardAnimation, useKeyboardAnimation, useKeyboardHandler, useGenericKeyboardHandler, useKeyboardController, useKeyboardState, useKeyboardContext, useReanimatedFocusedInput, useFocusedInputHandler, useResizeMode, useWindowDimensions, KeyboardEvents, FocusedInputEvents, WindowDimensionsEvents resize events, KeyboardController (dismiss/setFocusTo/isVisible/state/preload/setInputMode/setDefaultMode), KeyboardControllerView, OverKeyboardView, KeyboardBackgroundView, KeyboardExtender, ClippingScrollView, KeyboardToolbarGroupView, and AndroidSoftInputModes",
@@ -14044,6 +14302,8 @@ function matchCompatVersion(entry, declaredVersion) {
14044
14302
  return {
14045
14303
  ...resolution,
14046
14304
  coverage: selected.coverage,
14305
+ coverageSource: selected.coverageSource ?? "estimated",
14306
+ ...selected.outcomes ? { outcomes: selected.outcomes } : {},
14047
14307
  note: selected.note,
14048
14308
  ...selected.working ? { working: selected.working } : {},
14049
14309
  ...selected.missing ? { missing: selected.missing } : {}
@@ -14070,6 +14330,7 @@ function rnxSupportForPackage(name2, version, data) {
14070
14330
  return {
14071
14331
  level: "unsupported",
14072
14332
  coverage: 0,
14333
+ coverageSource: "estimated",
14073
14334
  note: unsupported?.note ?? UNSUPPORTED_NATIVE_PACKAGE_NOTE,
14074
14335
  recovery: unsupported?.recovery ?? null,
14075
14336
  source: "unsupported-list"
@@ -14096,9 +14357,12 @@ function rnxSupportForPackage(name2, version, data) {
14096
14357
  source: "compat-registry"
14097
14358
  };
14098
14359
  }
14360
+ const coverage = match.coverageSource === "measured" ? match.outcomes?.byPlatform.ios.compatibility ?? null : match.coverage;
14099
14361
  return {
14100
- level: match.coverage >= 0.9 ? "full" : "partial",
14101
- coverage: match.coverage,
14362
+ level: coverage === null ? "stubbed" : coverage >= 0.9 ? "full" : "partial",
14363
+ coverage,
14364
+ coverageSource: match.coverageSource,
14365
+ ...match.outcomes ? { outcomes: match.outcomes } : {},
14102
14366
  note: match.note,
14103
14367
  ...match.working ? { working: match.working } : {},
14104
14368
  ...match.missing ? { missing: match.missing } : {},
@@ -14106,6 +14370,20 @@ function rnxSupportForPackage(name2, version, data) {
14106
14370
  source: "compat-registry"
14107
14371
  };
14108
14372
  }
14373
+ function summarizeScanPackages(packages) {
14374
+ return {
14375
+ ...aggregateCompatibilityOutcomes(
14376
+ packages.filter((pkg) => pkg.status !== "not-relevant").map((pkg) => ({
14377
+ weight: 1,
14378
+ assessment: pkg.rnx.outcomes?.byPlatform.ios ?? null,
14379
+ estimate: pkg.coverage,
14380
+ source: pkg.rnx.coverageSource === "measured" ? "measured" : pkg.coverage === null ? "unassessed" : "estimated"
14381
+ }))
14382
+ ),
14383
+ platform: "ios",
14384
+ weighting: "dependency-usage"
14385
+ };
14386
+ }
14109
14387
  function detectFramework(deps) {
14110
14388
  if (deps["one"]) return "one";
14111
14389
  if (deps["expo"]) return "expo";
@@ -14145,7 +14423,7 @@ function scanDepsWithData(pkg, data) {
14145
14423
  packages.push({
14146
14424
  name: name2,
14147
14425
  version,
14148
- coverage: 0.3,
14426
+ coverage: null,
14149
14427
  status: "auto-stub",
14150
14428
  note: "not yet verified; it may work through rnx's generic native seam",
14151
14429
  rnx
@@ -14156,7 +14434,7 @@ function scanDepsWithData(pkg, data) {
14156
14434
  packages.push({
14157
14435
  name: name2,
14158
14436
  version,
14159
- coverage: 0.3,
14437
+ coverage: null,
14160
14438
  status: "auto-stub",
14161
14439
  note: rnx.note ?? "not yet verified for this version",
14162
14440
  rnx
@@ -14167,27 +14445,27 @@ function scanDepsWithData(pkg, data) {
14167
14445
  packages.push({
14168
14446
  name: name2,
14169
14447
  version,
14170
- coverage: rnx.coverage ?? 0.3,
14448
+ coverage: rnx.coverage,
14171
14449
  status: buildOnly ? "not-relevant" : rnx.level === "full" ? "full" : "partial",
14172
14450
  note: rnx.note ?? "",
14173
14451
  rnx
14174
14452
  });
14175
14453
  }
14176
- const scored = packages.filter((p) => p.status !== "not-relevant");
14177
- const total = scored.length;
14178
- const overallScore = total === 0 ? 1 : scored.reduce((sum, p) => sum + p.coverage, 0) / total;
14454
+ const scoreSummary = summarizeScanPackages(packages);
14179
14455
  return {
14180
14456
  projectName: pkg.name || "unknown",
14181
14457
  rnVersion,
14182
14458
  framework,
14183
14459
  packages,
14184
- overallScore: Math.round(overallScore * 100) / 100
14460
+ overallScore: scoreSummary.compatibility,
14461
+ scoreSummary
14185
14462
  };
14186
14463
  }
14187
14464
  var NON_RN_PACKAGES;
14188
14465
  var init_scan = __esm({
14189
14466
  "../compat/src/scan.ts"() {
14190
14467
  "use strict";
14468
+ init_capability_outcomes();
14191
14469
  init_native_evidence();
14192
14470
  init_registry();
14193
14471
  init_unsupported_packages();
@@ -14252,14 +14530,25 @@ function countScanResults(result) {
14252
14530
  }
14253
14531
  function formatScanCounts(result) {
14254
14532
  const counts = countScanResults(result);
14255
- return [
14533
+ const countsText = [
14256
14534
  `${counts.supported} supported`,
14257
14535
  `${counts.partial} partial`,
14258
14536
  `${counts.unsupported} unsupported`,
14259
14537
  `${counts.notYetVerified} not yet verified`
14260
14538
  ].join(", ");
14539
+ const summary = result.scoreSummary;
14540
+ const score = summary.compatibility === null ? "unassessed" : `${Math.round(summary.compatibility * 100)}% compatibility (${summary.source})`;
14541
+ return `${countsText}; ${score}; iOS measured: ${formatCompatibilityPercent(summary.assessed * 100)}% assessed dependency usage; ${Math.round(summary.estimated * 100)}% estimated dependency usage`;
14261
14542
  }
14262
14543
  function formatPackageStatus(pkg) {
14544
+ if (pkg.rnx.coverageSource === "measured") {
14545
+ const outcome = pkg.rnx.outcomes?.byPlatform.ios;
14546
+ const score = pkg.coverage === null ? "unassessed" : `${Math.round(pkg.coverage * 100)}% compatibility`;
14547
+ return `iOS measured: ${score}, ${formatCompatibilityPercent((outcome?.assessed ?? 0) * 100)}% assessed usage`;
14548
+ }
14549
+ if (pkg.coverage !== null && pkg.status !== "not-relevant") {
14550
+ return `${pkg.status === "full" ? "supported" : pkg.status} (estimated ${Math.round(pkg.coverage * 100)}%)`;
14551
+ }
14263
14552
  switch (pkg.status) {
14264
14553
  case "full":
14265
14554
  return "supported";
@@ -14276,7 +14565,7 @@ function formatPackageStatus(pkg) {
14276
14565
  function formatDetailedScanLines(result) {
14277
14566
  const lines = [];
14278
14567
  const actionable = result.packages.filter(
14279
- (pkg) => pkg.status === "partial" || pkg.status === "unsupported"
14568
+ (pkg) => pkg.status === "partial" || pkg.status === "unsupported" || pkg.status === "full" && pkg.rnx.coverageSource === "measured"
14280
14569
  );
14281
14570
  for (const pkg of actionable) {
14282
14571
  lines.push(`${formatPackageStatus(pkg)}: ${pkg.name}@${pkg.version} \u2014 ${pkg.note}`);
@@ -14285,7 +14574,9 @@ function formatDetailedScanLines(result) {
14285
14574
  if (unknown.length > 0) {
14286
14575
  lines.push("Not yet verified:");
14287
14576
  for (const pkg of unknown) {
14288
- lines.push(` ${pkg.name}@${pkg.version} \u2014 ${pkg.note}`);
14577
+ lines.push(
14578
+ ` ${pkg.name}@${pkg.version} \u2014 ${formatPackageStatus(pkg)}; ${pkg.note}`
14579
+ );
14289
14580
  }
14290
14581
  lines.push(
14291
14582
  "SootSim may still work. The simulator will report a concrete runtime error if it finds a gap."
@@ -14297,7 +14588,8 @@ var COMPAT_RESULT_CAVEAT;
14297
14588
  var init_scan_summary = __esm({
14298
14589
  "../compat/src/scan-summary.ts"() {
14299
14590
  "use strict";
14300
- COMPAT_RESULT_CAVEAT = "This is a dependency-level estimate, not a guarantee that every app path works.";
14591
+ init_capability_outcomes();
14592
+ COMPAT_RESULT_CAVEAT = "Measured iOS results cover assessed API scenarios. Legacy contributions are estimates; unassessed usage remains unknown. App paths may exercise additional behavior.";
14301
14593
  }
14302
14594
  });
14303
14595
 
@@ -15724,6 +16016,7 @@ __export(home_paths_exports, {
15724
16016
  profilesDir: () => profilesDir,
15725
16017
  readActiveRuntime: () => readActiveRuntime,
15726
16018
  readDaemonLockfile: () => readDaemonLockfile,
16019
+ readDefaultBox: () => readDefaultBox,
15727
16020
  readDevBridgeLockfiles: () => readDevBridgeLockfiles,
15728
16021
  readLiveRuntimeVersions: () => readLiveRuntimeVersions,
15729
16022
  readOrCreateAnonymousId: () => readOrCreateAnonymousId,
@@ -15739,6 +16032,7 @@ __export(home_paths_exports, {
15739
16032
  shouldSkipPersistentDaemon: () => shouldSkipPersistentDaemon,
15740
16033
  writeActiveRuntime: () => writeActiveRuntime,
15741
16034
  writeDaemonLockfile: () => writeDaemonLockfile,
16035
+ writeDefaultBox: () => writeDefaultBox,
15742
16036
  writeDevBridgeLockfile: () => writeDevBridgeLockfile,
15743
16037
  writeOnboardingPreferences: () => writeOnboardingPreferences,
15744
16038
  writePrivacyPreferences: () => writePrivacyPreferences,
@@ -15888,6 +16182,18 @@ function readOrCreateAnonymousId() {
15888
16182
  writeSharedConfig({ anonymousId: created });
15889
16183
  return created;
15890
16184
  }
16185
+ function readDefaultBox() {
16186
+ const stored = readSharedConfig().defaultBox;
16187
+ if (typeof stored !== "object" || stored === null) return null;
16188
+ if (!("boxId" in stored) || typeof stored.boxId !== "string" || !stored.boxId) {
16189
+ return null;
16190
+ }
16191
+ const name2 = "name" in stored && typeof stored.name === "string" ? stored.name : null;
16192
+ return { boxId: stored.boxId, name: name2 };
16193
+ }
16194
+ function writeDefaultBox(box) {
16195
+ writeSharedConfig({ defaultBox: box });
16196
+ }
15891
16197
  function runtimeUpgradeNoticePath() {
15892
16198
  return import_node_path4.default.join(rnxHomeDir(), "runtime-upgraded.json");
15893
16199
  }
@@ -21740,67 +22046,67 @@ var init_stub_manifest = __esm({
21740
22046
  specifier: "react-native/Libraries/Pressability/usePressability",
21741
22047
  stubFile: "rn-libraries/usePressability.ts",
21742
22048
  runtimeTier: "core",
21743
- buildResolvers: ["vite"]
22049
+ buildResolvers: ["vite", "dep-prebundle"]
21744
22050
  },
21745
22051
  pressability: {
21746
22052
  specifier: "react-native/Libraries/Pressability/Pressability",
21747
22053
  stubFile: "rn-libraries/Pressability.ts",
21748
22054
  runtimeTier: "core",
21749
- buildResolvers: ["vite"]
22055
+ buildResolvers: ["vite", "dep-prebundle"]
21750
22056
  },
21751
22057
  pressabilityDebug: {
21752
22058
  specifier: "react-native/Libraries/Pressability/PressabilityDebug",
21753
22059
  stubFile: "rn-libraries/PressabilityDebug.ts",
21754
22060
  runtimeTier: "core",
21755
- buildResolvers: ["vite"]
22061
+ buildResolvers: ["vite", "dep-prebundle"]
21756
22062
  },
21757
22063
  reactFabric: {
21758
22064
  specifier: "react-native/Libraries/Renderer/shims/ReactFabric",
21759
22065
  stubFile: "rn-libraries/ReactFabric.ts",
21760
22066
  runtimeTier: "core",
21761
- buildResolvers: ["vite"]
22067
+ buildResolvers: ["vite", "dep-prebundle"]
21762
22068
  },
21763
22069
  reactNativeRenderer: {
21764
22070
  specifier: "react-native/Libraries/Renderer/shims/ReactNative",
21765
22071
  stubFile: "rn-libraries/ReactNative.ts",
21766
22072
  runtimeTier: "core",
21767
- buildResolvers: ["vite"]
22073
+ buildResolvers: ["vite", "dep-prebundle"]
21768
22074
  },
21769
22075
  reactNativeViewConfigRegistry: {
21770
22076
  specifier: "react-native/Libraries/Renderer/shims/ReactNativeViewConfigRegistry",
21771
22077
  stubFile: "rn-libraries/ReactNativeViewConfigRegistry.ts",
21772
22078
  runtimeTier: "core",
21773
- buildResolvers: ["vite"]
22079
+ buildResolvers: ["vite", "dep-prebundle"]
21774
22080
  },
21775
22081
  appContainer: {
21776
22082
  specifier: "react-native/Libraries/ReactNative/AppContainer",
21777
22083
  stubFile: "rn-libraries/AppContainer.ts",
21778
22084
  runtimeTier: "core",
21779
- buildResolvers: ["vite"]
22085
+ buildResolvers: ["vite", "dep-prebundle"]
21780
22086
  },
21781
22087
  appRegistry: {
21782
22088
  specifier: "react-native/Libraries/ReactNative/AppRegistry",
21783
22089
  stubFile: "rn-libraries/AppRegistry.ts",
21784
22090
  runtimeTier: "core",
21785
- buildResolvers: ["vite"]
22091
+ buildResolvers: ["vite", "dep-prebundle"]
21786
22092
  },
21787
22093
  rendererImplementation: {
21788
22094
  specifier: "react-native/Libraries/ReactNative/RendererImplementation",
21789
22095
  stubFile: "rn-libraries/RendererImplementation.ts",
21790
22096
  runtimeTier: "core",
21791
- buildResolvers: ["vite"]
22097
+ buildResolvers: ["vite", "dep-prebundle"]
21792
22098
  },
21793
22099
  rendererProxy: {
21794
22100
  specifier: "react-native/Libraries/ReactNative/RendererProxy",
21795
22101
  stubFile: "rn-libraries/RendererProxy.ts",
21796
22102
  runtimeTier: "core",
21797
- buildResolvers: ["vite"]
22103
+ buildResolvers: ["vite", "dep-prebundle"]
21798
22104
  },
21799
22105
  getDevServer: {
21800
22106
  specifier: "react-native/Libraries/Core/Devtools/getDevServer",
21801
22107
  stubFile: "rn-libraries/getDevServer.ts",
21802
22108
  runtimeTier: "core",
21803
- buildResolvers: ["vite"]
22109
+ buildResolvers: ["vite", "dep-prebundle"]
21804
22110
  },
21805
22111
  codegenNativeCommands: {
21806
22112
  specifier: "react-native/Libraries/Utilities/codegenNativeCommands",
@@ -21818,19 +22124,19 @@ var init_stub_manifest = __esm({
21818
22124
  specifier: "react-native/Libraries/Image/resolveAssetSource",
21819
22125
  stubFile: "rn-libraries/resolveAssetSource.ts",
21820
22126
  runtimeTier: "core",
21821
- buildResolvers: ["vite"]
22127
+ buildResolvers: ["vite", "dep-prebundle"]
21822
22128
  },
21823
22129
  viewConfigIgnore: {
21824
22130
  specifier: "react-native/Libraries/NativeComponent/ViewConfigIgnore",
21825
22131
  stubFile: "rn-libraries/ViewConfigIgnore.ts",
21826
22132
  runtimeTier: "core",
21827
- buildResolvers: ["vite"]
22133
+ buildResolvers: ["vite", "dep-prebundle"]
21828
22134
  },
21829
22135
  nativeComponentRegistry: {
21830
22136
  specifier: "react-native/Libraries/NativeComponent/NativeComponentRegistry",
21831
22137
  stubFile: "rn-libraries/NativeComponentRegistry.ts",
21832
22138
  runtimeTier: "core",
21833
- buildResolvers: ["vite"]
22139
+ buildResolvers: ["vite", "dep-prebundle"]
21834
22140
  },
21835
22141
  // RN TurboModule spec for SourceCode. third-party libraries import
21836
22142
  // this directly to read `scriptURL`; without the deep-path stub the
@@ -21840,19 +22146,19 @@ var init_stub_manifest = __esm({
21840
22146
  specifier: "react-native/src/private/specs/modules/NativeSourceCode",
21841
22147
  stubFile: "rn-libraries/NativeSourceCode.ts",
21842
22148
  runtimeTier: "core",
21843
- buildResolvers: ["vite"]
22149
+ buildResolvers: ["vite", "dep-prebundle"]
21844
22150
  },
21845
22151
  nativeSourceCodeDeprecated: {
21846
22152
  specifier: "react-native/src/private/specs_DEPRECATED/modules/NativeSourceCode",
21847
22153
  stubFile: "rn-libraries/NativeSourceCode.ts",
21848
22154
  runtimeTier: "core",
21849
- buildResolvers: ["vite"]
22155
+ buildResolvers: ["vite", "dep-prebundle"]
21850
22156
  },
21851
22157
  nativeSourceCodeLibraries: {
21852
22158
  specifier: "react-native/Libraries/NativeModules/specs/NativeSourceCode",
21853
22159
  stubFile: "rn-libraries/NativeSourceCode.ts",
21854
22160
  runtimeTier: "core",
21855
- buildResolvers: ["vite"]
22161
+ buildResolvers: ["vite", "dep-prebundle"]
21856
22162
  },
21857
22163
  // RN TurboModule spec for the Android StatusBar. libraries import it
21858
22164
  // directly and `Object.assign` over its default export; the shim namespace
@@ -21861,13 +22167,13 @@ var init_stub_manifest = __esm({
21861
22167
  specifier: "react-native/Libraries/Components/StatusBar/NativeStatusBarManagerAndroid",
21862
22168
  stubFile: "rn-libraries/NativeStatusBarManagerAndroid.ts",
21863
22169
  runtimeTier: "core",
21864
- buildResolvers: ["vite"]
22170
+ buildResolvers: ["vite", "dep-prebundle"]
21865
22171
  },
21866
22172
  nativeStatusBarManagerAndroidDeprecated: {
21867
22173
  specifier: "react-native/src/private/specs_DEPRECATED/modules/NativeStatusBarManagerAndroid",
21868
22174
  stubFile: "rn-libraries/NativeStatusBarManagerAndroid.ts",
21869
22175
  runtimeTier: "core",
21870
- buildResolvers: ["vite"]
22176
+ buildResolvers: ["vite", "dep-prebundle"]
21871
22177
  }
21872
22178
  };
21873
22179
  }
@@ -22726,6 +23032,7 @@ function normalizeCloudOrigin(source) {
22726
23032
  function createCloudSession(input) {
22727
23033
  const session = {
22728
23034
  version: CLOUD_SESSION_VERSION,
23035
+ service: "sim",
22729
23036
  boxId: input.boxId.trim(),
22730
23037
  boxToken: input.boxToken,
22731
23038
  simId: input.simId.trim(),
@@ -22738,6 +23045,19 @@ function createCloudSession(input) {
22738
23045
  }
22739
23046
  return session;
22740
23047
  }
23048
+ function createCloudBoxSession(input) {
23049
+ const session = {
23050
+ version: CLOUD_SESSION_VERSION,
23051
+ service: "box",
23052
+ boxId: input.boxId.trim(),
23053
+ boxToken: input.boxToken,
23054
+ apiOrigin: normalizeCloudOrigin(input.apiOrigin.trim())
23055
+ };
23056
+ if (!session.boxId || !session.boxToken) {
23057
+ throw new Error("cloud box session requires a box, an origin, and a box token");
23058
+ }
23059
+ return session;
23060
+ }
22741
23061
  function parseCloudSession(encoded) {
22742
23062
  const value = encoded.trim();
22743
23063
  if (!value || value.length > MAX_ENCODED_SESSION_BYTES || !/^[A-Za-z0-9_-]+$/.test(value)) {
@@ -22758,14 +23078,20 @@ function parseCloudSession(encoded) {
22758
23078
  }
22759
23079
  const boxId = parsed.boxId;
22760
23080
  const boxToken = parsed.boxToken;
22761
- const simId = parsed.simId;
22762
23081
  const apiOrigin = parsed.apiOrigin;
22763
- const claimId = parsed.claimId;
22764
- const token = parsed.token;
22765
- if (typeof boxId !== "string" || typeof boxToken !== "string" || typeof simId !== "string" || typeof apiOrigin !== "string" || typeof claimId !== "string" || typeof token !== "string") {
23082
+ if (typeof boxId !== "string" || typeof boxToken !== "string" || typeof apiOrigin !== "string") {
22766
23083
  throw new Error(`${RNX_CLOUD_SESSION_ENV} is invalid`);
22767
23084
  }
22768
23085
  try {
23086
+ if (parsed.service === "box") {
23087
+ return createCloudBoxSession({ boxId, boxToken, apiOrigin });
23088
+ }
23089
+ const simId = parsed.simId;
23090
+ const claimId = parsed.claimId;
23091
+ const token = parsed.token;
23092
+ if (parsed.service !== "sim" || typeof simId !== "string" || typeof claimId !== "string" || typeof token !== "string") {
23093
+ throw new Error("unreadable cloud session");
23094
+ }
22769
23095
  return createCloudSession({ boxId, boxToken, simId, apiOrigin, claimId, token });
22770
23096
  } catch {
22771
23097
  throw new Error(`${RNX_CLOUD_SESSION_ENV} is invalid`);
@@ -22780,7 +23106,7 @@ var init_cloud_session = __esm({
22780
23106
  "cli/cloud-session.ts"() {
22781
23107
  "use strict";
22782
23108
  init_backend_origin();
22783
- CLOUD_SESSION_VERSION = 2;
23109
+ CLOUD_SESSION_VERSION = 3;
22784
23110
  MAX_ENCODED_SESSION_BYTES = 32 * 1024;
22785
23111
  RNX_CLOUD_SESSION_ENV = "RNX_CLOUD_SESSION";
22786
23112
  RNX_SHELL_UPDATE_PREFIX = "__RNX_SHELL_UPDATE_V1__";
@@ -23027,7 +23353,8 @@ function distinctByContent(directory, options) {
23027
23353
  return [...byContent.values()];
23028
23354
  }
23029
23355
  function placeMetroDescriptor(listing, descriptor) {
23030
- const perScale = descriptor.scales.map(
23356
+ const scales = [...new Set(descriptor.scales)];
23357
+ const perScale = scales.map(
23031
23358
  (scale) => distinctByContent(
23032
23359
  listing.directory,
23033
23360
  resolveMetroIosAssetDestFiles(listing.files, descriptor, scale)
@@ -23035,7 +23362,7 @@ function placeMetroDescriptor(listing, descriptor) {
23035
23362
  );
23036
23363
  const files = /* @__PURE__ */ new Map();
23037
23364
  const ambiguous = [];
23038
- descriptor.scales.forEach((scale, index) => {
23365
+ scales.forEach((scale, index) => {
23039
23366
  const options = perScale[index] ?? [];
23040
23367
  if (options.length === 1 && options[0]) files.set(scale, options[0]);
23041
23368
  else if (options.length > 1) ambiguous.push(...options);
@@ -23043,6 +23370,7 @@ function placeMetroDescriptor(listing, descriptor) {
23043
23370
  if (perScale.length === 0 || perScale.some((options) => options.length === 0)) {
23044
23371
  return { files, ambiguous, verified: false, mismatched: false };
23045
23372
  }
23373
+ const fileHashes = !descriptor.fileUris && descriptor.fileHashes?.length === descriptor.scales.length ? descriptor.fileHashes : null;
23046
23374
  for (const combination of placementCombinations(perScale)) {
23047
23375
  let bytes;
23048
23376
  try {
@@ -23052,14 +23380,23 @@ function placeMetroDescriptor(listing, descriptor) {
23052
23380
  } catch {
23053
23381
  continue;
23054
23382
  }
23055
- if (metroDescriptorHash(bytes) !== descriptor.hash) continue;
23383
+ const identical = fileHashes ? bytes.every((file, index) => {
23384
+ const digest = (0, import_node_crypto5.createHash)("md5").update(file).digest("hex");
23385
+ return descriptor.scales.some(
23386
+ (scale, declared) => scale === scales[index] && fileHashes[declared] === digest
23387
+ );
23388
+ }) : scales.length === descriptor.scales.length && metroDescriptorHash(bytes) === descriptor.hash;
23389
+ if (!identical) continue;
23056
23390
  const chosen = /* @__PURE__ */ new Map();
23057
- descriptor.scales.forEach((scale, index) => {
23391
+ scales.forEach((scale, index) => {
23058
23392
  const relative2 = combination[index];
23059
23393
  if (relative2) chosen.set(scale, relative2);
23060
23394
  });
23061
23395
  return { files: chosen, ambiguous: [], verified: true, mismatched: false };
23062
23396
  }
23397
+ if (!fileHashes && scales.length !== descriptor.scales.length) {
23398
+ return { files, ambiguous, verified: false, mismatched: false };
23399
+ }
23063
23400
  return { files, ambiguous, verified: false, mismatched: true };
23064
23401
  }
23065
23402
  function unverifiedFileKey(dest) {
@@ -23172,7 +23509,7 @@ async function inferCloudModuleIdentity(source) {
23172
23509
  );
23173
23510
  }
23174
23511
  }
23175
- async function produceCloudArtifact(bundlePath, assetsPath) {
23512
+ async function produceCloudArtifact(bundlePath, assetsPath, maxBytes = MAX_RNX_CLOUD_BUNDLE_BYTES) {
23176
23513
  const source = await loadBundleSource(bundlePath);
23177
23514
  const descriptors = extractAssetDescriptors(source);
23178
23515
  const search = assetsPath ? explicitMetroAssetDest((0, import_node_path15.resolve)(assetsPath), descriptors) : descriptors.length > 0 && !isRemoteBundleInput(bundlePath) ? searchMetroAssetDest(bundlePath, descriptors) : { dest: null, searched: [], truncated: false };
@@ -23229,9 +23566,9 @@ async function produceCloudArtifact(bundlePath, assetsPath) {
23229
23566
  });
23230
23567
  const bytes = Buffer.from(artifact.code, "utf8");
23231
23568
  const assets = artifact.receipt.assets;
23232
- if (bytes.length > MAX_RNX_CLOUD_BUNDLE_BYTES) {
23569
+ if (bytes.length > maxBytes) {
23233
23570
  throw new Error(
23234
- `${REMOTE_COMMAND} artifact is ${bytes.length} bytes and exceeds the ${MAX_RNX_CLOUD_BUNDLE_BYTES}-byte limit. Embedded assets weigh ${assets.bytes} bytes on disk, and base64 embedding costs about a third on top of that, so the practical asset budget is roughly 15 MB.${largestEmbeddedAssets(assets.sizes, 10)}`
23571
+ `${REMOTE_COMMAND} artifact is ${bytes.length} bytes and exceeds the ${maxBytes}-byte limit. Embedded assets weigh ${assets.bytes} bytes on disk, and base64 embedding costs about a third on top of that, so the practical asset budget is roughly ${Math.round(maxBytes * 0.75 / 1e6)} MB.${largestEmbeddedAssets(assets.sizes, 10)}`
23235
23572
  );
23236
23573
  }
23237
23574
  const warnings = [];
@@ -23240,9 +23577,9 @@ async function produceCloudArtifact(bundlePath, assetsPath) {
23240
23577
  `${REMOTE_COMMAND} embedded a placeholder image for ${substituted.length} asset(s) no scale of which is in ${search.searched.join(", ") || "any asset dest directory"}: ${substituted.join(", ")}. Build the bundle with --assets-dest, or pass --assets <dir>, to ship the real images.`
23241
23578
  );
23242
23579
  }
23243
- if (bytes.length >= WARN_ARTIFACT_BYTES) {
23580
+ if (bytes.length >= Math.floor(maxBytes * 0.8)) {
23244
23581
  warnings.push(
23245
- `${REMOTE_COMMAND} artifact is ${bytes.length} bytes, ${Math.round(bytes.length / MAX_RNX_CLOUD_BUNDLE_BYTES * 100)}% of the ${MAX_RNX_CLOUD_BUNDLE_BYTES}-byte limit.${largestEmbeddedAssets(assets.sizes, 5)}`
23582
+ `${REMOTE_COMMAND} artifact is ${bytes.length} bytes, ${Math.round(bytes.length / maxBytes * 100)}% of the ${maxBytes}-byte limit.${largestEmbeddedAssets(assets.sizes, 5)}`
23246
23583
  );
23247
23584
  }
23248
23585
  return {
@@ -23348,6 +23685,14 @@ async function createCloudBox(options) {
23348
23685
  function resolveCloudSessionForParsed(parsed) {
23349
23686
  const session = readCloudSession();
23350
23687
  if (!session) return null;
23688
+ if (session.service === "box") {
23689
+ if (parsed.simIdSource === "flag" && parsed.simId !== session.boxId) {
23690
+ throw new Error(
23691
+ `this shell is connected to box ${session.boxId}; ${parsed.simId ? `--sim ${parsed.simId}` : "the requested simulator"} is not available in this shell`
23692
+ );
23693
+ }
23694
+ return session;
23695
+ }
23351
23696
  if (parsed.simIdSource === "flag" && parsed.simId !== session.simId) {
23352
23697
  throw new Error(
23353
23698
  `this shell is connected to remote simulator ${session.simId}; ${parsed.simId ? `--sim ${parsed.simId}` : "the requested simulator"} is not available in this shell`
@@ -23367,9 +23712,10 @@ function cloudCommand(command) {
23367
23712
  }
23368
23713
  function createCloudBridgeForParsed(parsed) {
23369
23714
  const session = resolveCloudSessionForParsed(parsed);
23370
- return session ? new CloudBridge(session) : null;
23715
+ if (!session) return null;
23716
+ return session.service === "box" ? new CloudBoxBridge(session) : new CloudBridge(session);
23371
23717
  }
23372
- var import_node_crypto5, import_node_fs14, import_node_path15, DEFAULT_RNX_CLOUD_ORIGIN, MAX_RNX_CLOUD_BUNDLE_BYTES, REMOTE_COMMAND, WARN_ARTIFACT_BYTES, MAX_ASSET_DEST_FILES, ACCOUNT_CHOICE_REFUSALS, PROJECT_ONLY_DIRECTORIES, MAX_PLACEMENT_COMBINATIONS, CloudBridge;
23718
+ var import_node_crypto5, import_node_fs14, import_node_path15, DEFAULT_RNX_CLOUD_ORIGIN, MAX_RNX_CLOUD_BUNDLE_BYTES, REMOTE_COMMAND, MAX_ASSET_DEST_FILES, ACCOUNT_CHOICE_REFUSALS, PROJECT_ONLY_DIRECTORIES, MAX_PLACEMENT_COMBINATIONS, CloudBridge, CloudBoxBridge;
23373
23719
  var init_cloud_client = __esm({
23374
23720
  "cli/cloud-client.ts"() {
23375
23721
  "use strict";
@@ -23390,7 +23736,6 @@ var init_cloud_client = __esm({
23390
23736
  DEFAULT_RNX_CLOUD_ORIGIN = rnxPublicBrand.origin;
23391
23737
  MAX_RNX_CLOUD_BUNDLE_BYTES = RNX_CLOUD_MAX_ARTIFACT_BYTES;
23392
23738
  REMOTE_COMMAND = "rnx ios --remote";
23393
- WARN_ARTIFACT_BYTES = Math.floor(MAX_RNX_CLOUD_BUNDLE_BYTES * 0.8);
23394
23739
  MAX_ASSET_DEST_FILES = 25e3;
23395
23740
  ACCOUNT_CHOICE_REFUSALS = /* @__PURE__ */ new Set([
23396
23741
  "accountId is required",
@@ -23475,6 +23820,70 @@ var init_cloud_client = __esm({
23475
23820
  close() {
23476
23821
  }
23477
23822
  };
23823
+ CloudBoxBridge = class {
23824
+ constructor(session) {
23825
+ this.session = session;
23826
+ }
23827
+ plane = "cloud";
23828
+ async send(command, options) {
23829
+ const id = (0, import_node_crypto5.randomUUID)();
23830
+ const payload = {};
23831
+ for (const [key, value] of Object.entries(command)) {
23832
+ if (key !== "id" && key !== "simId") payload[key] = value;
23833
+ }
23834
+ let response;
23835
+ try {
23836
+ response = await fetch(
23837
+ `${this.session.apiOrigin}/v1/boxes/${encodeURIComponent(this.session.boxId)}/commands`,
23838
+ {
23839
+ method: "POST",
23840
+ headers: {
23841
+ authorization: `Bearer ${this.session.boxToken}`,
23842
+ "content-type": "application/json"
23843
+ },
23844
+ body: JSON.stringify({ id, command: payload }),
23845
+ ...options?.timeoutMs ? { signal: AbortSignal.timeout(options.timeoutMs) } : {}
23846
+ }
23847
+ );
23848
+ } catch (error) {
23849
+ throw new Error(
23850
+ `could not reach box ${this.session.boxId} at ${this.session.apiOrigin}: ${error instanceof Error ? error.message : String(error)}`
23851
+ );
23852
+ }
23853
+ const text = await response.text();
23854
+ if (!response.ok) throw responseError(response.status, text);
23855
+ let parsed;
23856
+ try {
23857
+ parsed = JSON.parse(text);
23858
+ } catch {
23859
+ throw new Error("box command returned unreadable JSON");
23860
+ }
23861
+ if (!isRecord5(parsed) || parsed.id !== id) {
23862
+ throw new Error("box command returned an invalid command receipt");
23863
+ }
23864
+ if (typeof parsed.error === "string" && parsed.error) throw new Error(parsed.error);
23865
+ if (!Object.hasOwn(parsed, "result")) {
23866
+ throw new Error("box command receipt has no result");
23867
+ }
23868
+ return parsed.result;
23869
+ }
23870
+ listSims() {
23871
+ return Promise.reject(new Error("a box does not expose a local simulator list"));
23872
+ }
23873
+ focusSim() {
23874
+ return Promise.reject(new Error("a box simulator has no browser window to focus"));
23875
+ }
23876
+ closeSim() {
23877
+ return Promise.reject(new Error("close a box simulator with rnx box stop"));
23878
+ }
23879
+ claim() {
23880
+ return Promise.reject(
23881
+ new Error("a box simulator is held by its Box page and has nothing to claim")
23882
+ );
23883
+ }
23884
+ close() {
23885
+ }
23886
+ };
23478
23887
  }
23479
23888
  });
23480
23889
 
@@ -26015,6 +26424,7 @@ __export(ws_bridge_exports, {
26015
26424
  createBridge: () => createBridge,
26016
26425
  createBridgeFromParsed: () => createBridgeFromParsed,
26017
26426
  evalInBridge: () => evalInBridge,
26427
+ formatLockOwner: () => formatLockOwner,
26018
26428
  parseBridgeCliArgs: () => parseBridgeCliArgs,
26019
26429
  printBridgeWorldNotice: () => printBridgeWorldNotice,
26020
26430
  resolveBridgePortForPin: () => resolveBridgePortForPin,
@@ -26179,6 +26589,17 @@ function describeSimIdSource(source) {
26179
26589
  if (source === "saved") return "saved via `rnx use`";
26180
26590
  return "primary fallback \u2014 no sim pinned";
26181
26591
  }
26592
+ function formatLockOwner(owner) {
26593
+ const colon = owner.indexOf(":");
26594
+ if (colon <= 0) return owner.length > 24 ? `${owner.slice(0, 21)}\u2026` : owner;
26595
+ const source = owner.slice(0, colon);
26596
+ const value = owner.slice(colon + 1);
26597
+ const short = value.length > 12 ? `${value.slice(0, 8)}\u2026` : value;
26598
+ if (source === "TM_SESSION" || source === "CLAUDE_CODE_SESSION_ID" || source === "CODEX_THREAD_ID") {
26599
+ return `agent ${short}`;
26600
+ }
26601
+ return `${source} ${short}`;
26602
+ }
26182
26603
  function parseBridgeCliArgs(args, opts = {}) {
26183
26604
  const flagIndices = /* @__PURE__ */ new Set();
26184
26605
  const state = {
@@ -28960,7 +29381,6 @@ __export(control_exports, {
28960
29381
  ensureBridgeForOpen: () => ensureBridgeForOpen,
28961
29382
  planBulkCloseTargets: () => planBulkCloseTargets,
28962
29383
  playwrightHostPidForSim: () => playwrightHostPidForSim,
28963
- printConnectedSims: () => printConnectedSims,
28964
29384
  printOpenedSim: () => printOpenedSim,
28965
29385
  resolveBundleTarget: () => resolveBundleTarget,
28966
29386
  resolveDefaultShellBaseUrl: () => resolveDefaultShellBaseUrl,
@@ -28973,7 +29393,6 @@ __export(control_exports, {
28973
29393
  runOpenCommand: () => runOpenCommand,
28974
29394
  runUseCommand: () => runUseCommand,
28975
29395
  signalDriverLaunchConnected: () => signalDriverLaunchConnected,
28976
- summarizeSimUrl: () => summarizeSimUrl,
28977
29396
  terminatePlaywrightHostsForSims: () => terminatePlaywrightHostsForSims,
28978
29397
  waitForSimMatch: () => waitForSimMatch,
28979
29398
  waitForSimMatchOrHostExit: () => waitForSimMatchOrHostExit
@@ -29470,108 +29889,6 @@ async function waitForSimReady(wsPort, commandTimeoutMs, simId, opts = {}) {
29470
29889
  }
29471
29890
  return null;
29472
29891
  }
29473
- function summarizeSimUrl(url) {
29474
- if (!url) return null;
29475
- try {
29476
- const parsed = new URL(url);
29477
- if (parsed.searchParams.has("bundle")) {
29478
- const bundleUrl = parsed.searchParams.get("bundle") || "";
29479
- try {
29480
- const bundle = new URL(bundleUrl);
29481
- const shortPath = bundle.pathname.length > 36 ? `...${bundle.pathname.slice(-36)}` : bundle.pathname;
29482
- return `bundle ${bundle.host}${shortPath}`;
29483
- } catch {
29484
- return "bundle";
29485
- }
29486
- }
29487
- if (parsed.searchParams.has("port")) {
29488
- return `connect :${parsed.searchParams.get("port") || ""}`;
29489
- }
29490
- if (parsed.searchParams.has("open")) {
29491
- return `connect ${parsed.searchParams.get("open") || ""}`;
29492
- }
29493
- if (parsed.searchParams.has("demo")) {
29494
- return `demo ${parsed.searchParams.get("demo") || "default"}`;
29495
- }
29496
- if (parsed.pathname.includes("/sootsim/index.html") || parsed.pathname === "/sootsim/" || parsed.pathname === "/sootsim") {
29497
- return "embedded rnx";
29498
- }
29499
- return null;
29500
- } catch {
29501
- return null;
29502
- }
29503
- }
29504
- function formatLockOwner(owner) {
29505
- const colon = owner.indexOf(":");
29506
- if (colon <= 0) return owner.length > 24 ? `${owner.slice(0, 21)}\u2026` : owner;
29507
- const source = owner.slice(0, colon);
29508
- const value = owner.slice(colon + 1);
29509
- const short = value.length > 12 ? `${value.slice(0, 8)}\u2026` : value;
29510
- if (source === "TM_SESSION" || source === "CLAUDE_CODE_SESSION_ID" || source === "CODEX_THREAD_ID") {
29511
- return `agent ${short}`;
29512
- }
29513
- return `${source} ${short}`;
29514
- }
29515
- function printConnectedSims(sims, selectedId) {
29516
- if (sims.length === 0) {
29517
- console.log(" no sims connected");
29518
- return;
29519
- }
29520
- console.log(` connected sims (${sims.length}):
29521
- `);
29522
- for (const sim of sims) {
29523
- const lockTag = sim.lockedBy && sim.lockExpiresAt ? `locked by ${formatLockOwner(sim.lockedBy)} (${Math.max(0, Math.round((sim.lockExpiresAt - Date.now()) / 1e3))}s)` : "";
29524
- const tags = [
29525
- sim.isPrimary ? "primary" : "",
29526
- sim.id === selectedId ? "selected" : "",
29527
- sim.readyState,
29528
- sim.userVisible === false ? "hidden" : sim.userVisible === true ? "visible" : "",
29529
- sim.attachedCliCount && sim.attachedCliCount > 0 ? "in use" : "",
29530
- sim.userFocused ? "focused" : "",
29531
- lockTag
29532
- ].filter(Boolean);
29533
- console.log(` ${sim.id}${tags.length ? ` [${tags.join(", ")}]` : ""}`);
29534
- const loaded = summarizeSimUrl(sim.url);
29535
- if (loaded) {
29536
- console.log(` loaded: ${loaded}`);
29537
- } else if (sim.url) {
29538
- const shown = sim.url.length > 96 ? `${sim.url.slice(0, 93)}\u2026` : sim.url;
29539
- console.log(` url: ${shown}`);
29540
- } else if (sim.origin) {
29541
- console.log(` origin: ${sim.origin}`);
29542
- }
29543
- const engine = describeEngineSource(sim);
29544
- if (engine) console.log(` engine: ${engine}`);
29545
- if (sim.title) console.log(` title: ${sim.title}`);
29546
- if (sim.visibilityState && sim.visibilityState !== "visible") {
29547
- console.log(` visibility: ${sim.visibilityState}`);
29548
- }
29549
- console.log(` connected: ${formatRelativeAge(Date.now() - sim.connectedAt)}`);
29550
- if (sim.lastActiveAt && sim.lastActiveAt > 0) {
29551
- console.log(` last active: ${formatRelativeAge(Date.now() - sim.lastActiveAt)}`);
29552
- }
29553
- }
29554
- }
29555
- function describeEngineSource(sim) {
29556
- const ref = sim.url || sim.origin || "";
29557
- if (!ref) return null;
29558
- try {
29559
- const port = new URL(ref).port;
29560
- if (port === "5173") return "dev \u2014 local source (:5173)";
29561
- if (port === "3000") return "Contrast app embedded (:3000)";
29562
- if (resolveDevCheckoutRuntimeRoot()) return `dev \u2014 local build (:${port || "?"})`;
29563
- return `runtime \u2014 published engine (:${port || "?"})`;
29564
- } catch {
29565
- return null;
29566
- }
29567
- }
29568
- function formatRelativeAge(ms) {
29569
- const sec = Math.max(0, Math.round(ms / 1e3));
29570
- if (sec < 60) return `${sec}s ago`;
29571
- if (sec < 3600) return `${Math.round(sec / 60)}m ago`;
29572
- if (sec < 86400) return `${Math.round(sec / 3600)}h ago`;
29573
- return `${Math.round(sec / 86400)}d ago`;
29574
- }
29575
29892
  async function waitForSimMatch(wsPort, commandTimeoutMs, predicate, opts = {}) {
29576
29893
  const attempts = opts.attempts ?? 30;
29577
29894
  const intervalMs = opts.intervalMs ?? 500;