stim 1.13.0 → 1.15.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.
Files changed (133) hide show
  1. package/README.md +2 -0
  2. package/dist/{activity-DfVKZTEB.mjs → activity-B2-kb7k0.mjs} +281 -41
  3. package/dist/{android-BHfAu2mf.mjs → android-CYmq0jNi.mjs} +2 -2
  4. package/dist/{android-CD8pr8Q2.mjs → android-Cu_L4RpL.mjs} +524 -412
  5. package/dist/{android-qx_31wJo.mjs → android-Db2eEMaf.mjs} +152 -65
  6. package/dist/android-cas-PnKfAdB2.mjs +167 -0
  7. package/dist/android-cas-compiler.mjs +2 -2
  8. package/dist/{app-install-CDFY2nUL.mjs → app-install-CAAplXAt.mjs} +162 -173
  9. package/dist/{budget-E5o91NR1.mjs → budget-CMiqghig.mjs} +1048 -77
  10. package/dist/{build-plan-BTa93o_r.mjs → build-plan-aeGMFX7e.mjs} +193 -650
  11. package/dist/build-progress-C2Jv1AtA.mjs +872 -0
  12. package/dist/build-slots-Df1ApSuH.mjs +127 -0
  13. package/dist/{cache-manifest-DWPF4RKJ.mjs → cache-manifest-DnUHBJaU.mjs} +2 -2
  14. package/dist/cache-manifest.mjs +1 -1
  15. package/dist/{chrome-B5hWgQJS.mjs → chrome-BrcVWQyD.mjs} +4 -4
  16. package/dist/cli-0cX5s4NM.mjs +45 -0
  17. package/dist/cli.mjs +6 -42
  18. package/dist/client-C2IS36Qf.mjs +1333 -0
  19. package/dist/collector-run.mjs +8 -7
  20. package/dist/{command-output-BIL7rlX7.mjs → command-output-CliHHn7a.mjs} +1 -1
  21. package/dist/{config-0jCcMM0E.mjs → config-D0DbpZtM.mjs} +29 -29
  22. package/dist/{created-devices-Cd558h31.mjs → created-devices-BwVb3liH.mjs} +2 -2
  23. package/dist/{dependency-state-DNN0yfx6.mjs → dependency-state-BmsjKZ2H.mjs} +2 -2
  24. package/dist/{deps-2Wo81np9.mjs → deps-BFlKbOIp.mjs} +3 -3
  25. package/dist/{detached-entry-DJHoca49.mjs → detached-entry-CiTEgMR1.mjs} +1 -1
  26. package/dist/dev-client-CjzLoNs0.mjs +80 -0
  27. package/dist/{device-Cf7vl-so.mjs → device-BZ1IyS5A.mjs} +7 -7
  28. package/dist/device-capacity-DMuKC7nx.mjs +136 -0
  29. package/dist/device-host-worker.d.mts +1 -0
  30. package/dist/device-host-worker.mjs +769 -0
  31. package/dist/device-ios-DMQBUPus.mjs +381 -0
  32. package/dist/{device-lease-CL9dZf73.mjs → device-lease-W5Pi1q38.mjs} +43 -36
  33. package/dist/{device-pool-MuoiyRcu.mjs → device-pool-B2r38YjS.mjs} +4 -4
  34. package/dist/{device-remote-DT9ngZiD.mjs → device-remote-9ulPsdhY.mjs} +68 -162
  35. package/dist/{doctor-D2iysNNH.mjs → doctor-BcE5xsBn.mjs} +191 -99
  36. package/dist/{error-diagnostics-BoiOhck8.mjs → error-diagnostics-Cb0P1WLS.mjs} +12 -11
  37. package/dist/{exec-DK8KaVHK.mjs → exec-CaErVv7t.mjs} +5 -1
  38. package/dist/{gc-eA-PRBX8.mjs → gc-BuL1Genr.mjs} +430 -102
  39. package/dist/{android-cas-B9Kv9aIy.mjs → gradle-CmdOBq1d.mjs} +8 -294
  40. package/dist/{guide-BfZ0OmiP.mjs → guide-cCSGRFd3.mjs} +2052 -240
  41. package/dist/{guide-status-BaMYu55M.mjs → guide-status-CIoWK6mG.mjs} +3 -3
  42. package/dist/hosted-macos-DwowNU7W.mjs +447 -0
  43. package/dist/idle-shutdown-B5LPaNyY.mjs +122 -0
  44. package/dist/in-use-CndPMilN.mjs +110 -0
  45. package/dist/{ios-CmEzZiOj.mjs → ios-3CtCRhwr.mjs} +201 -10
  46. package/dist/{ios-CcfCeZ19.mjs → ios-Chob8ny7.mjs} +560 -259
  47. package/dist/{ios-device-BW-t_Lkv.mjs → ios-device-DERmMmk-.mjs} +12 -7
  48. package/dist/{ios-device-BiOsSVzd.mjs → ios-device-Ee7sDXfp.mjs} +1 -1
  49. package/dist/{launch-verify-CuJaBpEa.mjs → launch-verify-CLlofxRt.mjs} +42 -11
  50. package/dist/{logs-DcSRbC2t.mjs → logs-h9h6MUvE.mjs} +95 -13
  51. package/dist/machine-usage-D_YYMzfR.mjs +283 -0
  52. package/dist/machines-CYtOCqcj.mjs +259 -0
  53. package/dist/macos-BwtbUtTN.mjs +468 -0
  54. package/dist/macos-run.d.mts +5 -0
  55. package/dist/macos-run.mjs +2 -0
  56. package/dist/{merge-state-ytFQCeh4.mjs → merge-state-BnxLNQiM.mjs} +22 -12
  57. package/dist/{metro-BPeY1YMh.mjs → metro-Di8EN2Tb.mjs} +20 -120
  58. package/dist/{named-ports-n7tnJsI8.mjs → named-ports-Dj_XBNaL.mjs} +8 -64
  59. package/dist/native-run-DFDoIRbY.mjs +147 -0
  60. package/dist/{native-runtime-CiiFHt0e.mjs → native-runtime-i6OkVg-w.mjs} +11 -6
  61. package/dist/offload-worker.d.mts +121 -0
  62. package/dist/offload-worker.mjs +601 -0
  63. package/dist/{ownership-Bz2kETAS.mjs → ownership-BkYxUtuj.mjs} +3 -2
  64. package/dist/{page-BTu7I60K.mjs → page-QF_Ke10s.mjs} +7 -2
  65. package/dist/{ports-C5UutqpJ.mjs → ports-DddwttKM.mjs} +3 -3
  66. package/dist/prebuild-BvxDlD6C.mjs +213 -0
  67. package/dist/process-identity-BmRm1qV0.mjs +12 -0
  68. package/dist/{project-DGeclhvO.mjs → project-CV3tDFHl.mjs} +9 -18
  69. package/dist/pull-request-pxnDCQzn.mjs +322 -0
  70. package/dist/pull-requests.d.mts +120 -0
  71. package/dist/pull-requests.mjs +2 -0
  72. package/dist/recordings-GEXp4iBT.mjs +37 -0
  73. package/dist/{reload-C-cV5yy_.mjs → reload-ChPiwvot.mjs} +70 -22
  74. package/dist/{remote-cache--aehr4Pr.mjs → remote-cache-CO2elm_b.mjs} +4 -4
  75. package/dist/run-B-xqRrsg.mjs +119 -0
  76. package/dist/{server-bare-Bq8BpSIo.mjs → server-bare-X7PUgizL.mjs} +60 -13
  77. package/dist/{server-expo-DUCg52-K.mjs → server-expo-DhtX6bom.mjs} +6 -10
  78. package/dist/server-expo-KJeD109I.mjs +2 -0
  79. package/dist/{settings-xB0Frkg6.mjs → settings-CduVcoxj.mjs} +77 -26
  80. package/dist/{settings-ssVBToDR.mjs → settings-DbL6uhH8.mjs} +16 -10
  81. package/dist/settings.schema.json +357 -2
  82. package/dist/{simslim-Bbg9UWrt.mjs → simslim-Ciluxlq4.mjs} +8 -132
  83. package/dist/slot-launch-BY0BrOLh.mjs +65 -0
  84. package/dist/{spawn-claims-PT8aQpCa.mjs → spawn-claims-D0XfSe8u.mjs} +1 -1
  85. package/dist/spawn-entry-DncpJvWL.mjs +16 -0
  86. package/dist/stage-CzaiwFsI.mjs +143 -0
  87. package/dist/start-CPO4wRg7.mjs +2 -0
  88. package/dist/{start-BZhItkiL.mjs → start-CUD9nasA.mjs} +108 -61
  89. package/dist/state-B4PQFXMW.d.mts +12 -0
  90. package/dist/state-BxCgeTQu.mjs +41 -0
  91. package/dist/{state-DwAU2_-D.mjs → state-CaeaHbDA.mjs} +7 -4
  92. package/dist/{state-l1pYwOre.mjs → state-DFm77wRn.mjs} +67 -5
  93. package/dist/stats-DBLLFmKd.mjs +66 -0
  94. package/dist/{status-TJlL0HWo.mjs → status-DYXxNOT0.mjs} +425 -260
  95. package/dist/{status-sszP4XKU.mjs → status-l84Gbvp2.mjs} +122 -20
  96. package/dist/stdout-reader-C8yjre1x.mjs +23 -0
  97. package/dist/stim-desktop-Cnz8CPnl.mjs +63 -0
  98. package/dist/stim-footprint.swift +32 -0
  99. package/dist/{stim-installations-CINXy_su.mjs → stim-installations-QMEI32v1.mjs} +1 -1
  100. package/dist/{stop-BZ2qMiBP.mjs → stop-Bad61z_2.mjs} +128 -19
  101. package/dist/stop-Bvf1MflS.mjs +48 -0
  102. package/dist/{stop-DskDKNTU.mjs → stop-CceYh1yG.mjs} +2 -2
  103. package/dist/stop-cause-CZ_Mr-v9.mjs +665 -0
  104. package/dist/supervisor-run.d.mts +44 -12
  105. package/dist/supervisor-run.mjs +276 -33
  106. package/dist/support-CDQbDkL5.mjs +315 -0
  107. package/dist/support-WLOzVKUv.mjs +176 -0
  108. package/dist/teardown-BYuQafiA.mjs +718 -0
  109. package/dist/{xcode-LM6A8cNZ.mjs → toolchain-DmeYjXD9.mjs} +363 -13
  110. package/dist/warm-progress-DVHLN4uC.mjs +463 -0
  111. package/dist/{idle-DxLi5OkN.mjs → watchman-Bx0wceoF.mjs} +55 -8
  112. package/dist/{web-sWXd5iek.mjs → web-k6w8-HnE.mjs} +39 -22
  113. package/dist/web-run.mjs +326 -13
  114. package/dist/workspace-process-lock-BL7Q0HCO.mjs +57 -0
  115. package/dist/workspace-state-CL2V2Ons.mjs +371 -0
  116. package/dist/worktree-BT_uULFx.mjs +2 -0
  117. package/dist/{worktree-DeBQSVtR.mjs → worktree-C0c5Udwa.mjs} +55 -54
  118. package/dist/{worktree-D4Do_XiQ.mjs → worktree-qXKzADSC.mjs} +161 -255
  119. package/package.json +10 -5
  120. package/shim/bundle-response.cjs +55 -10
  121. package/shim/bundle-response.d.cts +1 -0
  122. package/shim/expo-metro-config.cjs +10 -2
  123. package/dist/build-progress-l7d-X-ZP.mjs +0 -247
  124. package/dist/in-use-wYEaKQM9.mjs +0 -249
  125. package/dist/ownership-PUP4Dwai.mjs +0 -1138
  126. package/dist/server-expo-BeYwP_Xy.mjs +0 -2
  127. package/dist/slot-launch-BIWEW-wI.mjs +0 -19
  128. package/dist/start-Rw2GD3nV.mjs +0 -2
  129. package/dist/stats-CaSwmsSZ.mjs +0 -62
  130. package/dist/stats-D8rUTPHd.mjs +0 -368
  131. package/dist/stim-desktop-CXt8-Z3J.mjs +0 -40
  132. package/dist/worktree-3cBa-bQt.mjs +0 -2
  133. package/dist/{metro-store-DzeWkfqW.mjs → metro-store-CDDZHtPl.mjs} +1 -1
