peachsim 0.1.854 → 0.1.871

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 (93) hide show
  1. package/cli/commands/control.ts +37 -7
  2. package/cli/commands/do-chain.ts +1 -1
  3. package/cli/commands/inspect/settling.ts +2 -0
  4. package/cli/commands/inspect.ts +2 -2
  5. package/cli/commands/preview.ts +0 -11
  6. package/cli/current-sim.ts +11 -4
  7. package/cli/drivers/playwright-sim-host.ts +21 -13
  8. package/cli/drivers/playwright.ts +2 -47
  9. package/dist-lib/agent-daemon-client.cjs +1 -1
  10. package/dist-lib/agent-events.cjs +1 -1
  11. package/dist-lib/agent-identity.cjs +1 -1
  12. package/dist-lib/agent-sessions.cjs +1 -1
  13. package/dist-lib/attached-projects.cjs +1 -1
  14. package/dist-lib/auth/shared-session.cjs +1 -1
  15. package/dist-lib/backend-origin.cjs +1 -1
  16. package/dist-lib/beta.cjs +1 -1
  17. package/dist-lib/beta.mjs +1 -1
  18. package/dist-lib/bridge-constants.cjs +1 -1
  19. package/dist-lib/bridge-contract-input.cjs +1 -1
  20. package/dist-lib/bridge-contract-input.mjs +1 -1
  21. package/dist-lib/bridge-contract.cjs +1 -1
  22. package/dist-lib/bridge-contract.mjs +1 -1
  23. package/dist-lib/bundle-channel.cjs +13 -12
  24. package/dist-lib/capture-contract.cjs +1 -1
  25. package/dist-lib/capture-contract.mjs +1 -1
  26. package/dist-lib/cli-constants.cjs +1 -1
  27. package/dist-lib/cloud-contract.cjs +1 -1
  28. package/dist-lib/cloud-contract.mjs +1 -1
  29. package/dist-lib/cloud-test-args.cjs +1 -1
  30. package/dist-lib/cloud-test-args.mjs +1 -1
  31. package/dist-lib/cloud.cjs +1 -1
  32. package/dist-lib/cloud.mjs +1 -1
  33. package/dist-lib/config.cjs +1 -1
  34. package/dist-lib/detox/index.cjs +5 -3
  35. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  36. package/dist-lib/expo-swift-bundle.cjs +13 -12
  37. package/dist-lib/expo-swift-metadata.cjs +1 -1
  38. package/dist-lib/expo-swift-metadata.mjs +1 -1
  39. package/dist-lib/home-paths.cjs +1 -1
  40. package/dist-lib/host/bridge-host.cjs +13 -12
  41. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  42. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  43. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  44. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  45. package/dist-lib/host/websocket-proxy.cjs +1 -1
  46. package/dist-lib/index.cjs +7 -3
  47. package/dist-lib/jump-to-source-babel.cjs +1 -1
  48. package/dist-lib/jump-to-source-native.cjs +1 -1
  49. package/dist-lib/kotlin-host.cjs +1 -1
  50. package/dist-lib/menu.cjs +1 -1
  51. package/dist-lib/menu.mjs +1 -1
  52. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  53. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  54. package/dist-lib/metro-production-bundle.cjs +1 -1
  55. package/dist-lib/metro-production-bundle.mjs +1 -1
  56. package/dist-lib/metro.cjs +1 -1
  57. package/dist-lib/native-app-identity.cjs +1 -1
  58. package/dist-lib/native-app-identity.mjs +1 -1
  59. package/dist-lib/native-firebase-metadata.cjs +1 -1
  60. package/dist-lib/native-firebase-metadata.mjs +1 -1
  61. package/dist-lib/plist.cjs +1 -1
  62. package/dist-lib/plist.mjs +1 -1
  63. package/dist-lib/profiles.cjs +1 -1
  64. package/dist-lib/public-brand.cjs +1 -1
  65. package/dist-lib/react-native-host-modules.cjs +1 -1
  66. package/dist-lib/react-native-host-modules.mjs +1 -1
  67. package/dist-lib/render-mode.cjs +1 -1
  68. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  69. package/dist-lib/sdk.cjs +3 -1
  70. package/dist-lib/sdk.mjs +3 -1
  71. package/dist-lib/skills.cjs +53 -48
  72. package/dist-lib/swift-compile.cjs +1 -1
  73. package/dist-lib/swift-compile.mjs +1 -1
  74. package/dist-lib/swift-package.cjs +1 -1
  75. package/dist-lib/swift-package.mjs +1 -1
  76. package/dist-lib/swift-submit.cjs +1 -1
  77. package/dist-lib/swift-submit.mjs +1 -1
  78. package/dist-lib/swift-toolchain.cjs +1 -1
  79. package/dist-lib/swift.cjs +1 -1
  80. package/dist-lib/vite-swift.cjs +14 -13
  81. package/dist-lib/vite.cjs +1 -1
  82. package/dist-lib/worklet-executable.cjs +1 -1
  83. package/dist-lib/worklet-executable.mjs +1 -1
  84. package/kotlin/fork/NOTICE +4 -2
  85. package/kotlin/fork/README.md +12 -6
  86. package/kotlin/fork/build.sh +9 -2
  87. package/kotlin/fork/fork.json +1 -1
  88. package/kotlin/fork/skia-android-shaping.patch +124 -1
  89. package/kotlin/toolchain.json +3 -3
  90. package/package.json +1 -1
  91. package/skills/contrast/SKILL.md +2 -2
  92. package/skills/peach-debug/SKILL.md +2 -2
  93. package/src/swift-host.ts +14 -15
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.854 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.871 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -37069,11 +37069,13 @@ function packageSources(packagePath) {
37069
37069
  }
