stim 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -155
- package/dist/{android-BRgBYzU0.mjs → android-BPGizezh.mjs} +112 -135
- package/dist/{android-DeYdjjBP.mjs → android-DEgo4oCo.mjs} +2 -2
- package/dist/{android-DWssqHQ8.mjs → android-_y4Ohi5z.mjs} +54 -15
- package/dist/android-cas-compiler.mjs +2 -2
- package/dist/{android-cas-SWIjzeuL.mjs → android-cas-eiExNLf7.mjs} +21 -14
- package/dist/app-install-Uf3a83Tv.mjs +819 -0
- package/dist/{build-lock-CgtsB6TV.mjs → build-lock-DPXPLgTc.mjs} +120 -24
- package/dist/build-progress-CVqkfPC6.mjs +188 -0
- package/dist/{cache-manifest-CYJi8-Hx.mjs → cache-manifest-Dg7OnMrp.mjs} +4 -4
- package/dist/cache-manifest.mjs +1 -1
- package/dist/cli.mjs +22 -19
- package/dist/collector-run.d.mts +2 -0
- package/dist/collector-run.mjs +10 -9
- package/dist/{command-output-B3ycpsYv.mjs → command-output-gByVmIjy.mjs} +11 -2
- package/dist/{config-B7iyKWkL.mjs → config-Cp9lM3wX.mjs} +187 -57
- package/dist/{dependency-state-D0M7oKA7.mjs → dependency-state-Bq5DcLGn.mjs} +2 -2
- package/dist/{deps-oCXVNEqQ.mjs → deps-Cip5vUm1.mjs} +8 -5
- package/dist/{detached-entry-Bpo6ZY_I.mjs → detached-entry-KEu0_AXL.mjs} +1 -1
- package/dist/{device-BUoZyMoR.mjs → dev-client-HyqISM0h.mjs} +1178 -635
- package/dist/{device-RdujjHLB.mjs → device-D4U-xLty.mjs} +13 -20
- package/dist/{device-lease-Ffz_M5t0.mjs → device-lease-Crs-HkJY.mjs} +16 -9
- package/dist/{device-pool-BxRwdufO.mjs → device-pool-CnTAz8X1.mjs} +7 -7
- package/dist/{device-remote-ByN8P6CB.mjs → device-remote-AQ5rQPqr.mjs} +482 -35
- package/dist/{doctor-BMt156qe.mjs → doctor-B_Ei3bZu.mjs} +95 -107
- package/dist/{error-diagnostics-D1Kaf-eT.mjs → error-diagnostics-Vfz83GCF.mjs} +22 -16
- package/dist/exec-jIAlgilk.mjs +132 -0
- package/dist/{gc-v2YcoJvm.mjs → gc-Ckw8RQHi.mjs} +763 -126
- package/dist/{guide-BTAlD1_y.mjs → guide-BiAbhs1J.mjs} +891 -501
- package/dist/{guide-status-Craq9z0t.mjs → guide-status-BAMVU0ZA.mjs} +5 -3
- package/dist/{ios-BcCiI4TS.mjs → ios-BL2NFckr.mjs} +43 -20
- package/dist/{ios-BP04pY5f.mjs → ios-BzUJWk1K.mjs} +141 -175
- package/dist/{ios-device-CauFJiYx.mjs → ios-device-D972i9wf.mjs} +149 -52
- package/dist/{ios-device-CFXA46ez.mjs → ios-device-DPsSm0v_.mjs} +3 -2
- package/dist/launch-verify-Q_OtW1Rf.mjs +365 -0
- package/dist/{logs-CakdBTtm.mjs → logs-CI9NQSK7.mjs} +18 -13
- package/dist/{logs-query-BGL-Pl12.mjs → logs-query-Cqma3WIu.mjs} +36 -28
- package/dist/{metro-C7bcJ0uo.mjs → metro-DrLHaMn2.mjs} +78 -8
- package/dist/{named-ports-DzMOlmaX.mjs → named-ports-CmLQSIRj.mjs} +4 -4
- package/dist/{ndjson-BZwI1NBv.mjs → ndjson-9uFNRwfe.mjs} +36 -3
- package/dist/{ownership-Cp52QAK1.mjs → ownership-D15Op8vN.mjs} +3 -3
- package/dist/{ownership-wolE-0Do.mjs → ownership-DCQPuWEc.mjs} +26 -7
- package/dist/{ports-BIbJaKNW.mjs → ports-BNKoWVWZ.mjs} +3 -3
- package/dist/{process-output-Dl5uKE03.mjs → process-output-Fpl8PYi8.mjs} +1 -1
- package/dist/{project-DDZWf_16.mjs → project-DS112DYB.mjs} +8 -3
- package/dist/{reload-BdypPbjM.mjs → reload-ZNJUo1pl.mjs} +12 -13
- package/dist/{server-bare-BQkyxa_b.mjs → server-bare-DWkkcIxV.mjs} +2 -2
- package/dist/{server-expo-BVAA1OqJ.mjs → server-expo-B_lctBR3.mjs} +8 -7
- package/dist/server-expo-CeILEu86.mjs +2 -0
- package/dist/settings-BKNh5rl4.mjs +376 -0
- package/dist/{settings-BXXorVM2.mjs → settings-D030k0t4.mjs} +464 -152
- package/dist/settings.schema.json +989 -0
- package/dist/{teardown-BJqEzPo_.mjs → sim-pool-KaIsp2Ft.mjs} +14 -419
- package/dist/simslim-B_LsGLuJ.mjs +259 -0
- package/dist/{slot-launch-ZUUe0TQP.mjs → slot-launch-DU9A-gYw.mjs} +4 -4
- package/dist/spawn-claims-Dn3C_N6w.mjs +49 -0
- package/dist/{start-CmxtOKjU.mjs → start-DYkkKF0s.mjs} +27 -31
- package/dist/{state-DZobzxLW.mjs → state-NcJzMEBF.mjs} +5 -3
- package/dist/{stats-CLg5RuDS.mjs → stats-B63-JVAY.mjs} +4 -4
- package/dist/{stats-BYcZ6n1h.mjs → stats-DG9e66Rz.mjs} +66 -5
- package/dist/status-S6ehL4Ui.mjs +932 -0
- package/dist/{stop-C8JW6kKp.mjs → stop-BO28HGqF.mjs} +101 -25
- package/dist/{stop-B1kOpYei.mjs → stop-T1R-cZRz.mjs} +2 -2
- package/dist/supervisor-run.mjs +52 -34
- package/dist/{workspace-process-lock-BYfZz_S-.mjs → workspace-process-lock-DWaiRD0e.mjs} +14 -9
- package/dist/{workspace-state-BT5E3SA2.mjs → workspace-state-DF2gCFhx.mjs} +52 -29
- package/dist/worktree-DKhSF0UX.mjs +2 -0
- package/dist/{worktree-CFLA-6MX.mjs → worktree-LGB-UwgG.mjs} +603 -59
- package/dist/{worktree-FG_ZKKdb.mjs → worktree-R_cUlE7s.mjs} +62 -41
- package/dist/{xcode-B6YaWeg0.mjs → xcode-BZqyxh3e.mjs} +216 -58
- package/package.json +5 -6
- package/skill/SKILL.md +2 -0
- package/dist/app-install-BDbsSgCl.mjs +0 -1175
- package/dist/build-slots-C-oAHRT1.mjs +0 -151
- package/dist/dev-client-BmT-ioFI.mjs +0 -797
- package/dist/exec-B29XNuhP.mjs +0 -77
- package/dist/reclaim-KJ-0uWEF.mjs +0 -361
- package/dist/server-expo-YDDG3eP7.mjs +0 -2
- package/dist/status-DdkLki47.mjs +0 -426
- package/dist/{metro-store-CDDZHtPl.mjs → metro-store-DzeWkfqW.mjs} +1 -1
|
@@ -1,28 +1,27 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { a as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { d as quotedPath, l as phaseLine, u as plural } from "./command-output-
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { a as liveOwnedDeviceCount,
|
|
14
|
-
import { d as projectCmakeLauncher, g as androidPathRoomRemedy, h as androidPathRoomMessage, i as apkOutputsDir, m as androidPathRoom, r as resolveAndroidCompilerCache, t as readAndroidCasToolchain } from "./android-cas-
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import { n as hasInstalledDependencies, r as installedNpmTreeIsValid, t as dependencyState } from "./dependency-state-D0M7oKA7.mjs";
|
|
1
|
+
import { N as readJsonObject, g as loadConfig, l as getConcurrencyLimits, o as configCorruptRepair } from "./config-Cp9lM3wX.mjs";
|
|
2
|
+
import { t as getExecutor } from "./exec-jIAlgilk.mjs";
|
|
3
|
+
import { d as sharedBuildCache, g as workspaceDerivedData } from "./workspace-state-DF2gCFhx.mjs";
|
|
4
|
+
import { D as temporaryRoot, T as makeTemporaryDirectory, _ as repoRoot, a as dirtyFingerprintFiles, f as listWorktrees, p as locallyKnownUpstream, s as gitCommonDir, w as filesystemDevice, y as resolveSourceCheckout } from "./worktree-R_cUlE7s.mjs";
|
|
5
|
+
import { a as detectIsExpo, n as appProjectProblem, o as findProjectRoot } from "./project-DS112DYB.mjs";
|
|
6
|
+
import { C as projectOptimizations, D as remoteIosSetting, E as remoteAndroidSetting, F as unknownSettingKeys, M as settingShapeErrors, N as settingsLayers, V as settingDefinition, Y as resolveOptimizations, _ as iosSimSlimProfileSetting, i as SETTING_SHAPE_REMEDY, j as settingOrigin, k as resolveSettings, n as PATH_SETTINGS, q as compilerCacheFallbackMessage, r as SETTINGS_WITH_RESOLVE_TIME_FALLBACK, v as mergeSettingsLayers } from "./settings-D030k0t4.mjs";
|
|
7
|
+
import { C as listAdbDevices, S as hostSystemImageArch } from "./android-_y4Ohi5z.mjs";
|
|
8
|
+
import { d as quotedPath, f as refuseNoProject, l as phaseLine, u as plural } from "./command-output-gByVmIjy.mjs";
|
|
9
|
+
import { l as diffFingerprintSources, n as listBuildLocks, p as fingerprintProject } from "./build-lock-DPXPLgTc.mjs";
|
|
10
|
+
import { b as resolveEasCliBin, o as parkedMaxSetting, p as checkEasAuth$1, t as POOL_SETTING_REMEDY, v as ownerFromConfig, y as providerFromConfig } from "./sim-pool-KaIsp2Ft.mjs";
|
|
11
|
+
import { A as readHostMemoryPressure, k as hostMemoryPressureAdvice, u as listAllIosSims } from "./ios-BL2NFckr.mjs";
|
|
12
|
+
import { _ as listBuildSlots, h as podInstallCommand, i as ccacheEnabled, o as detectXcodeMajor } from "./xcode-BZqyxh3e.mjs";
|
|
13
|
+
import { a as liveOwnedDeviceCount, n as simslimIsOnPath } from "./simslim-B_LsGLuJ.mjs";
|
|
14
|
+
import { d as projectCmakeLauncher, g as androidPathRoomRemedy, h as androidPathRoomMessage, i as apkOutputsDir, m as androidPathRoom, r as resolveAndroidCompilerCache, t as readAndroidCasToolchain } from "./android-cas-eiExNLf7.mjs";
|
|
15
|
+
import { i as inspectStimVersions, n as recordDoctorRun, r as compareStimVersions } from "./guide-status-BAMVU0ZA.mjs";
|
|
16
|
+
import { n as hasInstalledDependencies, r as installedNpmTreeIsValid, t as dependencyState } from "./dependency-state-Bq5DcLGn.mjs";
|
|
18
17
|
import { existsSync, lstatSync, readFileSync, readdirSync, realpathSync, rmSync } from "node:fs";
|
|
19
18
|
import { InvalidArgumentError } from "commander";
|
|
20
|
-
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
21
19
|
import { existsSync as existsSync$1, lstatSync as lstatSync$1, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, realpathSync as realpathSync$1, renameSync as renameSync$1, rmSync as rmSync$1, writeFileSync as writeFileSync$1 } from "fs";
|
|
20
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from "path";
|
|
21
|
+
import { basename as basename$1, dirname as dirname$1, isAbsolute as isAbsolute$1, join as join$1, relative as relative$1, resolve as resolve$1, sep as sep$1 } from "node:path";
|
|
22
22
|
import { homedir } from "os";
|
|
23
|
-
import { dirname as dirname$1, isAbsolute as isAbsolute$1, join as join$1, relative as relative$1, resolve as resolve$1, sep as sep$1 } from "path";
|
|
24
|
-
import * as expoFingerprint from "@expo/fingerprint";
|
|
25
23
|
import chalk from "chalk";
|
|
24
|
+
import * as expoFingerprint from "@expo/fingerprint";
|
|
26
25
|
//#region src/diagnostics/sandbox.ts
|
|
27
26
|
/**
|
|
28
27
|
* What a sandboxed harness has to permit for Stim to work: its state
|
|
@@ -43,8 +42,8 @@ function detectHarness(env = process.env) {
|
|
|
43
42
|
function expandHome(value, home) {
|
|
44
43
|
const v = value.trim();
|
|
45
44
|
if (v === "~" || v === "$HOME") return home;
|
|
46
|
-
if (v.startsWith("~/")) return join
|
|
47
|
-
if (v.startsWith("$HOME/")) return join
|
|
45
|
+
if (v.startsWith("~/")) return join(home, v.slice(2));
|
|
46
|
+
if (v.startsWith("$HOME/")) return join(home, v.slice(6));
|
|
48
47
|
return v;
|
|
49
48
|
}
|
|
50
49
|
/**
|
|
@@ -54,7 +53,7 @@ function expandHome(value, home) {
|
|
|
54
53
|
*/
|
|
55
54
|
function sandboxBlocksStimHome(stimHome, home = homedir()) {
|
|
56
55
|
const dir = expandHome(stimHome, home);
|
|
57
|
-
const probe = join
|
|
56
|
+
const probe = join(dir, `.probe-${process.pid}-${Math.random().toString(36).slice(2)}`);
|
|
58
57
|
try {
|
|
59
58
|
mkdirSync$1(dir, { recursive: true });
|
|
60
59
|
writeFileSync$1(probe, "");
|
|
@@ -67,14 +66,14 @@ function sandboxBlocksStimHome(stimHome, home = homedir()) {
|
|
|
67
66
|
}
|
|
68
67
|
/** Where a per-user, gitignored Claude Code settings file belongs for this project. */
|
|
69
68
|
function claudeLocalSettingsPath(root) {
|
|
70
|
-
return join
|
|
69
|
+
return join(root, ".claude", "settings.local.json");
|
|
71
70
|
}
|
|
72
71
|
/** Every settings file that may already carry the allowance, most local first. */
|
|
73
72
|
function allowanceSearchPaths(settingsRoot, home = homedir()) {
|
|
74
73
|
return [
|
|
75
74
|
claudeLocalSettingsPath(settingsRoot),
|
|
76
|
-
join
|
|
77
|
-
join
|
|
75
|
+
join(settingsRoot, ".claude", "settings.json"),
|
|
76
|
+
join(home, ".claude", "settings.json")
|
|
78
77
|
];
|
|
79
78
|
}
|
|
80
79
|
function isPlainObject(value) {
|
|
@@ -114,10 +113,10 @@ function nested(source, ...keys) {
|
|
|
114
113
|
function covers(entry, target, home) {
|
|
115
114
|
const posix = (value) => {
|
|
116
115
|
const expanded = expandHome(value, home);
|
|
117
|
-
return sep
|
|
116
|
+
return sep === "/" ? expanded : expanded.replaceAll(sep, "/");
|
|
118
117
|
};
|
|
119
|
-
const e = posix(entry.replace(/\/+\*+$/, "").replace(/\/+$/, "")
|
|
120
|
-
const t = posix(target.replace(/\/+$/, "")
|
|
118
|
+
const e = posix(entry).replace(/\/+\*+$/, "").replace(/\/+$/, "");
|
|
119
|
+
const t = posix(target).replace(/\/+$/, "");
|
|
121
120
|
return e === t || t.startsWith(`${e}/`);
|
|
122
121
|
}
|
|
123
122
|
/**
|
|
@@ -186,7 +185,7 @@ function applyClaudeAllowance(path, allowance) {
|
|
|
186
185
|
status: "refused",
|
|
187
186
|
reason: `${path} holds a "${blocker}" that is not an object, so Stim cannot merge into it without discarding that value.`
|
|
188
187
|
};
|
|
189
|
-
mkdirSync$1(dirname
|
|
188
|
+
mkdirSync$1(dirname(path), { recursive: true });
|
|
190
189
|
const tmp = `${path}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
191
190
|
writeFileSync$1(tmp, `${JSON.stringify(withAllowance(existing, allowance), null, 2)}\n`);
|
|
192
191
|
try {
|
|
@@ -247,14 +246,14 @@ function checkStorageLayout(projectRoot, { platform, host = process.platform, de
|
|
|
247
246
|
const source = resolveSourceCheckout(target);
|
|
248
247
|
check("Worktree copy", ["path" in source ? source.path : target, target], "Keep the source checkout and linked worktree on the same volume to share file blocks when warming.");
|
|
249
248
|
const cache = sharedBuildCache();
|
|
250
|
-
check("Cached app/APK staging", [cache, stagingRoot(join(cache, "artifact.app"))], temporaryFix);
|
|
249
|
+
check("Cached app/APK staging", [cache, stagingRoot(join$1(cache, "artifact.app"))], temporaryFix);
|
|
251
250
|
const cacheFix = "Place STIM_BUILD_CACHE / machine caches.buildCache on the build-output volume, or accept the full-copy cost of keeping the cache on a separate volume.";
|
|
252
|
-
if ((platform === "ios" || platform !== "android" && existsSync(join(projectRoot, "ios"))) && host === "darwin") {
|
|
253
|
-
const output = join(workspaceDerivedData(projectRoot), "Build", "Products");
|
|
251
|
+
if ((platform === "ios" || platform !== "android" && existsSync(join$1(projectRoot, "ios"))) && host === "darwin") {
|
|
252
|
+
const output = join$1(workspaceDerivedData(projectRoot), "Build", "Products");
|
|
254
253
|
check("iOS build-cache storage", [output, cache], cacheFix);
|
|
255
|
-
check("iOS device app staging", [output, stagingRoot(join(output, "artifact.app"))], temporaryFix);
|
|
254
|
+
check("iOS device app staging", [output, stagingRoot(join$1(output, "artifact.app"))], temporaryFix);
|
|
256
255
|
}
|
|
257
|
-
if (platform === "android" || platform !== "ios" && existsSync(join(projectRoot, "android"))) check("Android build-cache storage", [apkOutputsDir(projectRoot), cache], cacheFix);
|
|
256
|
+
if (platform === "android" || platform !== "ios" && existsSync(join$1(projectRoot, "android"))) check("Android build-cache storage", [apkOutputsDir(projectRoot), cache], cacheFix);
|
|
258
257
|
} catch (error) {
|
|
259
258
|
findings.push({
|
|
260
259
|
level: "cost",
|
|
@@ -338,23 +337,23 @@ function parseIosDebugArchitectures(output) {
|
|
|
338
337
|
};
|
|
339
338
|
}
|
|
340
339
|
function inspectIosDebugArchitectures(projectRoot) {
|
|
341
|
-
const iosRoot = join(projectRoot, "ios");
|
|
340
|
+
const iosRoot = join$1(projectRoot, "ios");
|
|
342
341
|
if (!existsSync(iosRoot)) return [];
|
|
343
342
|
const findings = [];
|
|
344
343
|
const unknown = [];
|
|
345
344
|
let projects;
|
|
346
345
|
try {
|
|
347
|
-
projects = readdirSync(iosRoot).filter((name) => name.endsWith(".xcodeproj")).toSorted().map((name) => join(iosRoot, name));
|
|
346
|
+
projects = readdirSync(iosRoot).filter((name) => name.endsWith(".xcodeproj")).toSorted().map((name) => join$1(iosRoot, name));
|
|
348
347
|
} catch {
|
|
349
348
|
projects = [];
|
|
350
349
|
}
|
|
351
350
|
if (!projects.length) unknown.push("app project");
|
|
352
|
-
const pods = join(iosRoot, "Pods", "Pods.xcodeproj");
|
|
351
|
+
const pods = join$1(iosRoot, "Pods", "Pods.xcodeproj");
|
|
353
352
|
if (existsSync(pods)) projects.push(pods);
|
|
354
|
-
else if (existsSync(join(iosRoot, "Podfile"))) unknown.push("Pods project (not generated)");
|
|
353
|
+
else if (existsSync(join$1(iosRoot, "Podfile"))) unknown.push("Pods project (not generated)");
|
|
355
354
|
const deadline = Date.now() + 6e4;
|
|
356
355
|
for (const project of projects) {
|
|
357
|
-
const label = relative(projectRoot, project);
|
|
356
|
+
const label = relative$1(projectRoot, project);
|
|
358
357
|
const timeoutMs = Math.min(3e4, deadline - Date.now());
|
|
359
358
|
if (timeoutMs <= 0) {
|
|
360
359
|
unknown.push(label);
|
|
@@ -416,13 +415,13 @@ function children(path) {
|
|
|
416
415
|
}
|
|
417
416
|
}
|
|
418
417
|
function moduleRoots(root) {
|
|
419
|
-
const modules = [join(root, "android", "app")];
|
|
420
|
-
const dependencies = join(root, "node_modules");
|
|
418
|
+
const modules = [join$1(root, "android", "app")];
|
|
419
|
+
const dependencies = join$1(root, "node_modules");
|
|
421
420
|
for (const name of children(dependencies)) {
|
|
422
421
|
if (name.startsWith(".")) continue;
|
|
423
|
-
const entry = join(dependencies, name);
|
|
424
|
-
const packages = name.startsWith("@") ? children(entry).map((child) => join(entry, child)) : [entry];
|
|
425
|
-
modules.push(...packages.map((pkg) => join(pkg, "android")));
|
|
422
|
+
const entry = join$1(dependencies, name);
|
|
423
|
+
const packages = name.startsWith("@") ? children(entry).map((child) => join$1(entry, child)) : [entry];
|
|
424
|
+
modules.push(...packages.map((pkg) => join$1(pkg, "android")));
|
|
426
425
|
}
|
|
427
426
|
return modules;
|
|
428
427
|
}
|
|
@@ -430,7 +429,7 @@ function cacheFiles(base, depth = 0) {
|
|
|
430
429
|
const files = [];
|
|
431
430
|
for (const name of children(base)) {
|
|
432
431
|
if (depth === 0 && /^stim-[a-f0-9]{16}$/.test(name)) continue;
|
|
433
|
-
const path = join(base, name);
|
|
432
|
+
const path = join$1(base, name);
|
|
434
433
|
const entry = lstatSync(path);
|
|
435
434
|
if (entry.isSymbolicLink()) continue;
|
|
436
435
|
if (name === "CMakeCache.txt" && entry.isFile()) files.push(path);
|
|
@@ -439,8 +438,8 @@ function cacheFiles(base, depth = 0) {
|
|
|
439
438
|
return files;
|
|
440
439
|
}
|
|
441
440
|
function readCxxLauncherStates(root) {
|
|
442
|
-
return moduleRoots(root).flatMap((module) => cacheFiles(join(module, ".cxx")).map((path) => ({
|
|
443
|
-
path: relative(root, path),
|
|
441
|
+
return moduleRoots(root).flatMap((module) => cacheFiles(join$1(module, ".cxx")).map((path) => ({
|
|
442
|
+
path: relative$1(root, path),
|
|
444
443
|
launcher: parseCmakeCacheLauncher(readFileSync(path, "utf8"))
|
|
445
444
|
})));
|
|
446
445
|
}
|
|
@@ -450,13 +449,13 @@ function declaredLauncher(module) {
|
|
|
450
449
|
"build.gradle.kts",
|
|
451
450
|
"CMakeLists.txt"
|
|
452
451
|
].some((name) => {
|
|
453
|
-
const path = join(module, name);
|
|
452
|
+
const path = join$1(module, name);
|
|
454
453
|
return existsSync(path) && Boolean(projectCmakeLauncher(readFileSync(path, "utf8")));
|
|
455
454
|
});
|
|
456
455
|
}
|
|
457
456
|
function contained(root, path) {
|
|
458
|
-
const rel = relative(root, path);
|
|
459
|
-
return rel !== "" && rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel);
|
|
457
|
+
const rel = relative$1(root, path);
|
|
458
|
+
return rel !== "" && rel !== ".." && !rel.startsWith(`..${sep$1}`) && !isAbsolute$1(rel);
|
|
460
459
|
}
|
|
461
460
|
function selectedCompilerCache(root) {
|
|
462
461
|
try {
|
|
@@ -480,24 +479,24 @@ function repairCxxLauncherState(root) {
|
|
|
480
479
|
};
|
|
481
480
|
if (selectedCompilerCache(root) !== "ccache") return result;
|
|
482
481
|
if (!getExecutor().findExecutable("ccache")) return result;
|
|
483
|
-
const appOverrides = declaredLauncher(join(root, "android", "app"));
|
|
482
|
+
const appOverrides = declaredLauncher(join$1(root, "android", "app"));
|
|
484
483
|
const targets = readCxxLauncherStates(root).filter(({ launcher }) => {
|
|
485
484
|
if (!launcher) return true;
|
|
486
485
|
const command = launcher.split(";")[0]?.trim();
|
|
487
|
-
return Boolean(command && isAbsolute(command) && basename(command) === "ccache" && !existsSync(command));
|
|
486
|
+
return Boolean(command && isAbsolute$1(command) && basename$1(command) === "ccache" && !existsSync(command));
|
|
488
487
|
});
|
|
489
488
|
for (const state of targets) {
|
|
490
|
-
const target = dirname(join(root, state.path));
|
|
491
|
-
const label = relative(root, target);
|
|
489
|
+
const target = dirname$1(join$1(root, state.path));
|
|
490
|
+
const label = relative$1(root, target);
|
|
492
491
|
try {
|
|
493
492
|
let cxx = target;
|
|
494
|
-
while (contained(root, cxx) && basename(cxx) !== ".cxx") cxx = dirname(cxx);
|
|
495
|
-
if (basename(cxx) !== ".cxx" || target === cxx) throw new Error("unrecognized generated CMake layout");
|
|
496
|
-
if (appOverrides || declaredLauncher(dirname(cxx))) throw new Error("project configures its own compiler launcher");
|
|
493
|
+
while (contained(root, cxx) && basename$1(cxx) !== ".cxx") cxx = dirname$1(cxx);
|
|
494
|
+
if (basename$1(cxx) !== ".cxx" || target === cxx) throw new Error("unrecognized generated CMake layout");
|
|
495
|
+
if (appOverrides || declaredLauncher(dirname$1(cxx))) throw new Error("project configures its own compiler launcher");
|
|
497
496
|
const canonicalTarget = realpathSync(target);
|
|
498
497
|
if (!contained(canonicalRoot, canonicalTarget)) throw new Error("generated directory resolves outside this checkout");
|
|
499
|
-
if (realpathSync(cxx) !== join(realpathSync(dirname(cxx)), ".cxx")) throw new Error(".cxx is a symbolic link");
|
|
500
|
-
const gitPath = relative(canonicalRoot, canonicalTarget);
|
|
498
|
+
if (realpathSync(cxx) !== join$1(realpathSync(dirname$1(cxx)), ".cxx")) throw new Error(".cxx is a symbolic link");
|
|
499
|
+
const gitPath = relative$1(canonicalRoot, canonicalTarget);
|
|
501
500
|
if (getExecutor().runFile("git", [
|
|
502
501
|
"ls-files",
|
|
503
502
|
"-z",
|
|
@@ -551,14 +550,13 @@ function readMachineSettings(context) {
|
|
|
551
550
|
layers: [],
|
|
552
551
|
corrupt: {
|
|
553
552
|
level: "note",
|
|
554
|
-
title: "The Stim config is not valid JSON",
|
|
553
|
+
title: "The Stim config is not a valid JSON object",
|
|
555
554
|
detail: `${String(error.message).split("\n")[0]}. Every setting and device record lives in that file, so no other machine-level check can run until it parses.`,
|
|
556
555
|
fix: configCorruptRepair()
|
|
557
556
|
}
|
|
558
557
|
};
|
|
559
558
|
}
|
|
560
559
|
}
|
|
561
|
-
const PATH_SETTING_ENVIRONMENT = { "optimizations.android.casToolchain": "STIM_ANDROID_CAS_TOOLCHAIN" };
|
|
562
560
|
const PATH_SETTINGS_TRIMMED_BY_THEIR_CONSUMER = /* @__PURE__ */ new Set(["android.keystore"]);
|
|
563
561
|
function checkMachineSettings({ settings, layers, projectRoot, optimizations = null, reportedElsewhere = [], exists = existsSync, env = process.env }) {
|
|
564
562
|
const findings = [];
|
|
@@ -570,7 +568,7 @@ function checkMachineSettings({ settings, layers, projectRoot, optimizations = n
|
|
|
570
568
|
if (reported) skip.add(reported.key);
|
|
571
569
|
if (!optimizations) for (const key of SETTINGS_WITH_RESOLVE_TIME_FALLBACK) skip.add(key);
|
|
572
570
|
for (const key of PATH_SETTINGS) {
|
|
573
|
-
const variable =
|
|
571
|
+
const variable = settingDefinition(key)?.env;
|
|
574
572
|
if (skip.has(key) || variable && skip.has(variable)) continue;
|
|
575
573
|
const override = variable ? env[variable] : void 0;
|
|
576
574
|
if (variable && override) {
|
|
@@ -639,7 +637,7 @@ function compilerCacheFinding({ fallback, optimizations, file }) {
|
|
|
639
637
|
function missingPath(value, projectRoot, exists, trim = false) {
|
|
640
638
|
const opened = trim ? value.trim() : value;
|
|
641
639
|
if (opened.trim() === "") return null;
|
|
642
|
-
const path = isAbsolute(opened) ? opened : resolve(projectRoot, opened);
|
|
640
|
+
const path = isAbsolute$1(opened) ? opened : resolve$1(projectRoot, opened);
|
|
643
641
|
if (exists(path)) return null;
|
|
644
642
|
return opened === opened.trim() ? path : JSON.stringify(path);
|
|
645
643
|
}
|
|
@@ -653,22 +651,15 @@ function finding(level, title, detail, fix) {
|
|
|
653
651
|
fix
|
|
654
652
|
};
|
|
655
653
|
}
|
|
656
|
-
function readJson(path) {
|
|
657
|
-
try {
|
|
658
|
-
return JSON.parse(readFileSync$1(path, "utf-8"));
|
|
659
|
-
} catch {
|
|
660
|
-
return null;
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
654
|
function mainCheckoutProjectRoot(projectRoot) {
|
|
664
655
|
const currentRepoRoot = repoRoot(projectRoot);
|
|
665
656
|
if (!currentRepoRoot) return projectRoot;
|
|
666
657
|
try {
|
|
667
658
|
const source = resolveSourceCheckout(currentRepoRoot);
|
|
668
659
|
if ("refusal" in source) return projectRoot;
|
|
669
|
-
const projectRel = relative
|
|
660
|
+
const projectRel = relative(currentRepoRoot, realpathSync$1(projectRoot));
|
|
670
661
|
if (projectRel.startsWith("..")) return projectRoot;
|
|
671
|
-
return resolve
|
|
662
|
+
return resolve(source.path, projectRel);
|
|
672
663
|
} catch {
|
|
673
664
|
return projectRoot;
|
|
674
665
|
}
|
|
@@ -687,11 +678,11 @@ function brokenPodLinks(podsRoot) {
|
|
|
687
678
|
}
|
|
688
679
|
}
|
|
689
680
|
function hasIosWarmOutput(root) {
|
|
690
|
-
if (existsSync$1(join
|
|
681
|
+
if (existsSync$1(join(root, "ios", "build"))) return true;
|
|
691
682
|
const derivedData = workspaceDerivedData(root);
|
|
692
|
-
if (existsSync$1(join
|
|
683
|
+
if (existsSync$1(join(derivedData, "Build", "Products"))) return true;
|
|
693
684
|
try {
|
|
694
|
-
return readdirSync$1(derivedData).some((entry) => /^scheme-[a-f0-9]{64}$/.test(entry) && existsSync$1(join
|
|
685
|
+
return readdirSync$1(derivedData).some((entry) => /^scheme-[a-f0-9]{64}$/.test(entry) && existsSync$1(join(derivedData, entry, "Build", "Products")));
|
|
695
686
|
} catch {
|
|
696
687
|
return false;
|
|
697
688
|
}
|
|
@@ -720,8 +711,8 @@ function mainOperation(root) {
|
|
|
720
711
|
"--git-dir"
|
|
721
712
|
])?.trim();
|
|
722
713
|
if (!gitDir) return null;
|
|
723
|
-
if (existsSync$1(join
|
|
724
|
-
return existsSync$1(join
|
|
714
|
+
if (existsSync$1(join(gitDir, "rebase-merge")) || existsSync$1(join(gitDir, "rebase-apply"))) return "rebase";
|
|
715
|
+
return existsSync$1(join(gitDir, "MERGE_HEAD")) ? "merge" : null;
|
|
725
716
|
}
|
|
726
717
|
function dirtyTrackedPaths(root) {
|
|
727
718
|
return (getExecutor().runFileQuiet("git", [
|
|
@@ -785,9 +776,9 @@ function checkMainCheckout(projectRoot, { npmTreeValid, brokenPods = void 0, ups
|
|
|
785
776
|
if ((npmTreeValid === void 0 ? installedNpmTreeIsValid(dependencies.root) : npmTreeValid) === false) findings.push(finding("cost", "The source checkout dependency tree is stale", `npm reports that ${dependencies.root}/node_modules does not match the project dependency graph. Copying it makes each worktree start from the same invalid state.`, `Run \`${installCommand}\` before creating native worktrees, or let \`stim worktree warm --refresh\` run it from a linked worktree.`));
|
|
786
777
|
}
|
|
787
778
|
}
|
|
788
|
-
const podfileLock = join
|
|
789
|
-
const podManifest = join
|
|
790
|
-
const podsRoot = join
|
|
779
|
+
const podfileLock = join(mainRoot, "ios", "Podfile.lock");
|
|
780
|
+
const podManifest = join(mainRoot, "ios", "Pods", "Manifest.lock");
|
|
781
|
+
const podsRoot = join(mainRoot, "ios", "Pods");
|
|
791
782
|
if (localIos && existsSync$1(podfileLock)) {
|
|
792
783
|
let podsState = null;
|
|
793
784
|
if (!existsSync$1(podManifest)) podsState = "missing";
|
|
@@ -797,18 +788,18 @@ function checkMainCheckout(projectRoot, { npmTreeValid, brokenPods = void 0, ups
|
|
|
797
788
|
podsState = "stale";
|
|
798
789
|
}
|
|
799
790
|
if (podsState) {
|
|
800
|
-
const iosRoot = join
|
|
791
|
+
const iosRoot = join(mainRoot, "ios");
|
|
801
792
|
const podCommand = `cd ${quotedPath(iosRoot)} && ${podInstallCommand(mainRoot)}`;
|
|
802
793
|
findings.push(finding("cost", `The source checkout CocoaPods state is ${podsState}`, `ios/Pods cannot be reused safely because its Manifest.lock ${podsState === "missing" ? "is absent" : "does not match ios/Podfile.lock"}.`, `Run \`${podCommand}\` before creating native worktrees, or let \`stim worktree warm --refresh\` run it from a linked worktree.`));
|
|
803
794
|
}
|
|
804
795
|
const broken = brokenPods === void 0 && existsSync$1(podsRoot) ? brokenPodLinks(podsRoot) : brokenPods || [];
|
|
805
796
|
if (broken.length) {
|
|
806
|
-
const iosRoot = join
|
|
797
|
+
const iosRoot = join(mainRoot, "ios");
|
|
807
798
|
const podCommand = `cd ${quotedPath(iosRoot)} && ${podInstallCommand(mainRoot, "--clean-install")}`;
|
|
808
799
|
findings.push(finding("cost", "The source checkout CocoaPods state has broken links", `${broken.length} symlink${broken.length === 1 ? "" : "s"} under ios/Pods point to missing files. Worktrees copy these broken links and can fail during compilation. First: ${broken[0]}.`, `Run \`${podCommand}\` before creating native worktrees.`));
|
|
809
800
|
}
|
|
810
801
|
}
|
|
811
|
-
const coldPlatforms = [localIos && existsSync$1(join
|
|
802
|
+
const coldPlatforms = [localIos && existsSync$1(join(mainRoot, "ios")) && !hasIosWarmOutput(mainRoot) ? "iOS" : null, platform !== "ios" && existsSync$1(join(mainRoot, "android")) && !existsSync$1(join(mainRoot, "android", "build")) && !existsSync$1(join(mainRoot, "android", "app", "build")) ? "Android" : null].filter((coldPlatform) => coldPlatform !== null);
|
|
812
803
|
if (coldPlatforms.length) findings.push(finding("note", `The source checkout has no ${coldPlatforms.join(" or ")} warm build output`, "The shared Stim artifact or compilation cache can still be warm. Building the source checkout once gives later native worktrees the strongest warm starting point.", `When more native worktrees are expected, run \`stim start\`, \`stim ${coldPlatforms[0] === "iOS" ? "ios" : "android"}\`, and \`stim stop\` from ${mainRoot}.`));
|
|
813
804
|
if (linkedWorktrees === void 0 ? hasLinkedWorktree(projectRoot) : linkedWorktrees) findings.push(...seedFindings(mainRoot, upstream === void 0 ? locallyKnownUpstream(mainRoot) : upstream));
|
|
814
805
|
return findings;
|
|
@@ -855,7 +846,7 @@ function checkCcacheInstalled(onPath) {
|
|
|
855
846
|
}
|
|
856
847
|
function launcherPath(launcher) {
|
|
857
848
|
const command = launcher?.split(";")[0]?.trim();
|
|
858
|
-
return command && isAbsolute
|
|
849
|
+
return command && isAbsolute(command) ? command : null;
|
|
859
850
|
}
|
|
860
851
|
function checkCxxCompilerLauncher({ states, ccacheOnPath, launcherExists = existsSync$1 }) {
|
|
861
852
|
const missing = states.map((state) => ({
|
|
@@ -926,7 +917,7 @@ function checkIosHost(platform, host) {
|
|
|
926
917
|
}
|
|
927
918
|
function checkXcodeEnvLineEndings(projectRoot, platform, host) {
|
|
928
919
|
if (platform === "android" || host !== "win32") return null;
|
|
929
|
-
const xcodeEnv = join
|
|
920
|
+
const xcodeEnv = join(projectRoot, "ios", ".xcode.env");
|
|
930
921
|
if (!existsSync$1(xcodeEnv)) return null;
|
|
931
922
|
let content;
|
|
932
923
|
try {
|
|
@@ -940,7 +931,7 @@ function checkXcodeEnvLineEndings(projectRoot, platform, host) {
|
|
|
940
931
|
function runDoctor(projectRoot, { readFile = readFileSync$1, xcodeMajor = null, easAuth = checkEasAuth$1, concurrency = getConcurrencyLimits, liveDevices = null, activeBuilds = null, remoteEnv = process.env, lookupAgentDevice = null, lookupEasCli = null, lookupSimSlim = null, memoryPressure = readHostMemoryPressure, lookupCcache = null, platform, host = process.platform } = {}) {
|
|
941
932
|
const localIos = platform !== "android" && host === "darwin";
|
|
942
933
|
const read = (rel) => {
|
|
943
|
-
const p = join
|
|
934
|
+
const p = join(projectRoot, rel);
|
|
944
935
|
if (!existsSync$1(p)) return null;
|
|
945
936
|
try {
|
|
946
937
|
return readFile(p, "utf-8");
|
|
@@ -956,15 +947,15 @@ function runDoctor(projectRoot, { readFile = readFileSync$1, xcodeMajor = null,
|
|
|
956
947
|
});
|
|
957
948
|
if (machineSettings.corrupt) return [machineSettings.corrupt];
|
|
958
949
|
const projectSettings = machineSettings.settings;
|
|
959
|
-
const pkg =
|
|
960
|
-
const appConfig =
|
|
950
|
+
const pkg = readJsonObject(join(projectRoot, "package.json"));
|
|
951
|
+
const appConfig = readJsonObject(join(projectRoot, "app.json"));
|
|
961
952
|
const dynamicConfig = appConfig ? null : [
|
|
962
953
|
"app.config.ts",
|
|
963
954
|
"app.config.js",
|
|
964
955
|
"app.config.mjs"
|
|
965
|
-
].find((f) => existsSync$1(join
|
|
966
|
-
const podfileProperties =
|
|
967
|
-
const podfile = read(join
|
|
956
|
+
].find((f) => existsSync$1(join(projectRoot, f))) || null;
|
|
957
|
+
const podfileProperties = readJsonObject(join(projectRoot, "ios", "Podfile.properties.json"));
|
|
958
|
+
const podfile = read(join("ios", "Podfile"));
|
|
968
959
|
const metroConfig = read("metro.config.js") ?? read("metro.config.cjs");
|
|
969
960
|
const isExpo = detectIsExpo(projectRoot);
|
|
970
961
|
const expoRange = (pkg?.dependencies)?.expo || "";
|
|
@@ -986,9 +977,7 @@ function runDoctor(projectRoot, { readFile = readFileSync$1, xcodeMajor = null,
|
|
|
986
977
|
optimizations: resolveOptimizations(projectSettings),
|
|
987
978
|
use: readAndroidCasToolchain
|
|
988
979
|
}).optimizations;
|
|
989
|
-
} catch
|
|
990
|
-
settingShapeFindings.push(finding("cost", "Invalid optimization setting", error.message, SETTING_SHAPE_REMEDY));
|
|
991
|
-
}
|
|
980
|
+
} catch {}
|
|
992
981
|
const remoteBuildCache = optimizations?.buildCache && optimizations.remoteBuildCache;
|
|
993
982
|
const easFinding = remoteBuildCache && provider === "eas" ? checkEasAuth({
|
|
994
983
|
provider,
|
|
@@ -1072,7 +1061,7 @@ function checkAndroidPathRoom(projectRoot, platform, host, hostArch = process.ar
|
|
|
1072
1061
|
};
|
|
1073
1062
|
}
|
|
1074
1063
|
function androidCcacheFindings(projectRoot, platform, lookupCcache) {
|
|
1075
|
-
if (platform !== "android" && !existsSync$1(join
|
|
1064
|
+
if (platform !== "android" && !existsSync$1(join(projectRoot, "android"))) return [];
|
|
1076
1065
|
const onPath = lookupCcache ? lookupCcache() : ccacheIsOnPath();
|
|
1077
1066
|
let cxx;
|
|
1078
1067
|
try {
|
|
@@ -1135,7 +1124,7 @@ function checkFingerprintParity({ projectHash, worktreeHash, changed = [], dirty
|
|
|
1135
1124
|
}
|
|
1136
1125
|
function gitMetadataAt(path) {
|
|
1137
1126
|
try {
|
|
1138
|
-
const git = lstatSync$1(join
|
|
1127
|
+
const git = lstatSync$1(join(path, ".git"));
|
|
1139
1128
|
return git.isFile() || git.isDirectory();
|
|
1140
1129
|
} catch {
|
|
1141
1130
|
return false;
|
|
@@ -1150,14 +1139,14 @@ function listDirectory(dir) {
|
|
|
1150
1139
|
}
|
|
1151
1140
|
function hasLinkedPackageWithGit(projectRoot) {
|
|
1152
1141
|
const root = repoRoot(projectRoot) ?? projectRoot;
|
|
1153
|
-
for (let dir = projectRoot;; dir = dirname
|
|
1154
|
-
if (linkedPackageWithGitIn(join
|
|
1155
|
-
if (dir === root || dirname
|
|
1142
|
+
for (let dir = projectRoot;; dir = dirname(dir)) {
|
|
1143
|
+
if (linkedPackageWithGitIn(join(dir, "node_modules"))) return true;
|
|
1144
|
+
if (dir === root || dirname(dir) === dir || relative(root, dirname(dir)).startsWith("..")) return false;
|
|
1156
1145
|
}
|
|
1157
1146
|
}
|
|
1158
1147
|
function linkedPackageWithGitIn(nodeModules) {
|
|
1159
|
-
return listDirectory(nodeModules).filter((entry) => !entry.startsWith(".")).flatMap((entry) => entry.startsWith("@") ? listDirectory(join
|
|
1160
|
-
const root = join
|
|
1148
|
+
return listDirectory(nodeModules).filter((entry) => !entry.startsWith(".")).flatMap((entry) => entry.startsWith("@") ? listDirectory(join(nodeModules, entry)).map((child) => join(entry, child)) : [entry]).some((name) => {
|
|
1149
|
+
const root = join(nodeModules, name);
|
|
1161
1150
|
try {
|
|
1162
1151
|
return lstatSync$1(root).isSymbolicLink() && gitMetadataAt(root);
|
|
1163
1152
|
} catch {
|
|
@@ -1209,14 +1198,14 @@ async function detectFingerprintParity(projectRoot, { createFingerprint = expoFi
|
|
|
1209
1198
|
"--git-dir"
|
|
1210
1199
|
], { timeoutMs: 1e4 }) == null) return null;
|
|
1211
1200
|
if (hasInstalledDependencies(projectRoot)) return null;
|
|
1212
|
-
const platform = selectedPlatform ?? (existsSync$1(join
|
|
1201
|
+
const platform = selectedPlatform ?? (existsSync$1(join(projectRoot, "ios")) ? "ios" : existsSync$1(join(projectRoot, "android")) ? "android" : void 0);
|
|
1213
1202
|
let base;
|
|
1214
1203
|
try {
|
|
1215
1204
|
base = makeTemporaryDirectory(projectRoot, "stim-parity-");
|
|
1216
1205
|
} catch {
|
|
1217
1206
|
return null;
|
|
1218
1207
|
}
|
|
1219
|
-
const worktree = join
|
|
1208
|
+
const worktree = join(base, "head");
|
|
1220
1209
|
if (exec.runFileQuiet("git", [
|
|
1221
1210
|
"-C",
|
|
1222
1211
|
projectRoot,
|
|
@@ -1382,11 +1371,10 @@ function applySandboxFix(root, env = process.env) {
|
|
|
1382
1371
|
console.error(chalk.dim("Added writes to Stim's state directory, the simulator XPC service, and local port binding. Claude Code reads project settings from the directory a session starts in, so this file only counts for sessions rooted there. Restart the session for it to take effect."));
|
|
1383
1372
|
}
|
|
1384
1373
|
function doctorCommand(program, version, inspectVersions = inspectStimVersions, host = process.platform) {
|
|
1385
|
-
program.command("doctor").description("Inspect the source checkout and report project state that can make native worktrees slow or invalid. The checkout is left untouched unless --fix is passed; --platform filters native findings. Each run is recorded in Stim state so guide can say when doctor is due.").option("--json", "print the findings as JSON").option("--platform <platform>", "report shared findings plus only this native platform: ios or android", parseDoctorPlatform).option("--fix", "repair the sandbox allowance when the report names it, and stale Android .cxx configurations in this checkout. Stop native builds first. Generated CMake output must be ignored and untracked; custom launcher settings and source files are preserved.").action(async (opts) => {
|
|
1374
|
+
program.command("doctor").description("Inspect the source checkout and report project state that can make native worktrees slow or invalid. The checkout is left untouched unless --fix is passed; --platform filters native findings. Each run in a React Native or Expo app is recorded in Stim state so guide can say when doctor is due.").option("--json", "print the findings as JSON").option("--platform <platform>", "report shared findings plus only this native platform: ios or android", parseDoctorPlatform).option("--fix", "repair the sandbox allowance when the report names it, and stale Android .cxx configurations in this checkout. Stop native builds first. Generated CMake output must be ignored and untracked; custom launcher settings and source files are preserved.").action(async (opts) => {
|
|
1386
1375
|
const root = findProjectRoot(process.cwd());
|
|
1387
1376
|
if (!root) {
|
|
1388
|
-
|
|
1389
|
-
process.exitCode = 1;
|
|
1377
|
+
refuseNoProject({ json: Boolean(opts.json) });
|
|
1390
1378
|
return;
|
|
1391
1379
|
}
|
|
1392
1380
|
if (opts.fix) {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { r as readWorkspaceState } from "./workspace-state-
|
|
4
|
-
import { d as readWorkspaceLaunches } from "./state-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { r as androidHome, s as androidToolCwd } from "./android-
|
|
8
|
-
import { n as parseLogcatLine, t as androidClockOffset } from "./android-
|
|
9
|
-
import {
|
|
10
|
-
import { a as parseLease, n as fileLeaseIo, t as deviceLeasePath } from "./device-lease-
|
|
11
|
-
import {
|
|
1
|
+
import { A as withDirLock, H as deviceSlotKey, U as deviceSlotPlatforms, f as getProject } from "./config-Cp9lM3wX.mjs";
|
|
2
|
+
import { t as getExecutor } from "./exec-jIAlgilk.mjs";
|
|
3
|
+
import { r as readWorkspaceState } from "./workspace-state-DF2gCFhx.mjs";
|
|
4
|
+
import { d as readWorkspaceLaunches } from "./state-NcJzMEBF.mjs";
|
|
5
|
+
import { r as deviceConsoleLevel } from "./ios-device-DPsSm0v_.mjs";
|
|
6
|
+
import { c as resolveProjectMetro } from "./metro-DrLHaMn2.mjs";
|
|
7
|
+
import { r as androidHome, s as androidToolCwd } from "./android-_y4Ohi5z.mjs";
|
|
8
|
+
import { n as parseLogcatLine, t as androidClockOffset } from "./android-DEgo4oCo.mjs";
|
|
9
|
+
import { v as launchErrorPreview } from "./command-output-gByVmIjy.mjs";
|
|
10
|
+
import { a as parseLease, n as fileLeaseIo, t as deviceLeasePath } from "./device-lease-Crs-HkJY.mjs";
|
|
11
|
+
import { f as sortByTs, n as attachExpoErrorContext, u as readLogRecords } from "./logs-query-Cqma3WIu.mjs";
|
|
12
12
|
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
13
|
-
import { createHash, randomUUID } from "node:crypto";
|
|
14
13
|
import { basename, dirname, join, resolve, sep } from "node:path";
|
|
14
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
15
15
|
import { homedir } from "node:os";
|
|
16
16
|
//#region src/diagnostics/diagnostic-store.ts
|
|
17
17
|
/** Publishes an immutable diagnostic snapshot atomically; existing evidence wins. */
|
|
@@ -35,6 +35,7 @@ function writeDiagnosticOnce(path, content) {
|
|
|
35
35
|
}
|
|
36
36
|
//#endregion
|
|
37
37
|
//#region src/diagnostics/native-crash.ts
|
|
38
|
+
const CRASH_LOG_PREFIX = "native-crash-";
|
|
38
39
|
const IOS_CRASH_REPORT_RETRY = "iOS crash reports can take about a minute or longer to appear. Run `stim logs --errors` again for the native stack.";
|
|
39
40
|
/** Accepts only a report for this app, simulator and launch window. */
|
|
40
41
|
function parseIosCrash(text, target) {
|
|
@@ -346,7 +347,7 @@ function captureNativeCrashes(target, logsDir) {
|
|
|
346
347
|
record.incident ?? record.deviceTs,
|
|
347
348
|
record.rawReport
|
|
348
349
|
])).digest("hex");
|
|
349
|
-
writeDiagnosticOnce(join(logsDir,
|
|
350
|
+
writeDiagnosticOnce(join(logsDir, `${CRASH_LOG_PREFIX}${key}.ndjson`), `${JSON.stringify(record)}\n`);
|
|
350
351
|
} catch {}
|
|
351
352
|
}
|
|
352
353
|
return records;
|
|
@@ -355,8 +356,10 @@ function printNativeCrashReport(target, logsDir, emit, remote) {
|
|
|
355
356
|
if (remote) return;
|
|
356
357
|
for (const line of launchErrorPreview(captureNativeCrashes(target, logsDir), target.root)) emit(line);
|
|
357
358
|
}
|
|
359
|
+
/** Captures native crash reports for this workspace's current launches and returns the whole timeline. */
|
|
358
360
|
function captureWorkspaceCrashes(root, logsDir) {
|
|
359
|
-
const
|
|
361
|
+
const timeline = readLogRecords(logsDir, (name) => !isCrashLog(name));
|
|
362
|
+
const attempts = timeline.filter((record) => record.event === "launch_attempt");
|
|
360
363
|
const launches = readWorkspaceLaunches(root);
|
|
361
364
|
const latest = /* @__PURE__ */ new Map();
|
|
362
365
|
for (const attempt of attempts) if (attempt.platform === "ios" || attempt.platform === "android") latest.set(deviceSlotKey(attempt.platform, String(attempt.slot ?? "default")), attempt);
|
|
@@ -406,6 +409,10 @@ function captureWorkspaceCrashes(root, logsDir) {
|
|
|
406
409
|
}, logsDir);
|
|
407
410
|
} catch {}
|
|
408
411
|
}
|
|
412
|
+
return sortByTs([...timeline, ...readLogRecords(logsDir, isCrashLog)]);
|
|
413
|
+
}
|
|
414
|
+
function isCrashLog(name) {
|
|
415
|
+
return name.startsWith(CRASH_LOG_PREFIX);
|
|
409
416
|
}
|
|
410
417
|
//#endregion
|
|
411
418
|
//#region src/diagnostics/error-symbolication.ts
|
|
@@ -583,8 +590,7 @@ function mergeErrorCopies(records, root) {
|
|
|
583
590
|
return result;
|
|
584
591
|
}
|
|
585
592
|
/** Keeps symbolicated launch evidence stable when Metro later rebuilds or stops. */
|
|
586
|
-
async function errorDiagnostics(input, { root, logsDir, port, allowRequest = false }) {
|
|
587
|
-
const timeline = readLogRecords(logsDir);
|
|
593
|
+
async function errorDiagnostics(input, { root, logsDir, port, allowRequest = false, timeline = readLogRecords(logsDir) }) {
|
|
588
594
|
const records = attachDeviceErrorContext(timeline, attachExpoErrorContext(timeline, input.map((record) => ({
|
|
589
595
|
...record,
|
|
590
596
|
src: typeof record.src === "string" ? record.src : void 0,
|