@@ -1,2 +0,0 @@
1
- import { p as startExpoServer } from "./server-expo-DUCg52-K.mjs";
2
- export { startExpoServer };
@@ -1,19 +0,0 @@
1
- import { p as getProject } from "./config-0jCcMM0E.mjs";
2
- import { h as readWorkspaceState } from "./metro-BPeY1YMh.mjs";
3
- import { n as fileLeaseIo } from "./device-lease-CL9dZf73.mjs";
4
- import { d as deviceShellArg } from "./app-install-CDFY2nUL.mjs";
5
- //#region src/engine/slot-launch.ts
6
- function launchSlotScope(root, slot = "default") {
7
- if (slot !== "default") return slot;
8
- if (Object.keys(getProject(root)?.deviceSlots ?? {}).length) return slot;
9
- const state = readWorkspaceState(root);
10
- if (Object.keys({
11
- ...state?.collectors,
12
- ...fileLeaseIo.readHolder(root)
13
- }).some((key) => key.includes(":"))) return slot;
14
- }
15
- function nativeRunCommand(platform, slot = "default", { physical, deviceId } = {}) {
16
- return `stim ${platform}${slot === "default" ? "" : ` --slot ${slot}`}${physical && deviceId ? ` --device ${deviceShellArg(deviceId)}` : ""}`;
17
- }
18
- //#endregion
19
- export { nativeRunCommand as n, launchSlotScope as t };
@@ -1,2 +0,0 @@
1
- import { a as registerStart, c as startFacts, d as wantsExpoOwnTunnel, i as readLogTail, l as supervisorEntry, n as liveSupervisor, o as startCommand, r as parseWait, s as startDevServer, t as failureEvidence, u as tailLines } from "./start-BZhItkiL.mjs";
2
- export { startCommand as default, failureEvidence, liveSupervisor, parseWait, readLogTail, registerStart, startDevServer, startFacts, supervisorEntry, tailLines, wantsExpoOwnTunnel };
@@ -1,62 +0,0 @@
1
- import { s as gitCommonDir, y as repoRoot } from "./worktree-DeBQSVtR.mjs";
2
- import { a as findProjectRoot } from "./project-DGeclhvO.mjs";
3
- import { o as formatLongDuration } from "./command-output-BIL7rlX7.mjs";
4
- import { a as statsProjectKey, r as readStats } from "./stats-D8rUTPHd.mjs";
5
- import chalk from "chalk";
6
- //#region src/commands/stats.ts
7
- const PLATFORMS = ["ios", "android"];
8
- const PLATFORM_WIDTH = 9;
9
- function statsCommand(program) {
10
- program.command("stats").description("Show how many `ios` and `android` runs this project and this machine have recorded, how many hit the build cache, and an estimate of the time that cache saved.").option("--json", "print the aggregates as JSON").action((opts) => {
11
- const root = findProjectRoot(process.cwd());
12
- const key = root ? statsProjectKey({
13
- root,
14
- commonDir: gitCommonDir(root),
15
- repoRoot: repoRoot(root)
16
- }) : null;
17
- const { record, note } = readStats();
18
- if (note) console.error(chalk.dim(note));
19
- const machine = record?.machine ?? {};
20
- const project = key ? record?.projects?.[key] ?? {} : {};
21
- if (opts.json) {
22
- console.log(JSON.stringify({
23
- version: 1,
24
- project: key ? {
25
- key,
26
- ios: project.ios ?? null,
27
- android: project.android ?? null
28
- } : null,
29
- machine: {
30
- ios: machine.ios ?? null,
31
- android: machine.android ?? null
32
- }
33
- }));
34
- return;
35
- }
36
- const lines = [];
37
- if (key) lines.push(`project ${key}`, ...sectionLines(project));
38
- lines.push("machine", ...sectionLines(machine));
39
- for (const line of lines) console.log(line);
40
- });
41
- }
42
- function sectionLines(scope) {
43
- const lines = PLATFORMS.filter((platform) => scope[platform]).map((platform) => bucketLine(platform, scope[platform]));
44
- return lines.length ? lines : [chalk.dim(" no runs recorded")];
45
- }
46
- function bucketLine(platform, bucket) {
47
- const finished = bucket.runs - bucket.failed;
48
- const cells = [
49
- `${bucket.runs} runs${bucket.failed > 0 ? ` (${bucket.failed} failed)` : ""}`,
50
- `${bucket.hits} hits (${finished > 0 ? `${Math.round(bucket.hits / finished * 100)}%` : "-"})`,
51
- `cold run ${average(bucket.coldRunMs, bucket.coldRuns)} avg`,
52
- `hit run ${average(bucket.hitRunMs, bucket.hitRuns)} avg`,
53
- `saved ~${formatLongDuration(bucket.timeSavedMs)} (estimated)`,
54
- `since ${bucket.firstRunAt.slice(0, 10)}`
55
- ];
56
- return ` ${platform.padEnd(PLATFORM_WIDTH)}${cells.join(" ")}`;
57
- }
58
- function average(totalMs, runs) {
59
- return runs > 0 ? formatLongDuration(Math.round(totalMs / runs)) : "-";
60
- }
61
- //#endregion
62
- export { statsCommand as default };
@@ -1,368 +0,0 @@
1
- import { E as withConfigLock, d as getConfigDir } from "./config-0jCcMM0E.mjs";
2
- import { readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
3
- import { basename, dirname, join, relative, resolve } from "node:path";
4
- const PLATFORMS = ["ios", "android"];
5
- const OUTCOMES = ["hit", "cold"];
6
- function statsFile() {
7
- return join(getConfigDir(), "stats.json");
8
- }
9
- function emptyStats() {
10
- return {
11
- version: 1,
12
- machine: {},
13
- projects: {}
14
- };
15
- }
16
- function statsProjectKey({ root, commonDir, repoRoot }) {
17
- if (commonDir && repoRoot && basename(commonDir) === ".git") return canonical(join(dirname(commonDir), relative(repoRoot, root)));
18
- return canonical(root);
19
- }
20
- function updateStats(record, run, now) {
21
- const at = new Date(now).toISOString();
22
- const durationMs = wholeMs(run.durationMs);
23
- const phases = {
24
- coldBuildMs: wholeMs(run.coldBuildMs),
25
- podsMs: wholeMs(run.podsMs)
26
- };
27
- const projects = { ...record.projects };
28
- const scope = { ...projects[run.projectKey] };
29
- const machine = { ...record.machine };
30
- const before = scope[run.platform] ?? null;
31
- const credit = creditMs(before, run, durationMs);
32
- scope[run.platform] = applyRun(before, run, {
33
- at,
34
- durationMs,
35
- credit,
36
- phases
37
- });
38
- projects[run.projectKey] = scope;
39
- machine[run.platform] = applyRun(machine[run.platform] ?? null, run, {
40
- at,
41
- durationMs,
42
- credit,
43
- phases
44
- });
45
- const history = { ...record.history };
46
- if (run.phases && !run.failed && !run.waitedForBuild) {
47
- const outcome = isHit(run.cacheHit) ? "hit" : "cold";
48
- const project = { ...history[run.projectKey] };
49
- const lists = { ...project[run.platform] };
50
- const sample = {
51
- at,
52
- durationMs,
53
- phases: wholePhases(run.phases)
54
- };
55
- lists[outcome] = [...lists[outcome] ?? [], sample].slice(-10);
56
- project[run.platform] = lists;
57
- history[run.projectKey] = project;
58
- }
59
- return {
60
- version: 1,
61
- machine,
62
- projects,
63
- ...Object.keys(history).length ? { history } : {}
64
- };
65
- }
66
- function readStats() {
67
- const path = statsFile();
68
- let text;
69
- try {
70
- text = readFileSync(path, "utf-8");
71
- } catch {
72
- return {
73
- record: null,
74
- note: null
75
- };
76
- }
77
- const parsed = parseRecord(text);
78
- if (!parsed) return {
79
- record: null,
80
- note: `Run statistics at ${path} could not be read; the next ios or android run moves them aside and starts a new file.`
81
- };
82
- if (parsed.version > 1) return {
83
- record: null,
84
- note: `Run statistics at ${path} are version ${parsed.version}, which this Stim does not understand, so none are shown.`
85
- };
86
- return {
87
- record: normalize(parsed),
88
- note: null
89
- };
90
- }
91
- function projectEstimates(record, projectKey, platform) {
92
- const bucket = record?.projects?.[projectKey]?.[platform] ?? null;
93
- return {
94
- coldBuildMs: positive(bucket?.lastColdBuildMs),
95
- podsMs: positive(bucket?.lastPodsMs)
96
- };
97
- }
98
- function readRunEstimates({ projectKey, platform, read = readStats }) {
99
- if (!projectKey) return {
100
- coldBuildMs: null,
101
- podsMs: null
102
- };
103
- try {
104
- return projectEstimates(read().record, projectKey, platform);
105
- } catch {
106
- return {
107
- coldBuildMs: null,
108
- podsMs: null
109
- };
110
- }
111
- }
112
- function recordRunStats(run, now) {
113
- return withConfigLock(() => {
114
- const path = statsFile();
115
- const loaded = loadForUpdate(path, now);
116
- if (loaded.newerVersion !== null) return {
117
- recorded: false,
118
- note: `Run statistics at ${path} are version ${loaded.newerVersion}, which this Stim does not understand, so this run was not recorded.`
119
- };
120
- writeStats(path, updateStats(loaded.record, run, now));
121
- return {
122
- recorded: true,
123
- note: loaded.note
124
- };
125
- });
126
- }
127
- function createRunRecorder({ platform, write, now, note, phases }) {
128
- let projectKey = null;
129
- let cacheKey = null;
130
- let coldBuildMs = 0;
131
- let podsMs = 0;
132
- let recorded = false;
133
- return {
134
- setProject(key) {
135
- projectKey = key;
136
- },
137
- setCacheKey(key) {
138
- cacheKey = key;
139
- },
140
- setBuildMs(ms) {
141
- coldBuildMs = wholeMs(ms);
142
- },
143
- setPodsMs(ms) {
144
- podsMs = wholeMs(ms);
145
- },
146
- record({ failed, cacheHit = false, waited = null, durationMs }) {
147
- if (!projectKey || !cacheKey || recorded) return;
148
- recorded = true;
149
- const ran = failed ? {} : phases?.() ?? {};
150
- try {
151
- const outcome = write({
152
- platform,
153
- projectKey,
154
- failed,
155
- cacheHit,
156
- waitedForBuild: Boolean(waited),
157
- durationMs,
158
- ...coldBuildMs > 0 ? { coldBuildMs } : {},
159
- ...podsMs > 0 ? { podsMs } : {},
160
- ...Object.keys(ran).length ? { phases: ran } : {}
161
- }, now());
162
- if (outcome?.note) note(outcome.note);
163
- } catch (error) {
164
- note(`Run statistics could not be recorded: ${error?.message || error}`);
165
- }
166
- }
167
- };
168
- }
169
- function loadForUpdate(path, now) {
170
- let text;
171
- try {
172
- text = readFileSync(path, "utf-8");
173
- } catch {
174
- return {
175
- record: emptyStats(),
176
- note: null,
177
- newerVersion: null
178
- };
179
- }
180
- const parsed = parseRecord(text);
181
- if (!parsed) {
182
- const aside = `${path}.corrupt-${now}`;
183
- renameSync(path, aside);
184
- return {
185
- record: emptyStats(),
186
- note: `Run statistics at ${path} could not be read, so they were moved to ${aside} and a new file was started.`,
187
- newerVersion: null
188
- };
189
- }
190
- if (parsed.version > 1) return {
191
- record: emptyStats(),
192
- note: null,
193
- newerVersion: parsed.version
194
- };
195
- return {
196
- record: normalize(parsed),
197
- note: null,
198
- newerVersion: null
199
- };
200
- }
201
- function writeStats(path, record) {
202
- const tmp = `${path}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
203
- writeFileSync(tmp, `${JSON.stringify(record)}\n`);
204
- try {
205
- renameSync(tmp, path);
206
- } catch (error) {
207
- rmSync(tmp, { force: true });
208
- throw error;
209
- }
210
- }
211
- function parseRecord(text) {
212
- let parsed;
213
- try {
214
- parsed = JSON.parse(text);
215
- } catch {
216
- return null;
217
- }
218
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
219
- const version = parsed.version;
220
- if (typeof version !== "number" || !Number.isInteger(version)) return null;
221
- return parsed;
222
- }
223
- function normalize(record) {
224
- const projects = {};
225
- const source = record.projects;
226
- if (source && typeof source === "object" && !Array.isArray(source)) for (const [key, scope] of Object.entries(source)) projects[key] = normalizeScope(scope);
227
- const history = {};
228
- if (isObject(record.history)) for (const [key, scope] of Object.entries(record.history)) {
229
- const normalized = normalizeHistory(scope);
230
- if (Object.keys(normalized).length) history[key] = normalized;
231
- }
232
- return {
233
- version: 1,
234
- machine: normalizeScope(record.machine),
235
- projects,
236
- ...Object.keys(history).length ? { history } : {}
237
- };
238
- }
239
- function isObject(value) {
240
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
241
- }
242
- function normalizeHistory(scope) {
243
- const history = {};
244
- if (!isObject(scope)) return history;
245
- for (const platform of PLATFORMS) {
246
- const lists = scope[platform];
247
- if (!isObject(lists)) continue;
248
- const normalized = {};
249
- for (const outcome of OUTCOMES) {
250
- const samples = lists[outcome];
251
- if (!Array.isArray(samples)) continue;
252
- const kept = samples.filter(isObject).flatMap((sample) => {
253
- const durationMs = wholeMs(sample.durationMs);
254
- if (durationMs <= 0) return [];
255
- return [{
256
- at: timestamp(sample.at),
257
- durationMs,
258
- phases: wholePhases(sample.phases)
259
- }];
260
- });
261
- if (kept.length) normalized[outcome] = kept.slice(-10);
262
- }
263
- if (Object.keys(normalized).length) history[platform] = normalized;
264
- }
265
- return history;
266
- }
267
- function wholePhases(phases) {
268
- const out = {};
269
- if (!isObject(phases)) return out;
270
- for (const [name, ms] of Object.entries(phases)) {
271
- const value = Number(ms);
272
- if (Number.isFinite(value) && value >= 0) out[name] = Math.round(value);
273
- }
274
- return out;
275
- }
276
- function normalizeScope(scope) {
277
- const normalized = {};
278
- if (!scope || typeof scope !== "object" || Array.isArray(scope)) return normalized;
279
- for (const platform of PLATFORMS) {
280
- const bucket = scope[platform];
281
- if (bucket && typeof bucket === "object" && !Array.isArray(bucket)) normalized[platform] = normalizeBucket(bucket);
282
- }
283
- return normalized;
284
- }
285
- function normalizeBucket(bucket) {
286
- return {
287
- runs: count(bucket.runs),
288
- failed: count(bucket.failed),
289
- hits: count(bucket.hits),
290
- misses: count(bucket.misses),
291
- coldRuns: count(bucket.coldRuns),
292
- coldRunMs: count(bucket.coldRunMs),
293
- hitRuns: count(bucket.hitRuns),
294
- hitRunMs: count(bucket.hitRunMs),
295
- timeSavedMs: count(bucket.timeSavedMs),
296
- firstRunAt: timestamp(bucket.firstRunAt),
297
- lastRunAt: timestamp(bucket.lastRunAt),
298
- ...count(bucket.lastColdBuildMs) > 0 ? { lastColdBuildMs: count(bucket.lastColdBuildMs) } : {},
299
- ...count(bucket.lastPodsMs) > 0 ? { lastPodsMs: count(bucket.lastPodsMs) } : {}
300
- };
301
- }
302
- function applyRun(bucket, run, { at, durationMs, credit, phases }) {
303
- const next = bucket ? { ...bucket } : {
304
- runs: 0,
305
- failed: 0,
306
- hits: 0,
307
- misses: 0,
308
- coldRuns: 0,
309
- coldRunMs: 0,
310
- hitRuns: 0,
311
- hitRunMs: 0,
312
- timeSavedMs: 0,
313
- firstRunAt: at,
314
- lastRunAt: at
315
- };
316
- next.runs += 1;
317
- next.lastRunAt = at;
318
- if (phases.coldBuildMs > 0) next.lastColdBuildMs = phases.coldBuildMs;
319
- if (phases.podsMs > 0) next.lastPodsMs = phases.podsMs;
320
- if (run.failed) {
321
- next.failed += 1;
322
- return next;
323
- }
324
- if (isHit(run.cacheHit)) {
325
- next.hits += 1;
326
- if (!run.waitedForBuild) {
327
- next.hitRuns += 1;
328
- next.hitRunMs += durationMs;
329
- next.timeSavedMs += credit;
330
- }
331
- return next;
332
- }
333
- next.misses += 1;
334
- next.coldRuns += 1;
335
- next.coldRunMs += durationMs;
336
- return next;
337
- }
338
- function creditMs(bucket, run, durationMs) {
339
- if (run.failed || !isHit(run.cacheHit) || run.waitedForBuild) return 0;
340
- if (!bucket || bucket.coldRuns <= 0) return 0;
341
- return Math.max(0, Math.round(bucket.coldRunMs / bucket.coldRuns) - durationMs);
342
- }
343
- function isHit(cacheHit) {
344
- return cacheHit === "local" || cacheHit === "remote";
345
- }
346
- function positive(value) {
347
- const ms = wholeMs(value);
348
- return ms > 0 ? ms : null;
349
- }
350
- function wholeMs(value) {
351
- const ms = Number(value);
352
- return Number.isFinite(ms) && ms > 0 ? Math.round(ms) : 0;
353
- }
354
- function count(value) {
355
- return wholeMs(value);
356
- }
357
- function timestamp(value) {
358
- return typeof value === "string" && value !== "" ? value : (/* @__PURE__ */ new Date(0)).toISOString();
359
- }
360
- function canonical(path) {
361
- try {
362
- return realpathSync(path);
363
- } catch {
364
- return resolve(path);
365
- }
366
- }
367
- //#endregion
368
- export { statsProjectKey as a, recordRunStats as i, readRunEstimates as n, readStats as r, createRunRecorder as t };
@@ -1,40 +0,0 @@
1
- import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
2
- //#region src/devices/stim-desktop.ts
3
- const LAUNCH_SERVICES_LOOKUP = `ObjC.import('AppKit'); const url = $.NSWorkspace.sharedWorkspace.URLForApplicationWithBundleIdentifier('dev.stim.desktop'); url.isNil() ? '' : url.path.js`;
4
- const STIM_DESKTOP_INSTALLED = "Stim Desktop installed";
5
- /**
6
- * macOS `open` passes its environment to an app it launches, so Stim Desktop
7
- * started by a command run under a scoped `STIM_HOME` would serve that home.
8
- */
9
- const STIM_DESKTOP_OPEN_OPTIONS = {
10
- timeoutMs: 5e3,
11
- killSignal: "SIGKILL",
12
- omitEnv: ["STIM_HOME"]
13
- };
14
- /** Stim Desktop sets `STIM_DESKTOP_APP` to its bundle path for every command it runs; a non-empty value means Desktop is installed. */
15
- function stimDesktopInstalled(platform = process.platform, env = process.env) {
16
- if (platform !== "darwin") return false;
17
- if (env.STIM_DESKTOP_APP) return true;
18
- const found = getExecutor().runFileQuiet("osascript", [
19
- "-l",
20
- "JavaScript",
21
- "-e",
22
- LAUNCH_SERVICES_LOOKUP
23
- ], {
24
- timeoutMs: 5e3,
25
- killSignal: "SIGKILL"
26
- });
27
- return Boolean(found);
28
- }
29
- function settingDefault(setting, desktopInstalled = stimDesktopInstalled) {
30
- if (setting.desktopDefault !== void 0 && desktopInstalled()) return {
31
- value: setting.desktopDefault,
32
- reason: STIM_DESKTOP_INSTALLED
33
- };
34
- return {
35
- value: setting.default,
36
- reason: null
37
- };
38
- }
39
- //#endregion
40
- export { settingDefault as n, stimDesktopInstalled as r, STIM_DESKTOP_OPEN_OPTIONS as t };
@@ -1,2 +0,0 @@
1
- import { a as reclaimKeys, c as removalBlockers, d as removeWorktreeTarget, f as worktreeCommand, i as porcelainPath, l as removalPath, n as excludePodChurn, o as registerRemove, r as matchWorktreeEntry, s as registerWarm, t as dependencyInstallCommand, u as removalRemedy } from "./worktree-D4Do_XiQ.mjs";
2
- export { worktreeCommand as default, dependencyInstallCommand, excludePodChurn, matchWorktreeEntry, porcelainPath, reclaimKeys, registerRemove, registerWarm, removalBlockers, removalPath, removalRemedy, removeWorktreeTarget };
@@ -1,6 +1,6 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
- import { METRO_NAMED_CACHE_LAYOUT, metroCacheRoot, registerCache, sharedStoreRoot, tagSharedStore } from "@stim-cli/core";
3
2
  import { dirname, join, resolve } from "node:path";
3
+ import { METRO_NAMED_CACHE_LAYOUT, metroCacheRoot, registerCache, sharedStoreRoot, tagSharedStore } from "@stim-cli/core";
4
4
  import { fileURLToPath } from "node:url";
5
5
  //#region src/supervisor/metro-store.ts
6
6
  function metroStoreName(root) {