37070
37070
  return files2;
37071
37071
  }
37072
- function packageSnapshot(project) {
37072
+ function packageSnapshot(project, entry) {
37073
37073
  const files2 = packageSources(project.packagePath);
37074
+ const layout = xcodeLayout(project.packagePath);
37074
37075
  const native = nativeSourceDescriptor(project.packagePath);
37075
37076
  return {
37076
37077
  files: files2,
37078
+ entry: layout ? xcodeInputKey(layout, import_node_path20.default.resolve(project.packagePath, entry), entry) : entry,
37077
37079
  resourcePaths: swiftImplicitResourcePaths(
37078
37080
  resourceCandidateFiles(project.packagePath).map(
37079
37081
  (file) => import_node_path20.default.relative(project.packagePath, file).split(import_node_path20.default.sep).join(import_node_path20.default.posix.sep)
@@ -37091,18 +37093,18 @@ function packageSnapshot(project) {
37091
37093
  } : {}
37092
37094
  };
37093
37095
  }
37094
- function snapshotCompileInput(snapshot, entry) {
37096
+ function snapshotCompileInput(snapshot) {
37095
37097
  const input = {
37096
37098
  files: snapshot.files,
37097
37099
  resourcePaths: snapshot.resourcePaths,
37098
37100
  resources: snapshot.bundleFiles.files,
37099
37101
  images: snapshot.resources.images,
37100
- entry,
37102
+ entry: snapshot.entry,
37101
37103
  oneModule: true
37102
37104
  };
37103
37105
  return snapshot.glue ? withNativeSourceGlue(input, snapshot.glue) : input;
37104
37106
  }
37105
- async function compile(packagePath, entry, stamp, moduleRootOverride, hosted, snapshot) {
37107
+ async function compile(packagePath, stamp, moduleRootOverride, hosted, snapshot) {
37106
37108
  const resources = {
37107
37109
  table: snapshot.resources.table,
37108
37110
  colors: snapshot.resources.colors,
@@ -37116,7 +37118,7 @@ async function compile(packagePath, entry, stamp, moduleRootOverride, hosted, sn
37116
37118
  };
37117
37119
  if (hosted)
37118
37120
  return {
37119
- ...await compileRemote(packagePath, entry, snapshot, hosted),
37121
+ ...await compileRemote(packagePath, snapshot, hosted),
37120
37122
  stamp,
37121
37123
  package: content
37122
37124
  };
@@ -37125,12 +37127,12 @@ async function compile(packagePath, entry, stamp, moduleRootOverride, hosted, sn
37125
37127
  ) ?? await swiftDistributionRoot();
37126
37128
  if (!moduleRoot)
37127
37129
  return {
37128
- ...await compileRemote(packagePath, entry, snapshot),
37130
+ ...await compileRemote(packagePath, snapshot),
37129
37131
  stamp,
37130
37132
  package: content
37131
37133
  };
37132
37134
  const toolchain = swiftModuleToolchain(moduleRoot);
37133
- const input = snapshotCompileInput(snapshot, entry);
37135
+ const input = snapshotCompileInput(snapshot);
37134
37136
  const targets = compileTargets(input).map((target) => target.name);
37135
37137
  const missing = missingSwiftModules(
37136
37138
  input.files,
@@ -37248,7 +37250,7 @@ async function missingModulesMessage(packagePath, missing) {
37248
37250
  })
37249
37251
  ].join("\n");
37250
37252
  }
37251
- async function compileRemote(packagePath, entry, snapshot, hosted) {
37253
+ async function compileRemote(packagePath, snapshot, hosted) {
37252
37254
  const auth = hosted ? null : resolveCliAuth();
37253
37255
  if (!hosted && (!auth || auth.kind === "github")) {
37254
37256
  throw new Error(
@@ -37282,7 +37284,7 @@ async function compileRemote(packagePath, entry, snapshot, hosted) {
37282
37284
  resourcePaths: snapshot.resourcePaths,
37283
37285
  resources: snapshot.bundleFiles.files,
37284
37286
  images: snapshot.resources.images,
37285
- entry,
37287
+ entry: snapshot.entry,
37286
37288
  packageId: descriptor?.packageId ?? swiftPackageId(packagePath)
37287
37289
  },
37288
37290
  origin,
@@ -37330,13 +37332,12 @@ function artifactFor(project, entry, moduleRoot) {
37330
37332
  const again = () => artifactFor(project, entry, moduleRoot);
37331
37333
  return running.promise.then(again, again);
37332
37334
  }
37333
- const snapshot = packageSnapshot(project);
37335
+ const snapshot = packageSnapshot(project, entry);
37334
37336
  if (sourceStamp(project.packagePath, moduleRoot, Boolean(project.hosted)) !== stamp) {
37335
37337
  return artifactFor(project, entry, moduleRoot);
37336
37338
  }
37337
37339
  const promise = compile(
37338
37340
  project.packagePath,
37339
- entry,
37340
37341
  stamp,
37341
37342
  moduleRoot,
37342
37343
  project.hosted,
@@ -47843,7 +47844,8 @@ function findTopAncestor(start, maxDepth = 20) {
47843
47844
  let pid = getParentPid(start);
47844
47845
  if (!pid || pid <= 1) {
47845
47846
  const comm = getProcessComm(start);
47846
- return start > 1 && comm && !IMMORTAL_HOST_COMM_RE.test(comm) ? start : null;
47847
+ if (!comm || start < 1 || IMMORTAL_HOST_COMM_RE.test(comm)) return null;
47848
+ return start > 1 || !INIT_COMM_RE.test(comm) ? start : null;
47847
47849
  }
47848
47850
  for (let i = 0; i < maxDepth; i++) {
47849
47851
  const comm = getProcessComm(pid);
@@ -47865,7 +47867,7 @@ function getCliIdentity() {
47865
47867
  }
47866
47868
  }
47867
47869
  const topPid = findTopAncestor(process.ppid);
47868
- if (topPid && topPid > 1) {
47870
+ if (topPid) {
47869
47871
  return { key: `gppid-${topPid}`, source: "grand-ppid", stable: true };
47870
47872
  }
47871
47873
  return { key: `pid-${process.ppid}`, source: "ppid", stable: false };
@@ -47939,7 +47941,7 @@ function saveCurrentSimId(simId) {
47939
47941
  function clearCurrentSimId() {
47940
47942
  (0, import_fs4.rmSync)(getCurrentSimPath(), { force: true });
47941
47943
  }
47942
- var import_fs4, import_os, import_path3, CURRENT_SIM_VERSION, CURRENT_SIM_PATH_ENV, IDENTITY_ENV_VARS, IMMORTAL_HOST_COMM_RE, readCurrentSim;
47944
+ var import_fs4, import_os, import_path3, CURRENT_SIM_VERSION, CURRENT_SIM_PATH_ENV, IDENTITY_ENV_VARS, IMMORTAL_HOST_COMM_RE, INIT_COMM_RE, readCurrentSim;
47943
47945
  var init_current_sim = __esm({
47944
47946
  "cli/current-sim.ts"() {
47945
47947
  "use strict";
@@ -47981,6 +47983,7 @@ var init_current_sim = __esm({
47981
47983
  // vscode integrated terminal
47982
47984
  ];
47983
47985
  IMMORTAL_HOST_COMM_RE = /^(?:tmux|screen)|^tm$/i;
47986
+ INIT_COMM_RE = /^(?:init|systemd|launchd|tini|docker-init|dumb-init|catatonit|s6-svscan|runsvdir)$/i;
47984
47987
  readCurrentSim = readCurrentTarget;
47985
47988
  }
47986
47989
  });
@@ -52502,15 +52505,6 @@ function probe() {
52502
52505
  detail: resolved ? `resolved via ${resolved.spec}@${resolved.version}` : `installs playwright-core@${PINNED_PLAYWRIGHT_CORE.version} on first launch`
52503
52506
  };
52504
52507
  }
52505
- function headlessHintForLinuxFailure(opts, detail) {
52506
- if (process.platform !== "linux") return null;
52507
- if (opts.headless) return null;
52508
- if (process.env.DISPLAY || process.env.WAYLAND_DISPLAY) return null;
52509
- if (!/missing x server|cannot open display|x server|x11/i.test(detail)) {
52510
- return null;
52511
- }
52512
- return " hint: linux without DISPLAY/WAYLAND_DISPLAY \u2014 rerun without --headed (or add --headless) to run playwright headless.";
52513
- }
52514
52508
  function resolveUserDataDir(opts) {
52515
52509
  if (opts.profileId) {
52516
52510
  return playwrightProfileUserDataDir(ensureProfile(opts.profileId).id);
@@ -52537,7 +52531,7 @@ async function launch(opts) {
52537
52531
  return { launched: false, message: "playwright driver requires a target url" };
52538
52532
  }
52539
52533
  const ownerPid = opts.ownerPid;
52540
- if (ownerPid === void 0 || !Number.isInteger(ownerPid) || ownerPid <= 1) {
52534
+ if (ownerPid === void 0 || !Number.isInteger(ownerPid) || ownerPid < 1) {
52541
52535
  return {
52542
52536
  launched: false,
52543
52537
  message: "playwright driver requires a valid owning session process"
@@ -52623,23 +52617,6 @@ async function launch(opts) {
52623
52617
  }
52624
52618
  );
52625
52619
  child.unref();
52626
- const earlyExit = await new Promise((resolve10) => {
52627
- const timer = setTimeout(() => resolve10(null), 4e3);
52628
- child.once("exit", (code) => {
52629
- clearTimeout(timer);
52630
- resolve10(code ?? 0);
52631
- });
52632
- });
52633
- if (earlyExit !== null) {
52634
- const detail = (0, import_fs7.readFileSync)(errLog, "utf8").trim();
52635
- const hint = headlessHintForLinuxFailure(opts, detail);
52636
- return {
52637
- launched: false,
52638
- message: `playwright host exited early (code ${earlyExit}) \u2014 host log ${errLog}${detail ? `:
52639
- ${detail}` : ""}${hint ? `
52640
- ${hint}` : ""}`
52641
- };
52642
- }
52643
52620
  const ownerComm = getProcessComm(ownerPid);
52644
52621
  const idleMinutes = AUTOMATION_SIM_IDLE_REAP_TTL_MS / 6e4;
52645
52622
  const ownerNote = ` \u2014 browser closes after ${idleMinutes} min with no peach command or input, or when pid ${ownerPid}${ownerComm ? ` (${ownerComm})` : ""} exits`;
@@ -54069,7 +54046,11 @@ async function waitForSimReady(wsPort, commandTimeoutMs, simId, opts = {}) {
54069
54046
  bridge.close();
54070
54047
  await sleep(intervalMs);
54071
54048
  }
54072
- return { bridge: null, attempts, intervalMs, minNodeCount, lastCount, lastError };
54049
+ const observed = lastError ? `last bridge error: ${lastError}` : lastCount === null ? "guest never installed window.__sootsimTest" : `last node count: ${String(lastCount)} (needs > ${minNodeCount})`;
54050
+ return {
54051
+ bridge: null,
54052
+ failure: `after ${attempts} polls over ${Math.round(attempts * intervalMs / 1e3)}s; ${observed}`
54053
+ };
54073
54054
  }
54074
54055
  async function waitForSimMatch(wsPort, commandTimeoutMs, predicate, opts = {}) {
54075
54056
  const attempts = opts.attempts ?? 30;
@@ -54775,15 +54756,14 @@ async function runOpenCommand(args, opts = {}) {
54775
54756
  rnxExit(1);
54776
54757
  }
54777
54758
  targetSim = navigatedSim;
54778
- const ready = await waitForSimReady(
54759
+ const ready2 = await waitForSimReady(
54779
54760
  parsed.wsPort,
54780
54761
  parsed.commandTimeoutMs,
54781
54762
  targetSim.id
54782
54763
  );
54783
- if (!ready.bridge) {
54784
- const observed = ready.lastError ? `last bridge error: ${ready.lastError}` : ready.lastCount === null ? "guest never installed window.__sootsimTest" : `last node count: ${String(ready.lastCount)} (needs > ${ready.minNodeCount})`;
54764
+ if (!ready2.bridge) {
54785
54765
  console.error(
54786
- ` timed out waiting for current sim to load target after ${ready.attempts} polls over ${Math.round(ready.attempts * ready.intervalMs / 1e3)}s; ${observed}`
54766
+ ` timed out waiting for current sim to load target ${ready2.failure}`
54787
54767
  );
54788
54768
  await printBridgeFailureDiagnostics(bridge, {
54789
54769
  errorsCommand: `peach get errors 5${simHint}`,
@@ -54792,7 +54772,7 @@ async function runOpenCommand(args, opts = {}) {
54792
54772
  });
54793
54773
  rnxExit(1);
54794
54774
  }
54795
- ready.bridge.close();
54775
+ ready2.bridge.close();
54796
54776
  saveCurrentSimId(targetSim.id);
54797
54777
  printOpenedSim(
54798
54778
  navigatedShellUrl,
@@ -54889,6 +54869,29 @@ async function runOpenCommand(args, opts = {}) {
54889
54869
  if (opts.resources) opts.resources.simId = match.id;
54890
54870
  saveCurrentSimId(match.id);
54891
54871
  signalDriverLaunchConnected(result);
54872
+ const ready = await waitForSimReady(parsed.wsPort, parsed.commandTimeoutMs, match.id, {
54873
+ intervalMs: connectWait.intervalMs,
54874
+ attempts: connectWait.attempts
54875
+ });
54876
+ if (!ready.bridge) {
54877
+ console.error(
54878
+ ` timed out waiting for opened sim ${match.id} to load ${ready.failure}`
54879
+ );
54880
+ const hint = ` --sim ${match.id}`;
54881
+ const bridge = createBridge(parsed.wsPort, {
54882
+ commandTimeoutMs: parsed.commandTimeoutMs,
54883
+ simId: match.id,
54884
+ simIdSource: "flag"
54885
+ });
54886
+ await printBridgeFailureDiagnostics(bridge, {
54887
+ errorsCommand: `peach get errors 5${hint}`,
54888
+ warningsCommand: `peach get warnings 5${hint}`,
54889
+ requestsCommand: `peach get requests 5${hint}`
54890
+ });
54891
+ bridge.close();
54892
+ rnxExit(1);
54893
+ }
54894
+ ready.bridge.close();
54892
54895
  printOpenedSim(openUrl2, match, `${driver.name} driver`, quiet);
54893
54896
  await maybeDescribeAfterOpen(parsed.wsPort, match.id, args);
54894
54897
  printAgentHints(quiet);
@@ -55903,6 +55906,8 @@ async function waitForSootsimIdle({
55903
55906
  if (paintStill && !last.screenPixels) blockers.push('screen pixels unavailable')
55904
55907
  else if (paintStill && !screenUnchanged(last.screenPixels)) blockers.push('screen pixels still changing')
55905
55908
  if (last.requestInFlight > 0) blockers.push(last.requestInFlight + ' requests in flight')
55909
+ else if (last.requestTotal !== lastRequestTotal) blockers.push('new requests issued')
55910
+ if (polls < 2) blockers.push('sim too busy to poll twice')
55906
55911
  return {
55907
55912
  settled: false,
55908
55913
  elapsed: Date.now() - start,
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.854 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.871 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.854 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.871 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/swift-compile.ts
4
4
  import { execFile as execFile2, execFileSync } from "node:child_process";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.854 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.871 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.854 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.871 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/swift-package.ts
4
4
  function isSwiftManifestFile(file) {
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.854 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.871 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.854 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.871 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/swift-submit.ts
4
4
  var SWIFT_COMPILE_PATH = "/api/swift-compile";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.854 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.871 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.854 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.871 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.854 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.871 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -8057,11 +8057,13 @@ function packageSources(packagePath) {
8057
8057
  }
8058
8058
  return files2;
8059
8059
  }
8060
- function packageSnapshot(project) {
8060
+ function packageSnapshot(project, entry) {
8061
8061
  const files2 = packageSources(project.packagePath);
8062
+ const layout = xcodeLayout(project.packagePath);
8062
8063
  const native = nativeSourceDescriptor(project.packagePath);
8063
8064
  return {
8064
8065
  files: files2,
8066
+ entry: layout ? xcodeInputKey(layout, import_node_path15.default.resolve(project.packagePath, entry), entry) : entry,
8065
8067
  resourcePaths: swiftImplicitResourcePaths(
8066
8068
  resourceCandidateFiles(project.packagePath).map(
8067
8069
  (file) => import_node_path15.default.relative(project.packagePath, file).split(import_node_path15.default.sep).join(import_node_path15.default.posix.sep)
@@ -8079,21 +8081,21 @@ function packageSnapshot(project) {
8079
8081
  } : {}
8080
8082
  };
8081
8083
  }
8082
- function snapshotCompileInput(snapshot, entry) {
8084
+ function snapshotCompileInput(snapshot) {
8083
8085
  const input = {
8084
8086
  files: snapshot.files,
8085
8087
  resourcePaths: snapshot.resourcePaths,
8086
8088
  resources: snapshot.bundleFiles.files,
8087
8089
  images: snapshot.resources.images,
8088
- entry,
8090
+ entry: snapshot.entry,
8089
8091
  oneModule: true
8090
8092
  };
8091
8093
  return snapshot.glue ? withNativeSourceGlue(input, snapshot.glue) : input;
8092
8094
  }
8093
8095
  function compileInput(packagePath, entry) {
8094
- return snapshotCompileInput(packageSnapshot(projectFor(packagePath)), entry);
8096
+ return snapshotCompileInput(packageSnapshot(projectFor(packagePath), entry));
8095
8097
  }
8096
- async function compile(packagePath, entry, stamp, moduleRootOverride, hosted, snapshot) {
8098
+ async function compile(packagePath, stamp, moduleRootOverride, hosted, snapshot) {
8097
8099
  const resources = {
8098
8100
  table: snapshot.resources.table,
8099
8101
  colors: snapshot.resources.colors,
@@ -8107,7 +8109,7 @@ async function compile(packagePath, entry, stamp, moduleRootOverride, hosted, sn
8107
8109
  };
8108
8110
  if (hosted)
8109
8111
  return {
8110
- ...await compileRemote(packagePath, entry, snapshot, hosted),
8112
+ ...await compileRemote(packagePath, snapshot, hosted),
8111
8113
  stamp,
8112
8114
  package: content
8113
8115
  };
@@ -8116,12 +8118,12 @@ async function compile(packagePath, entry, stamp, moduleRootOverride, hosted, sn
8116
8118
  ) ?? await swiftDistributionRoot();
8117
8119
  if (!moduleRoot)
8118
8120
  return {
8119
- ...await compileRemote(packagePath, entry, snapshot),
8121
+ ...await compileRemote(packagePath, snapshot),
8120
8122
  stamp,
8121
8123
  package: content
8122
8124
  };
8123
8125
  const toolchain = swiftModuleToolchain(moduleRoot);
8124
- const input = snapshotCompileInput(snapshot, entry);
8126
+ const input = snapshotCompileInput(snapshot);
8125
8127
  const targets = compileTargets(input).map((target) => target.name);
8126
8128
  const missing = missingSwiftModules(
8127
8129
  input.files,
@@ -8258,7 +8260,7 @@ async function missingModulesMessage(packagePath, missing) {
8258
8260
  })
8259
8261
  ].join("\n");
8260
8262
  }
8261
- async function compileRemote(packagePath, entry, snapshot, hosted) {
8263
+ async function compileRemote(packagePath, snapshot, hosted) {
8262
8264
  const auth = hosted ? null : resolveCliAuth();
8263
8265
  if (!hosted && (!auth || auth.kind === "github")) {
8264
8266
  throw new Error(
@@ -8292,7 +8294,7 @@ async function compileRemote(packagePath, entry, snapshot, hosted) {
8292
8294
  resourcePaths: snapshot.resourcePaths,
8293
8295
  resources: snapshot.bundleFiles.files,
8294
8296
  images: snapshot.resources.images,
8295
- entry,
8297
+ entry: snapshot.entry,
8296
8298
  packageId: descriptor?.packageId ?? swiftPackageId(packagePath)
8297
8299
  },
8298
8300
  origin,
@@ -8340,13 +8342,12 @@ function artifactFor(project, entry, moduleRoot) {
8340
8342
  const again = () => artifactFor(project, entry, moduleRoot);
8341
8343
  return running.promise.then(again, again);
8342
8344
  }
8343
- const snapshot = packageSnapshot(project);
8345
+ const snapshot = packageSnapshot(project, entry);
8344
8346
  if (sourceStamp(project.packagePath, moduleRoot, Boolean(project.hosted)) !== stamp) {
8345
8347
  return artifactFor(project, entry, moduleRoot);
8346
8348
  }
8347
8349
  const promise = compile(
8348
8350
  project.packagePath,
8349
- entry,
8350
8351
  stamp,
8351
8352
  moduleRoot,
8352
8353
  project.hosted,
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.854 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.871 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.854 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.871 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.854 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.871 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/worklet-executable.ts
4
4
  import { parse } from "acorn";
@@ -1,7 +1,7 @@
1
1
  Peach's patched builds of JetBrains Compose Multiplatform UI and Skiko
2
2
 
3
3
  This directory records modified Compose and Skiko builds under Apache License
4
- 2.0 (LICENSE), and a modified Skia shaping unit under BSD-3-Clause (SKIA_LICENSE).
4
+ 2.0 (LICENSE), and modified Skia shaping and paragraph units under BSD-3-Clause (SKIA_LICENSE).
5
5
 
6
6
  - JetBrains/compose-multiplatform-core at tag v1.13.0-alpha01
7
7
  (commit a9e47e8aa04c95cfe572ab4297c770f3cbfb234e), a fork of the Android
@@ -38,4 +38,6 @@ The Compose patch also selects integer static glyph advances on Android and
38
38
  scales letter spacing to the integer shaping size, retaining fractional Animated
39
39
  text. skia-android-shaping.patch truncates only the measurement-font copy for
40
40
  non-subpixel, non-linear shaping. The original run font retains its painting
41
- size and metrics. The modified Skia unit compiles into the Skiko Wasm runtime.
41
+ size and metrics. Run.cpp uses Android inter-glyph spacing and caret boundaries. TextLine.cpp
42
+ trims line edges, and TextWrapper.cpp applies the same trimming before fitting
43
+ a line. These modified Skia units compile into the Skiko Wasm runtime.
@@ -16,6 +16,7 @@ Android behavior for the approved web differences and static text shaping below.
16
16
  | Compose `ui-skiko` | `SkiaBackedPaint.nonAndroid.kt` | initial Miter join agrees with the backing paint and Android |
17
17
  | Compose `ui-skiko` | `SkikoText.nonAndroid.kt`, `SkikoParagraphBuilder.nonAndroid.kt` | Android static advances and letter-spacing scale; Animated text retains fractional shaping |
18
18
  | Skia shaper | `SkShaper_harfbuzz.cpp` | measurement-font copy truncates static shaping size; the painted run font retains the requested size |
19
+ | Skia paragraph | `Run.cpp`, `TextLine.cpp`, `TextWrapper.cpp` | Android inter-glyph spacing, caret boundaries and edge trimming before line fits |
19
20
  | Compose `material3` | `PlatformDateFormat.web.kt` | timestamp formatting uses UTC, as Android does |
20
21
  | Navigation `navigation-compose` | `DefaultNavTransitions.web.kt` | Android forward fades and predictive pop defaults |
21
22
  | Skiko | `OsArch.web.kt` | explicit `setHostOsProvider`; its default lazily retains upstream OS detection |
@@ -30,12 +31,14 @@ this contract.
30
31
 
31
32
  `fork.json` pins repositories, commits, patch hashes, JDK and Android tools.
32
33
  Every changed upstream file carries a modification notice. `LICENSE` and
33
- `NOTICE` travel with the patches. `SKIA_LICENSE` records the shaping unit’s BSD license. `build.sh` builds the changed KLIBs and Skiko
34
- runtime jar with the upstream Gradle builds on the Linux builder. The Skia shaping
35
- unit is fetched at its pinned commit, patched, and compiled into Skiko; the linker
36
- uses it instead of the same unit in the pinned Skia archive. All other Skia
34
+ `NOTICE` travel with the patches. `SKIA_LICENSE` records the modified Skia units’ BSD license. `build.sh` builds the changed KLIBs and Skiko
35
+ runtime jar with the upstream Gradle builds on the Linux builder. The Skia shaping and paragraph
36
+ units are fetched at their pinned commit, patched, and compiled into Skiko; the linker
37
+ uses them instead of the same units in the pinned Skia archive. All other Skia
37
38
  objects retain their upstream build. This adds no allocation beyond the existing
38
39
  measurement-font copy, and truncates once per shaped font, outside the glyph loop.
40
+ Paragraph spacing adds constant arithmetic per glyph or cluster; line fits trim
41
+ the same edge half-spaces as completed lines, without allocation.
39
42
 
40
43
  ```sh
41
44
  delivery="scripts/tmp/kotlin-fork-$(date +%s)-$$"
@@ -65,5 +68,8 @@ then rematch the Android pins in `plans/peach/kotlin-everywhere.md`. The prepare
65
68
  upstream issue names these hooks and the full guest regression vehicle.
66
69
 
67
70
  The static shaping correction is measured against the original `textwidth`
68
- fixture. Styled line-end letter spacing and Animated whole-width rounding
69
- remain open in the lane plan; the shaping correction does not close those grades.
71
+ fixture. The six original widths, twelve spacing assertions and the 162/164 px
72
+ wrapping threshold pass their paired Android controls. The body Range probe
73
+ retains its existing 0.00098 px difference. Pixel residuals, mixed-font bold
74
+ advances, the primary caret at a style boundary and Animated whole-width rounding
75
+ remain open in the lane plan. These corrections do not certify full text parity.
@@ -118,10 +118,17 @@ checkout 0
118
118
  checkout 1
119
119
  SKIKO_SOURCE=${SOURCE}
120
120
  checkout 2
121
- # compile the patched shaping unit in Skiko so the linker uses it in place of
122
- # the upstream archive unit. all other Skia objects remain pinned upstream.
121
+ # compile patched shaping and paragraph units in Skiko instead of their
122
+ # upstream archive units. all other Skia objects remain pinned upstream.
123
123
  cmp "${SOURCE}/LICENSE" "${FORK}/SKIA_LICENSE"
124
124
  cp "${SOURCE}/modules/skshaper/src/SkShaper_harfbuzz.cpp" "${SKIKO_SOURCE}/skiko/src/nativeJsMain/cpp/AndroidShaper.cpp"
125
+ # internal paragraph headers come from the same pinned source as the archive.
126
+ rsync -a --include='*/' --include='*.h' --exclude='*' "${SOURCE}/include/" "${SKIKO_SOURCE}/skiko/src/nativeJsMain/cpp/include/"
127
+ rsync -a --include='*/' --include='*.h' --exclude='*' "${SOURCE}/modules/" "${SKIKO_SOURCE}/skiko/src/nativeJsMain/cpp/modules/"
128
+ rsync -a --include='*/' --include='*.h' --exclude='*' "${SOURCE}/src/" "${SKIKO_SOURCE}/skiko/src/nativeJsMain/cpp/src/"
129
+ cp "${SOURCE}/modules/skparagraph/src/Run.cpp" "${SKIKO_SOURCE}/skiko/src/nativeJsMain/cpp/AndroidParagraphRun.cpp"
130
+ cp "${SOURCE}/modules/skparagraph/src/TextLine.cpp" "${SKIKO_SOURCE}/skiko/src/nativeJsMain/cpp/AndroidParagraphTextLine.cpp"
131
+ cp "${SOURCE}/modules/skparagraph/src/TextWrapper.cpp" "${SKIKO_SOURCE}/skiko/src/nativeJsMain/cpp/AndroidParagraphTextWrapper.cpp"
125
132
  (
126
133
  cd "${SKIKO_SOURCE}/skiko"
127
134
  gradle -Pdeploy.version=0.152.0-alpha02 -Pdeploy.release=true \
@@ -36,7 +36,7 @@
36
36
  "tag": "m152-2ca5fe6a81",
37
37
  "commit": "2ca5fe6a8170e2f55f519d9de083be4dccc06e70",
38
38
  "patch": "skia-android-shaping.patch",
39
- "patchSha256": "1f1b656d8ae1144e3599dd900859202003784d14a52b3bb1da9349f3f8a322df"
39
+ "patchSha256": "4e453826e54c1fcaf0e164b5e2ff121399c4316b18653911e1d6b51df840f100"
40
40
  }
41
41
  ]
42
42
  }