@stim-cli/core 1.26.0 → 1.27.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/dist/state.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  import { S as tryAcquireClaim, _ as releaseClaim, f as isClaimRefusal, g as readClaimSet } from "./ownership-claim-DG2GMIoo.mjs";
2
2
  import { inspectProcessIdentity } from "./process-identity.mjs";
3
- import { $ as withDirLockAsync, C as workspaceName, J as readJsonFile, Q as withDirLock, T as workspaceStateDir, U as ambientContext, W as ambientEnv, X as readStateFile, Y as readJsonObject, Z as withStateReadCache, _ as rotatedLogPath, d as ensurePrivateDir, g as rotateLog, q as isJsonObject, t as LOG_ROTATE_BYTES, u as configDir } from "./core-Cd3b_fBm.mjs";
3
+ import { $ as withDirLockAsync, C as workspaceName, J as readJsonFile, Q as withDirLock, T as workspaceStateDir, U as ambientContext, W as ambientEnv, X as readStateFile, Y as readJsonObject, Z as withStateReadCache, _ as rotatedLogPath, d as ensurePrivateDir, g as rotateLog, q as isJsonObject, t as LOG_ROTATE_BYTES, u as configDir } from "./core-B_w6CiKQ.mjs";
4
4
  import { readOrCreateKeyFile } from "./noise-session.mjs";
5
5
  import { validHomeId } from "./workspace-link.mjs";
6
6
  import { a as workspaceSummary, i as statusViews, n as applyKeyedDelta, o as withDerivedFacts, r as SUMMARY_ARCHIVES, s as withGitChip, t as KeyedEntities } from "./keyed-delta-BBoOeR2J.mjs";
7
- import { appendFileSync, closeSync, existsSync, fstatSync, lstatSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, realpathSync, statSync, watch } from "node:fs";
7
+ import { appendFileSync, closeSync, existsSync, fstatSync, lstatSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, realpathSync, statSync, watch, writeFileSync, writeSync } from "node:fs";
8
8
  import { availableParallelism, homedir, loadavg } from "node:os";
9
9
  import { basename, dirname, isAbsolute, join, posix, relative, resolve, sep, win32 } from "node:path";
10
10
  import { createHash, randomBytes } from "node:crypto";
@@ -645,6 +645,10 @@ function supervisorPidFile(projectRoot) {
645
645
  function workspaceStateFile(projectRoot) {
646
646
  return join(workspaceStateDir(projectRoot), "state.json");
647
647
  }
648
+ /** The dependency directories `gc --delete` deleted from the workspace's worktree, apart from state.json so writing it is not workspace activity. */
649
+ function workspaceLightenedFile(projectRoot) {
650
+ return join(workspaceStateDir(projectRoot), "lightened.json");
651
+ }
648
652
  function workspaceStateLock(projectRoot) {
649
653
  return join(workspaceStateDir(projectRoot), "state.lock");
650
654
  }
@@ -719,6 +723,12 @@ function easSessionLedgerLock(root = easMachineStateRoot()) {
719
723
  function deviceViewersDir() {
720
724
  return join(configDir(), "viewers");
721
725
  }
726
+ function budgetSweepFile() {
727
+ return join(configDir(), "budget-sweep.json");
728
+ }
729
+ function budgetSweepLock() {
730
+ return join(configDir(), "budget-sweep.lock");
731
+ }
722
732
  function statsFile() {
723
733
  return join(configDir(), "stats.json");
724
734
  }
@@ -740,6 +750,15 @@ function gcLogDir() {
740
750
  function gcLogFile() {
741
751
  return join(gcLogDir(), "gc.ndjson");
742
752
  }
753
+ function buildLedgerDir() {
754
+ return join(configDir(), "builds");
755
+ }
756
+ function buildLedgerFile() {
757
+ return join(buildLedgerDir(), "builds.ndjson");
758
+ }
759
+ function buildLedgerLock() {
760
+ return join(buildLedgerDir(), "builds.lock");
761
+ }
743
762
  function maintenanceChildLogFile() {
744
763
  return join(maintenanceDir(), "child.log");
745
764
  }
@@ -759,6 +778,10 @@ function archiveDir(id) {
759
778
  function archiveLock() {
760
779
  return join(archiveRoot(), ".lock");
761
780
  }
781
+ /** Uncommitted changes of removed worktrees: `<repository>/<branch-or-dir>-<timestamp>/` holding `manifest.json`. */
782
+ function worktreeArchiveRoot() {
783
+ return join(archiveRoot(), "worktrees");
784
+ }
762
785
  /** This machine's own long-term X25519 key as a client of other machines' stim-servers. */
763
786
  function clientIdentityKeyFile() {
764
787
  return join(configDir(), "client-identity.key");
@@ -1166,11 +1189,20 @@ const IOS_SIMULATOR_APPS = [
1166
1189
  "stim-desktop"
1167
1190
  ];
1168
1191
  const ANDROID_EMULATOR_APPS = ["emulator", "stim-desktop"];
1169
- const OFFLOAD_MODES = [
1170
- "auto",
1171
- "force",
1172
- "off"
1173
- ];
1192
+ const REPLACED_SETTINGS = { "remote.buildMode": {
1193
+ key: "remote.build",
1194
+ env: "STIM_REMOTE_BUILD_MODE",
1195
+ value: (old) => old === "auto" ? "auto" : old === "force" ? "remote" : old === "off" ? "local" : null
1196
+ } };
1197
+ function replacementAdvice(key, old) {
1198
+ const replaced = REPLACED_SETTINGS[key];
1199
+ if (!replaced) return null;
1200
+ const value = replaced.value(old);
1201
+ return {
1202
+ key: replaced.key,
1203
+ command: value ? `stim settings set ${replaced.key} ${value}` : null
1204
+ };
1205
+ }
1174
1206
  const WEB_VIEWPORTS = ["desktop", "phone"];
1175
1207
  const PROJECT = [
1176
1208
  "workspace",
@@ -1288,10 +1320,10 @@ const SETTINGS = [
1288
1320
  type: {
1289
1321
  kind: "string",
1290
1322
  pattern: TAILNET_MACHINE_PATTERN,
1291
- patternHelp: "eas, proxy, auto, local, or a tailnet machine name"
1323
+ patternHelp: "eas, proxy, local, auto, remote, remote-only, or a tailnet machine name"
1292
1324
  },
1293
1325
  scopes: EVERY,
1294
- description: "Default iOS remote target: eas, proxy, or an approved Mac in remote.machines; auto places on an approved Mac when this machine is full or busy; local runs here, overriding a lower layer"
1326
+ description: "Where the iOS simulator runs: local here (overriding a lower layer); auto here first, then a remote.machines entry when this machine is full or busy; remote on a remote.machines entry in order, here only when none takes it; remote-only the same but never here; a machine name exactly that machine; eas or proxy a remote device backend"
1295
1327
  },
1296
1328
  {
1297
1329
  key: "ios.projectPath",
@@ -1467,10 +1499,10 @@ const SETTINGS = [
1467
1499
  type: {
1468
1500
  kind: "string",
1469
1501
  pattern: TAILNET_MACHINE_PATTERN,
1470
- patternHelp: "eas, proxy, auto, local, or a tailnet machine name"
1502
+ patternHelp: "eas, proxy, local, auto, remote, remote-only, or a tailnet machine name"
1471
1503
  },
1472
1504
  scopes: EVERY,
1473
- description: "Default Android remote target: eas, proxy, or an approved Mac in remote.machines; auto places on an approved Mac when this machine is full or busy; local runs here, overriding a lower layer"
1505
+ description: "Where the Android emulator runs: local here (overriding a lower layer); auto here first, then a remote.machines entry when this machine is full or busy; remote on a remote.machines entry in order, here only when none takes it; remote-only the same but never here; a machine name exactly that machine; eas or proxy a remote device backend"
1474
1506
  },
1475
1507
  {
1476
1508
  key: "metro.tunnel",
@@ -1585,6 +1617,16 @@ const SETTINGS = [
1585
1617
  scopes: PROJECT,
1586
1618
  description: "Arguments passed directly to the owned macOS development executable."
1587
1619
  },
1620
+ {
1621
+ key: "macos.remote",
1622
+ type: {
1623
+ kind: "string",
1624
+ pattern: `^(?![Ee][Aa][Ss]$|[Pp][Rr][Oo][Xx][Yy]$)${TAILNET_MACHINE_PATTERN.slice(1)}`,
1625
+ patternHelp: "local, auto, remote, remote-only, or a tailnet machine name (macOS has no eas or proxy backend)"
1626
+ },
1627
+ scopes: EVERY,
1628
+ description: "Where stim macos launches the app: local here; auto here unless this machine is busy, then a remote.machines entry; remote on a remote.machines entry in order, here only when none takes it; remote-only the same but never here; a machine name exactly that machine. The --remote flag overrides it"
1629
+ },
1588
1630
  {
1589
1631
  key: "macos.assetCatalog",
1590
1632
  type: RELATIVE_PATH,
@@ -1639,7 +1681,7 @@ const SETTINGS = [
1639
1681
  default: true,
1640
1682
  env: "STIM_ARCHIVE_ENABLED",
1641
1683
  scopedHomeValue: false,
1642
- description: "Keep workspace history on removal; false under STIM_HOME unless explicitly enabled"
1684
+ description: "Keep workspace history on removal, and archive a dirty finished worktree's changes before gc removes it; false keeps such worktrees, and is the default under STIM_HOME unless explicitly enabled"
1643
1685
  },
1644
1686
  {
1645
1687
  key: "archive.maxAgeDays",
@@ -1647,7 +1689,7 @@ const SETTINGS = [
1647
1689
  scopes: MACHINE,
1648
1690
  default: 30,
1649
1691
  env: "STIM_ARCHIVE_MAX_AGE_DAYS",
1650
- description: "Days to keep archived workspace records; 0 keeps nothing"
1692
+ description: "Days to keep archived workspace records and worktree change archives; 0 keeps nothing"
1651
1693
  },
1652
1694
  {
1653
1695
  key: "archive.maxCount",
@@ -1663,7 +1705,7 @@ const SETTINGS = [
1663
1705
  scopes: MACHINE,
1664
1706
  default: 5,
1665
1707
  env: "STIM_ARCHIVE_MAX_TOTAL_GB",
1666
- description: "Total archived bytes in binary GB; 0 keeps no artifacts"
1708
+ description: "Total archived bytes in binary GB, and separately the worktree change archives; 0 keeps no artifacts"
1667
1709
  },
1668
1710
  {
1669
1711
  key: "archive.logs.maxAgeDays",
@@ -2041,7 +2083,7 @@ const SETTINGS = [
2041
2083
  scopes: MACHINE,
2042
2084
  default: 10,
2043
2085
  env: "STIM_MAINTENANCE_PRESSURE_PROTECT_MINUTES",
2044
- description: "Protection window, in minutes, that replaces maintenance.protectRecentHours at disk pressure levels 2 and 3"
2086
+ description: "Protection window, in minutes, that replaces maintenance.protectRecentHours at disk pressure levels 2 and 3, except for workspace build outputs and build directories, which level 2 keeps for 15 minutes after the last ios, android or macos run"
2045
2087
  },
2046
2088
  {
2047
2089
  key: "maintenance.gradleVersionIdleDays",
@@ -2061,7 +2103,7 @@ const SETTINGS = [
2061
2103
  scopes: MACHINE,
2062
2104
  default: true,
2063
2105
  env: "STIM_MAINTENANCE_REMOVE_FINISHED_WORKTREES",
2064
- description: "Remove clean linked worktrees whose branch or pull request finished, under gc.worktreeGraceMinutes, and at disk pressure level 3 clean, pushed ones with no commits of their own"
2106
+ description: "Remove linked worktrees whose branch or pull request finished, under gc.worktreeGraceMinutes, archiving a dirty one's uncommitted files first, and clean, pushed ones with no commits of their own once idle"
2065
2107
  },
2066
2108
  {
2067
2109
  key: "maintenance.removeIdleWorktrees",
@@ -2202,7 +2244,7 @@ const SETTINGS = [
2202
2244
  key: "remote.machines",
2203
2245
  type: { kind: "strings" },
2204
2246
  scopes: MACHINE,
2205
- description: "Tailscale names of the remote machines this machine may build on and host owned simulators on, each optionally with :<port> of its tailscale serve route (default 7443); what each is used for follows the build and device-host approvals it grants, which doctor --fix asks for separately"
2247
+ description: "Tailscale names of the remote machines this machine may build on and host owned simulators, emulators and macOS apps on, each optionally with :<port> of its tailscale serve route (default 7443). The order is the placement priority: each workload goes to the first machine with room and a load under its own limit. What each is used for follows the build and device-host approvals it grants, which doctor --fix asks for separately"
2206
2248
  },
2207
2249
  {
2208
2250
  key: "remote.buildPoolDisabled",
@@ -2223,7 +2265,7 @@ const SETTINGS = [
2223
2265
  type: BOOLEAN,
2224
2266
  scopes: EVERY,
2225
2267
  default: false,
2226
- description: "When ios.remote or android.remote is auto, this machine is at its concurrency.maxDevices cap and no remote.machines entry takes the run, run the simulator or emulator on a billed EAS Simulator instead of waiting or refusing, when eas-cli can"
2268
+ description: "When ios.remote or android.remote is auto or remote, this machine is at its concurrency.maxDevices cap and no remote.machines entry takes the run, run the simulator or emulator on a billed EAS Simulator instead of waiting or refusing, when eas-cli can; remote-only never uses it"
2227
2269
  },
2228
2270
  {
2229
2271
  key: "remote.easMaxDurationMinutes",
@@ -2241,23 +2283,12 @@ const SETTINGS = [
2241
2283
  type: {
2242
2284
  kind: "string",
2243
2285
  pattern: TAILNET_MACHINE_PATTERN,
2244
- patternHelp: "auto, local, or a tailnet machine name"
2286
+ patternHelp: "local, auto, remote, remote-only, or a tailnet machine name"
2245
2287
  },
2246
2288
  scopes: MACHINE,
2247
2289
  default: "auto",
2248
2290
  env: "STIM_REMOTE_BUILD",
2249
- description: "Build placement: auto follows remote.buildMode within enabled automatic pool members; local always builds here; a name in remote.machines requires that remote machine without fallback. The ios, android and macos --remote-build flag overrides this setting and its environment override"
2250
- },
2251
- {
2252
- key: "remote.buildMode",
2253
- type: {
2254
- kind: "choice",
2255
- choices: OFFLOAD_MODES
2256
- },
2257
- scopes: MACHINE,
2258
- default: "auto",
2259
- env: "STIM_REMOTE_BUILD_MODE",
2260
- description: "When remote.build is auto, where iOS simulator Debug, Android emulator debug and macOS SwiftPM Debug builds run: auto builds here while this machine has a free concurrency.maxBuilds slot and its load is under server.maxLoadPerCore, and otherwise builds on a less loaded machine in remote.machines; force builds on an enabled remote machine whenever one can take the build; off builds here when local is enabled in remote.buildPoolDisabled"
2291
+ description: "Where iOS simulator Debug, Android emulator debug and macOS SwiftPM Debug builds run: local here; auto here while it has a free concurrency.maxBuilds slot and load under server.maxLoadPerCore, otherwise on a remote.machines entry; remote on a remote.machines entry in order, here only when none takes the build; remote-only the same but never here; a machine name exactly that machine without fallback. The ios, android and macos --remote-build flag overrides this setting and its environment override"
2261
2292
  },
2262
2293
  {
2263
2294
  key: "server.maxLoadPerCore",
@@ -2267,7 +2298,7 @@ const SETTINGS = [
2267
2298
  },
2268
2299
  scopes: MACHINE,
2269
2300
  default: 2,
2270
- description: "Load per core (5-minute load average divided by the CPU count) at which this machine counts as saturated: it declines builds other machines send it, automatic build placement stops preferring it, and automatic iOS and Android device placement treats it as busy"
2301
+ description: "Load per core (5-minute load average divided by the CPU count) at which this machine counts as saturated: it declines builds other machines send it, reports the limit in its device offers so other machines skip it like a full one, stops preferring itself for automatic placement, and automatic iOS, Android and macOS placement treats it as busy"
2271
2302
  },
2272
2303
  {
2273
2304
  key: "server.workerRoot",
@@ -2698,6 +2729,282 @@ function createDebugLog(component, { env, now = Date.now, base = () => ({}) } =
2698
2729
  };
2699
2730
  }
2700
2731
  //#endregion
2732
+ //#region state/trace.ts
2733
+ const TRACE_ENV = "STIM_TRACE";
2734
+ const OWNER_ENV = "STIM_TRACE_OWNER";
2735
+ const PHASE_TID_BASE = 1e3;
2736
+ const MAX_ARGS = 60;
2737
+ const MAX_ARG_CHARS = 240;
2738
+ const MAX_LINE_CHARS = 500;
2739
+ const SCAN_ARG_CHARS = 1e3;
2740
+ const SCAN_LINE_CHARS = 2e3;
2741
+ const SECRET_WORDS = "token|secret|ticket|pass|pwd|otp|credential|cookie|api[-_]?key|access[-_]?key|private[-_]?key|auth";
2742
+ const SECRET_NAME = new RegExp(SECRET_WORDS, "i");
2743
+ const SECRET_FLAG = String.raw`--?[A-Za-z0-9_.-]*(?:${SECRET_WORDS})[A-Za-z0-9_.-]*`;
2744
+ const SECRET_FLAG_VALUE = new RegExp(String.raw`(${SECRET_FLAG})(=|\s+)(?:'[^']*'|"[^"]*"|\S+)`, "gi");
2745
+ const SECRET_ASSIGNMENT = new RegExp(String.raw`([A-Za-z0-9_]*(?:${SECRET_WORDS})[A-Za-z0-9_]*)=(?:'[^']*'|"[^"]*"|[^\s&]+)`, "gi");
2746
+ const URL_USERINFO = /(\/\/)[^/\s?#]*@/g;
2747
+ const SECRET_HEADER = new RegExp(String.raw`(\b[A-Za-z-]*(?:${SECRET_WORDS})[A-Za-z-]*:\s*)[^'"\r\n]+`, "gi");
2748
+ const AUTH_SCHEME = /\b(Bearer|Basic)\s+[A-Za-z0-9._~+/=-]{8,}/gi;
2749
+ const TOKEN_SHAPE = /\b(?:(?:gh[pousr]_|github_pat_|sk-|[sr]k_(?:live|test)_|xox[abprs]-|AKIA|AIza|glpat-)[A-Za-z0-9_-]{10,}|npm_[A-Za-z0-9]{36}|eyJ[A-Za-z0-9_-]{5,}\.[A-Za-z0-9_-]{5,}\.[A-Za-z0-9_-]*)/g;
2750
+ const CREDENTIAL_FLAGS = {
2751
+ curl: { "": [
2752
+ "-u",
2753
+ "-U",
2754
+ "--user",
2755
+ "--proxy-user"
2756
+ ] },
2757
+ security: {
2758
+ "unlock-keychain": ["-p"],
2759
+ "create-keychain": ["-p"],
2760
+ import: ["-P"],
2761
+ export: ["-P"]
2762
+ }
2763
+ };
2764
+ function credentialFlagsOf(program, subcommand) {
2765
+ const name = basename(program);
2766
+ const flags = Object.hasOwn(CREDENTIAL_FLAGS, name) ? CREDENTIAL_FLAGS[name] : void 0;
2767
+ const key = flags && Object.hasOwn(flags, "") ? "" : subcommand ?? "";
2768
+ return new Set(flags && Object.hasOwn(flags, key) ? flags[key] : []);
2769
+ }
2770
+ function scrubText(text, exact) {
2771
+ return exact.filter(Boolean).reduce((acc, value) => acc.split(value).join("***"), text).replace(URL_USERINFO, "$1[redacted]@").replace(SECRET_ASSIGNMENT, "$1=[redacted]").replace(SECRET_HEADER, "$1[redacted]").replace(AUTH_SCHEME, "$1 [redacted]").replace(TOKEN_SHAPE, "[redacted]");
2772
+ }
2773
+ /**
2774
+ * `args` with the value of any flag or assignment that looks like a secret, credentials in URLs, token shapes and
2775
+ * the `exact` values replaced. `program` selects the flags that carry a credential without a secret-looking name,
2776
+ * such as `curl -u`.
2777
+ */
2778
+ function redactArgv(args, exact = [], program = "") {
2779
+ const out = [];
2780
+ const credentialFlags = credentialFlagsOf(program, args[0]);
2781
+ let redactNext = false;
2782
+ for (const arg of args.slice(0, MAX_ARGS)) {
2783
+ const flag = /^(--?[A-Za-z0-9_.-]+)=/.exec(arg)?.[1];
2784
+ const assignment = /^([A-Za-z_][A-Za-z0-9_]*)=/.exec(arg)?.[1];
2785
+ const attached = arg.length > 2 && credentialFlags.has(arg.slice(0, 2)) ? arg.slice(0, 2) : null;
2786
+ if (redactNext) {
2787
+ out.push("[redacted]");
2788
+ redactNext = false;
2789
+ } else if (credentialFlags.has(arg)) {
2790
+ out.push(arg);
2791
+ redactNext = true;
2792
+ } else if (attached) out.push(`${attached}[redacted]`);
2793
+ else if (flag) out.push(SECRET_NAME.test(flag) || credentialFlags.has(flag) ? `${flag}=[redacted]` : clip(scrubText(arg.slice(0, SCAN_ARG_CHARS), exact)));
2794
+ else if (/^--?[A-Za-z0-9_.-]+$/.test(arg) && SECRET_NAME.test(arg)) {
2795
+ out.push(arg);
2796
+ redactNext = true;
2797
+ } else if (assignment && SECRET_NAME.test(assignment)) out.push(`${assignment}=[redacted]`);
2798
+ else if (/\s/.test(arg)) out.push(redactCommandLine(arg, exact));
2799
+ else out.push(clip(scrubText(arg.slice(0, SCAN_ARG_CHARS), exact)));
2800
+ }
2801
+ if (args.length > MAX_ARGS) out.push(`[+${args.length - MAX_ARGS} more]`);
2802
+ return out;
2803
+ }
2804
+ function clip(text, max = MAX_ARG_CHARS) {
2805
+ return text.length > max ? `${text.slice(0, max)}...` : text;
2806
+ }
2807
+ /** A shell command line with the same redactions as `redactArgv`, clipped to a fixed length. */
2808
+ function redactCommandLine(command, exact = []) {
2809
+ return clip(scrubText(command.slice(0, SCAN_LINE_CHARS).replace(SECRET_FLAG_VALUE, "$1$2[redacted]"), exact), MAX_LINE_CHARS);
2810
+ }
2811
+ const microseconds = () => Math.round((performance.timeOrigin + performance.now()) * 1e3);
2812
+ let current$1 = null;
2813
+ let attempted = null;
2814
+ function emit(sink, event) {
2815
+ try {
2816
+ const line = Buffer.from(`${JSON.stringify({
2817
+ ...event,
2818
+ pid: process.pid
2819
+ })},\n`);
2820
+ for (let written = 0; written < line.length;) written += writeSync(sink.fd, line, written);
2821
+ } catch {
2822
+ sink.fd = -1;
2823
+ }
2824
+ }
2825
+ function nameThread(sink, tid, name) {
2826
+ if (sink.named.has(tid)) return;
2827
+ sink.named.add(tid);
2828
+ emit(sink, {
2829
+ ph: "M",
2830
+ name: "thread_name",
2831
+ tid,
2832
+ args: { name }
2833
+ });
2834
+ }
2835
+ function finish(sink, span, args) {
2836
+ if (!sink.open.delete(span)) return;
2837
+ if (span.lane !== null) sink.lanes[span.lane] = false;
2838
+ if (sink.fd < 0) return;
2839
+ const end = microseconds();
2840
+ emit(sink, {
2841
+ name: span.name,
2842
+ cat: span.cat,
2843
+ ph: "X",
2844
+ ts: span.ts,
2845
+ dur: Math.max(0, end - span.ts),
2846
+ tid: span.tid,
2847
+ ...args || Object.keys(span.args).length ? { args: {
2848
+ ...span.args,
2849
+ ...args
2850
+ } } : {}
2851
+ });
2852
+ }
2853
+ function claimRoot() {
2854
+ const path = process.env[TRACE_ENV];
2855
+ if (!path) return;
2856
+ try {
2857
+ const absolute = resolve(path);
2858
+ if (process.env[OWNER_ENV] === absolute) return;
2859
+ mkdirSync(dirname(absolute), { recursive: true });
2860
+ writeFileSync(absolute, "[\n");
2861
+ process.env[OWNER_ENV] = absolute;
2862
+ } catch {}
2863
+ }
2864
+ function openSink(path) {
2865
+ try {
2866
+ const absolute = resolve(path);
2867
+ mkdirSync(dirname(absolute), { recursive: true });
2868
+ try {
2869
+ writeFileSync(absolute, "[\n", { flag: "wx" });
2870
+ } catch (error) {
2871
+ if (!(error instanceof Error && "code" in error && error.code === "EEXIST")) throw error;
2872
+ }
2873
+ process.env[TRACE_ENV] = absolute;
2874
+ const sink = {
2875
+ path: absolute,
2876
+ fd: openSync(absolute, "a"),
2877
+ lanes: [],
2878
+ named: /* @__PURE__ */ new Set(),
2879
+ open: /* @__PURE__ */ new Set(),
2880
+ tracks: /* @__PURE__ */ new Map()
2881
+ };
2882
+ emit(sink, {
2883
+ ph: "M",
2884
+ name: "process_name",
2885
+ args: { name: `${basename(process.argv[1] ?? "node").replace(/\.[cm]?[jt]s$/, "")} ${process.pid}` }
2886
+ });
2887
+ process.on("exit", (code) => {
2888
+ for (const span of sink.open) finish(sink, span, span.cat === "command" ? { exit: code } : { unfinished: true });
2889
+ });
2890
+ return sink;
2891
+ } catch {
2892
+ return null;
2893
+ }
2894
+ }
2895
+ function active() {
2896
+ const path = process.env[TRACE_ENV];
2897
+ if (!path) return null;
2898
+ if (path === attempted || path === current$1?.path) return current$1 && current$1.fd >= 0 ? current$1 : null;
2899
+ attempted = path;
2900
+ current$1 = openSink(path);
2901
+ return current$1;
2902
+ }
2903
+ function begin(name, args, cat = "span") {
2904
+ const sink = active();
2905
+ if (!sink) return NO_END;
2906
+ let lane = sink.lanes.indexOf(false);
2907
+ if (lane < 0) lane = sink.lanes.length;
2908
+ sink.lanes[lane] = true;
2909
+ const tid = lane + 1;
2910
+ nameThread(sink, tid, `spans ${tid}`);
2911
+ const span = {
2912
+ name,
2913
+ cat,
2914
+ tid,
2915
+ lane,
2916
+ ts: microseconds(),
2917
+ args: args ?? {}
2918
+ };
2919
+ sink.open.add(span);
2920
+ return (endArgs) => finish(sink, span, endArgs);
2921
+ }
2922
+ const NO_END = () => {};
2923
+ const NO_PHASES = {
2924
+ enter: () => {},
2925
+ end: () => {}
2926
+ };
2927
+ function phases(track) {
2928
+ const sink = active();
2929
+ if (!sink) return NO_PHASES;
2930
+ const tid = sink.tracks.get(track) ?? PHASE_TID_BASE + sink.tracks.size;
2931
+ sink.tracks.set(track, tid);
2932
+ nameThread(sink, tid, `phases: ${track}`);
2933
+ let open = null;
2934
+ const close = (args) => {
2935
+ if (open) finish(sink, open, args);
2936
+ open = null;
2937
+ };
2938
+ return {
2939
+ enter(name, args) {
2940
+ if (open?.name === name) return;
2941
+ close();
2942
+ open = {
2943
+ name,
2944
+ cat: "phase",
2945
+ tid,
2946
+ lane: null,
2947
+ ts: microseconds(),
2948
+ args: args ?? {}
2949
+ };
2950
+ sink.open.add(open);
2951
+ },
2952
+ end: close
2953
+ };
2954
+ }
2955
+ /**
2956
+ * Timing spans for one stim process tree, written as Chrome trace events (open the file in Perfetto or
2957
+ * chrome://tracing) when `STIM_TRACE=<path>` is set. Unset, every call is one environment check. A stim command
2958
+ * (`trace.command`) truncates the file and writes `[`; every other process that inherits the variable appends one
2959
+ * event per line, creating the file if it is missing, so the file has no closing bracket. Child process arguments are written through `redactArgv`.
2960
+ */
2961
+ const trace = {
2962
+ enabled: () => active() !== null,
2963
+ begin: (name, args) => begin(name, args),
2964
+ command(name, args) {
2965
+ claimRoot();
2966
+ begin(name, args, "command");
2967
+ },
2968
+ beginExec: (name, args) => begin(name, args, "exec"),
2969
+ span(name, fn, args) {
2970
+ const end = begin(name, args);
2971
+ try {
2972
+ const result = fn();
2973
+ end();
2974
+ return result;
2975
+ } catch (error) {
2976
+ end({ error: true });
2977
+ throw error;
2978
+ }
2979
+ },
2980
+ async spanAsync(name, fn, args) {
2981
+ const end = begin(name, args);
2982
+ try {
2983
+ const result = await fn();
2984
+ end();
2985
+ return result;
2986
+ } catch (error) {
2987
+ end({ error: true });
2988
+ throw error;
2989
+ }
2990
+ },
2991
+ mark(name, args) {
2992
+ const sink = active();
2993
+ if (!sink) return;
2994
+ nameThread(sink, 1, "spans 1");
2995
+ emit(sink, {
2996
+ name,
2997
+ cat: "mark",
2998
+ ph: "i",
2999
+ s: "t",
3000
+ ts: microseconds(),
3001
+ tid: 1,
3002
+ ...args ? { args } : {}
3003
+ });
3004
+ },
3005
+ phases
3006
+ };
3007
+ //#endregion
2701
3008
  //#region state/home-identity.ts
2702
3009
  /** The persistent, nonsecret identity of this Stim home; null until the CLI initializes it. */
2703
3010
  function readHomeIdentity(config = loadConfig()) {
@@ -2898,7 +3205,8 @@ const SOURCES = [
2898
3205
  "agent",
2899
3206
  "maintenance",
2900
3207
  "placement",
2901
- "gc"
3208
+ "gc",
3209
+ "builds"
2902
3210
  ];
2903
3211
  function levelRank(level) {
2904
3212
  const i = LEVELS.indexOf(level);
@@ -3926,6 +4234,130 @@ async function withErrorContext(generations, { extra = [], ...options }, selecte
3926
4234
  return matched.map((record) => contextual.get(record) ?? record);
3927
4235
  }
3928
4236
  //#endregion
4237
+ //#region state/ndjson-tail.ts
4238
+ const HEAD_BYTES = 64;
4239
+ function generation(path) {
4240
+ return {
4241
+ path,
4242
+ id: null,
4243
+ offset: 0,
4244
+ head: Buffer.alloc(0),
4245
+ records: []
4246
+ };
4247
+ }
4248
+ function reset(gen) {
4249
+ gen.id = null;
4250
+ gen.offset = 0;
4251
+ gen.head = Buffer.alloc(0);
4252
+ gen.records = [];
4253
+ }
4254
+ function fileId(stats) {
4255
+ return `${stats.dev}:${stats.ino}`;
4256
+ }
4257
+ function readAt(fd, length, position) {
4258
+ const buffer = Buffer.allocUnsafe(length);
4259
+ let filled = 0;
4260
+ while (filled < length) {
4261
+ const n = readSync(fd, buffer, filled, length - filled, position + filled);
4262
+ if (n === 0) break;
4263
+ filled += n;
4264
+ }
4265
+ return buffer.subarray(0, filled);
4266
+ }
4267
+ function advance(gen) {
4268
+ let fd;
4269
+ try {
4270
+ fd = openSync(gen.path, "r");
4271
+ } catch {
4272
+ const had = gen.id !== null;
4273
+ reset(gen);
4274
+ return had;
4275
+ }
4276
+ try {
4277
+ const stats = fstatSync(fd, { bigint: true });
4278
+ const id = fileId(stats);
4279
+ const size = Number(stats.size);
4280
+ let changed = false;
4281
+ if (gen.id !== id || size < gen.offset || gen.head.length > 0 && !readAt(fd, gen.head.length, 0).equals(gen.head)) {
4282
+ changed = gen.id !== null || gen.records.length > 0;
4283
+ reset(gen);
4284
+ gen.id = id;
4285
+ }
4286
+ const length = size - gen.offset;
4287
+ if (length <= 0) return changed;
4288
+ const buffer = readAt(fd, length, gen.offset);
4289
+ const end = buffer.lastIndexOf(10);
4290
+ if (end < 0) return changed;
4291
+ const added = parseNdjsonText(buffer.toString("utf-8", 0, end + 1));
4292
+ for (const record of added) gen.records.push(record);
4293
+ if (gen.head.length < HEAD_BYTES) gen.head = Buffer.concat([gen.head, buffer.subarray(0, end + 1)]).subarray(0, HEAD_BYTES);
4294
+ gen.offset += end + 1;
4295
+ return changed || added.length > 0;
4296
+ } finally {
4297
+ closeSync(fd);
4298
+ }
4299
+ }
4300
+ function statId(path) {
4301
+ try {
4302
+ return fileId(statSync(path, { bigint: true }));
4303
+ } catch {
4304
+ return null;
4305
+ }
4306
+ }
4307
+ /**
4308
+ * Returns a reader of `file` and its rotated generation that yields, on every call, the records a full
4309
+ * `readNdjsonGenerations(file)` would, while reading only the bytes appended since the previous call. A file renamed
4310
+ * to its rotated generation between two calls is finished from there; any other replacement or a shrunk file is
4311
+ * read again from its start. A file rewritten in place to at least its previous length is not detected.
4312
+ */
4313
+ function createNdjsonTail(file) {
4314
+ const rotated = generation(rotatedLogPath(file));
4315
+ const current = generation(file);
4316
+ let all = [];
4317
+ return () => {
4318
+ let changed = false;
4319
+ if (current.id !== null && statId(file) !== current.id && statId(rotated.path) === current.id) {
4320
+ rotated.id = current.id;
4321
+ rotated.offset = current.offset;
4322
+ rotated.head = current.head;
4323
+ rotated.records = current.records;
4324
+ reset(current);
4325
+ changed = true;
4326
+ }
4327
+ changed = advance(rotated) || changed;
4328
+ changed = advance(current) || changed;
4329
+ if (changed) all = rotated.records.concat(current.records);
4330
+ return all;
4331
+ };
4332
+ }
4333
+ //#endregion
4334
+ //#region state/placement.ts
4335
+ /**
4336
+ * The placement words every workload shares (`remote.build`, `ios.remote`, `android.remote`, `macos.remote` and their
4337
+ * flags). Anything else a setting holds is a machine name, or for devices `eas` or `proxy`.
4338
+ *
4339
+ * - `local`: this machine only.
4340
+ * - `auto`: this machine first, a remote machine when this one is full or busy.
4341
+ * - `remote`: remote machines first, in `remote.machines` order; this machine only when none takes the run.
4342
+ * - `remote-only`: remote machines in `remote.machines` order, never this machine.
4343
+ */
4344
+ const PLACEMENT_WORDS = [
4345
+ "local",
4346
+ "auto",
4347
+ "remote",
4348
+ "remote-only"
4349
+ ];
4350
+ function placementWord(value) {
4351
+ const word = value.trim().toLowerCase();
4352
+ return PLACEMENT_WORDS.find((each) => each === word) ?? null;
4353
+ }
4354
+ function prefersRemote(word) {
4355
+ return word === "remote" || word === "remote-only";
4356
+ }
4357
+ function mayRunHere(word) {
4358
+ return word !== "remote-only";
4359
+ }
4360
+ //#endregion
3929
4361
  //#region state/recordings.ts
3930
4362
  /** The footage stim-server keeps per device: the last 15 minutes recorded, however long ago. */
3931
4363
  const RECORDING_FOOTAGE_MS = 9e5;
@@ -4802,6 +5234,14 @@ function lastUseFrom(state, logMtimes) {
4802
5234
  ].filter(Number.isFinite);
4803
5235
  return candidates.length ? Math.max(...candidates) : NaN;
4804
5236
  }
5237
+ /**
5238
+ * When an ios, android or macos run last finished in the workspace, from its recorded builds (a cache hit counts),
5239
+ * in epoch milliseconds; NaN when it records none. Dev server starts, reloads and logs do not count.
5240
+ */
5241
+ function lastNativeUseFrom(state) {
5242
+ const times = [...Object.values(readLastBuilds(state)), ...Object.values(readBuildHistory(state)).flatMap((entries) => entries.slice(0, 1))].map((run) => Date.parse(run.finishedAt ?? run.startedAt)).filter(Number.isFinite);
5243
+ return times.length ? Math.max(...times) : NaN;
5244
+ }
4805
5245
  const MAINTENANCE_LOG_NAME = "maintenance.ndjson";
4806
5246
  /**
4807
5247
  * When the workspace was last used, in epoch milliseconds. A workspace that recorded no use falls back to the mtime
@@ -4911,8 +5351,8 @@ function trimCapacityRefusals(events, now) {
4911
5351
  }).toSorted((a, b) => Date.parse(a.at) - Date.parse(b.at)).slice(-50);
4912
5352
  }
4913
5353
  const trimCapacityWaits = trimCapacityRefusals;
4914
- const PLATFORMS = ["ios", "android"];
4915
- const OUTCOMES = ["hit", "cold"];
5354
+ const PLATFORMS$1 = ["ios", "android"];
5355
+ const OUTCOMES$1 = ["hit", "cold"];
4916
5356
  const HISTORY_LIMIT = 10;
4917
5357
  function statsProjectKey({ root, commonDir, repoRoot }) {
4918
5358
  if (commonDir && repoRoot && basename(commonDir) === ".git") return canonical$1(join(canonical$1(dirname(commonDir)), relative(canonical$1(repoRoot), canonical$1(root))));
@@ -5069,7 +5509,7 @@ function normalize$1(record) {
5069
5509
  function normalizePlacement(value) {
5070
5510
  if (!isJsonObject(value)) return [];
5071
5511
  const { decision, platform, reason, project, machine } = value;
5072
- if (!PLACEMENT_DECISIONS.includes(decision) || !PLATFORMS.includes(platform)) return [];
5512
+ if (!PLACEMENT_DECISIONS.includes(decision) || !PLATFORMS$1.includes(platform)) return [];
5073
5513
  if (typeof reason !== "string" || typeof project !== "string") return [];
5074
5514
  const buildMs = wholeMs(value.buildMs);
5075
5515
  const slotWaitMs = wholeMs(value.slotWaitMs);
@@ -5092,7 +5532,7 @@ function normalizePlacement(value) {
5092
5532
  function normalizeCapacityRefusal(value) {
5093
5533
  if (!isJsonObject(value)) return [];
5094
5534
  const { at, kind, platform, max, workspace } = value;
5095
- if (kind !== "device" || !PLATFORMS.includes(platform)) return [];
5535
+ if (kind !== "device" || !PLATFORMS$1.includes(platform)) return [];
5096
5536
  if (typeof at !== "string" || !Number.isFinite(Date.parse(at))) return [];
5097
5537
  if (typeof max !== "number" || !Number.isInteger(max) || max <= 0) return [];
5098
5538
  if (typeof workspace !== "string" || workspace === "") return [];
@@ -5132,11 +5572,11 @@ function normalizeMachineTotals(totals) {
5132
5572
  function normalizeHistory(scope) {
5133
5573
  const history = {};
5134
5574
  if (!isJsonObject(scope)) return history;
5135
- for (const platform of PLATFORMS) {
5575
+ for (const platform of PLATFORMS$1) {
5136
5576
  const lists = scope[platform];
5137
5577
  if (!isJsonObject(lists)) continue;
5138
5578
  const normalized = {};
5139
- for (const outcome of OUTCOMES) {
5579
+ for (const outcome of OUTCOMES$1) {
5140
5580
  const samples = lists[outcome];
5141
5581
  if (!Array.isArray(samples)) continue;
5142
5582
  const kept = samples.filter(isJsonObject).flatMap((sample) => {
@@ -5167,7 +5607,7 @@ function wholePhases(phases) {
5167
5607
  function normalizeScope(scope) {
5168
5608
  const normalized = {};
5169
5609
  if (!scope || typeof scope !== "object" || Array.isArray(scope)) return normalized;
5170
- for (const platform of PLATFORMS) {
5610
+ for (const platform of PLATFORMS$1) {
5171
5611
  const bucket = scope[platform];
5172
5612
  if (bucket && typeof bucket === "object" && !Array.isArray(bucket)) normalized[platform] = normalizeBucket(bucket);
5173
5613
  }
@@ -5426,6 +5866,7 @@ function parseHostedNativeOffer(value) {
5426
5866
  resources: {
5427
5867
  cpus: resources.cpus,
5428
5868
  loadPerCore: resources.loadPerCore,
5869
+ ...typeof resources.maxLoadPerCore === "number" && Number.isFinite(resources.maxLoadPerCore) && resources.maxLoadPerCore > 0 ? { maxLoadPerCore: resources.maxLoadPerCore } : {},
5429
5870
  memoryFreeBytes: resources.memoryFreeBytes,
5430
5871
  memoryPressure: resources.memoryPressure,
5431
5872
  workerDiskFreeBytes: resources.workerDiskFreeBytes,
@@ -6033,6 +6474,33 @@ function readGcLog(file = gcLogFile()) {
6033
6474
  return readNdjsonGenerations(file).filter(isGcLogRecord).toSorted((a, b) => a.ts - b.ts);
6034
6475
  }
6035
6476
  //#endregion
6477
+ //#region state/build-ledger.ts
6478
+ const BUILD_LEDGER_CAP = 500;
6479
+ const PLATFORMS = [
6480
+ "ios",
6481
+ "android",
6482
+ "macos"
6483
+ ];
6484
+ const OUTCOMES = [
6485
+ "succeeded",
6486
+ "failed",
6487
+ "cancelled",
6488
+ "interrupted"
6489
+ ];
6490
+ function isBuildLedgerRecord(record) {
6491
+ return record.src === "builds" && record.event === "build" && typeof record.ts === "number" && typeof record.id === "string" && typeof record.platform === "string" && PLATFORMS.includes(record.platform) && typeof record.outcome === "string" && OUTCOMES.includes(record.outcome) && typeof record.placement === "object" && record.placement !== null && typeof record.cache === "object" && record.cache !== null;
6492
+ }
6493
+ /** The ledger's records, oldest first. A missing or unreadable ledger is empty. */
6494
+ function readBuildLedger(file = buildLedgerFile()) {
6495
+ let text;
6496
+ try {
6497
+ text = readStateFile(file);
6498
+ } catch {
6499
+ return [];
6500
+ }
6501
+ return parseNdjsonText(text).filter(isBuildLedgerRecord).toSorted((a, b) => a.ts - b.ts);
6502
+ }
6503
+ //#endregion
6036
6504
  //#region state/agent-device.ts
6037
6505
  function agentDeviceStateDirs(home = ambientEnv().HOME || ambientEnv().USERPROFILE || homedir(), env = ambientEnv()) {
6038
6506
  const override = env.AGENT_DEVICE_STATE_DIR?.trim();
@@ -6252,4 +6720,4 @@ function isSetupJournalPrunable(journal, now) {
6252
6720
  return Date.parse(journal.expiresAt) + 36e5 < now;
6253
6721
  }
6254
6722
  //#endregion
6255
- export { ACTIVITY_RECENCY_BASES, AGENT_TOOLS, ANDROID_COMPILER_CACHE_CHOICES, ANDROID_EMULATOR_APPS, ANDROID_PCH_CHOICES, APP_PROCESS_STATES, BUILD_HISTORY_KEY, BUILD_HISTORY_LIMIT, BUILD_PHASES, BUILD_RESULTS, CAPACITY_REFUSAL_LIMIT, CAPACITY_REFUSAL_MAX_AGE_MS, DEBUG_ENV, DEVICE_HOST_LIMITS, DEVICE_IDLE_SHUTDOWN_KEY, DEVICE_RECLAIM_REASON, DEV_SERVER_STOP_REQUEST_KEY, ENDED_AGENT_RETENTION_MS, ERROR_SOURCES, FINGERPRINT_MEMO_SCHEMA, HISTORY_LIMIT, HOSTED_AGENT_DRIVERS, HOSTED_APP_CHUNK_BYTES, HOSTED_LOGS_FIRST_BYTES, HOSTED_LOGS_PAGE_BYTES, HOSTED_MACOS_APP_SLOTS, HOSTED_METRO_GATEWAYS_KEY, HOSTED_METRO_REQUESTS_KEY, HOSTED_PARKED_CANDIDATES, IDLE_STOP_KEY, IOS_SIMULATOR_APPS, KeyedEntities, LAST_BUILD_KEYS, LEVELS, MACHINE_CREDENTIALS_VERSION, MACHINE_OWNER_KINDS, MAINTENANCE_LOG_NAME, MEMORY_SOURCES, NATIVE_BUILD_STEPS, NATIVE_CRASH_LOG_PREFIX, OFFLOAD_MODES, PHYSICAL_DEVICE_CONNECTIONS, PLACEMENT_DECISIONS, READY_PHASE_MS, RECORDING_CAP_BYTES, RECORDING_FOOTAGE_MS, RECORDING_PLATFORMS, REMOTE_DEVICE_BACKENDS, RUN_ID_ENV, SETTINGS, SETTINGS_SCHEMA_FILE, SETTINGS_SCHEMA_URL, SETTING_GROUPS, SETTING_SCOPES, SOURCES, STATS_VERSION, STATUS_ISSUE_CODES, SUMMARY_ARCHIVES, TAILNET_MACHINE_PATTERN, TUNNEL_MODES, TUTORIAL_VERSION, WARM_KEY, WEB_PAGE_STATES, WEB_VIEWPORTS, WORKSPACE_AGENT_KEY, WORKSPACE_PHASES, WORKSPACE_STAGE_KINDS, acceptsShape, advanceTail, agentDeviceStateDirs, agentDeviceStateDirsAsync, agentDeviceUsageFile, agentSessionOf, agentSessionsCacheFile, allMetroPorts, applyKeyedDelta, archiveDir, archiveEnabled, archiveLock, archiveRoot, archivedUsage, assertHostedDeviceLedger, attachExpoErrorContext, automaticMachineEnabled, buildCriteria, buildDiagnostics, buildMachinesFile, buildMachinesLock, buildSlotPath, buildSlotsDir, buildWorkerRoot, bundleMarkerPlatform, cannotHost, capDrops, clientIdentity, clientIdentityKeyFile, closedSegmentName, coerceSettingText, compileGrep, configCorruptRepair, configLockPath, countErrorEntries, createAgentActionReader, createAsyncAgentActionReader, createDebugLog, createdDevicesFile, createdDevicesLock, debugLogDir, debugLoggingEnabled, decodeStats, deviceHostArea, deviceHostMachinesClaims, deviceHostMachinesFile, deviceHostMachinesLock, deviceHostRoot, deviceViewersDir, diskUsageCacheDir, diskUsageCacheFile, diskUsageFailureFile, diskUsageWalkClaims, easMachineStateRoot, easSessionLedgerFile, easSessionLedgerLock, emulatorLogFile, endedAgentSessionOf, endpoint, expectedShape, fileIdentity, fileSizes, findEnclosingWorktreeRoot, findPeer, findProjectRoot, fingerprintMemoDir, fingerprintMemoFile, fingerprintMemoLock, followLogs, footageDrops, gcLogDir, gcLogFile, getConcurrencyLimits, getConfigPath, getParkedMax, getProject, getProjectSettings, getRepoSettings, gitMergeCacheDir, hostedAgentDriverName, hostedAndroidDeviceName, hostedAndroidPlacements, hostedAndroidRecords, hostedAndroidStatus, hostedAppArea, hostedAppAttempt, hostedAppBlobs, hostedConsolePort, hostedDeviceId, hostedIosPlacements, hostedIosRecords, hostedIosStatus, hostedMacosAppSlot, hostedMacosBundleId, hostedMacosLogsDir, hostedMetroGateways, hostedMetroRequests, hostedNativeLogsDir, hostedNativeRecords, hostedWorkerSettleMs, isExpoErrorContext, isGcLogRecord, isJournalExpired, isJsonObject, isLayeredSetting, isPathPrefix, isSensitiveReference, isSetupJournalPrunable, lastUseFrom, levelRank, linkReplacedArchives, listRecordedDevices, listRecordedDevicesAsync, listSegments, listSegmentsAsync, listStatusCacheEntries, loadConfig, logFiles, machineCacheUsageFile, machineCapacity, machineEndpoint, macosAppState, maintenanceAttemptFile, maintenanceChildLogFile, maintenanceDir, maintenanceNdjsonFile, maintenanceRunClaims, maintenanceStateFile, markerWindow, offloadSummary, openLogDir, openSegmentName, parseHostedAgentAccess, parseHostedAgentGrant, parseHostedAndroidDevice, parseHostedAndroidPlacement, parseHostedAppManifest, parseHostedAppOffer, parseHostedChoice, parseHostedDevice, parseHostedIosPlacement, parseHostedLocalDeviceCount, parseHostedLogsCursor, parseHostedMacosChoice, parseHostedMacosDevice, parseHostedMacosPlacement, parseHostedNativeOffer, parseHostedNativePlacement, parseHostedOfferRequest, parseHostedPlatformDevice, parseHostedRequest, parseMachine, parseMachineCredential, parseMacosRecord, parseMaintenanceState, parseMissReason, parseNdjsonLine, parseNdjsonText, parseSetupJournal, parseSince, planLogQuery, projectRootDirectories, pullRequestCacheDir, pullRequestCacheFile, queryJsonLogs, queryLogs, readAgentDeviceUsage, readAgentDeviceUsageCache, readAgentSessionsCache, readArchive, readArchiveAsync, readArchiveState, readArchives, readArchivesAsync, readBuildDetail, readBuildHistory, readBuildMachines, readCreatedDevices, readDevServerStop, readDevServerStopRequest, readDeviceHostMachines, readDeviceIdleShutdowns, readDevicePlacement, readDiskUsage, readDiskUsageFailure, readEasSessionLedger, readEndedAgentSessions, readFingerprintMemo, readGcLog, readHomeIdentity, readHostedApp, readHostedAppMetadata, readHostedDevice, readHostedDeviceLedger, readHostedMacosApp, readHostedNativeLogsCheckpoint, readHostedSessions, readIdleStop, readJsonFile, readJsonObject, readLastBuilds, readLogRecords, readLogTimeline, readLogsSince, readMachineCacheUsage, readMacosRecord, readMaintenanceAttempt, readMaintenanceState, readNdjsonGenerations, readPullRequestCache, readRunEstimates, readSetupJournal, readStateFile, readStats, readStatsReport, readSwiftpmCacheUsage, readViewedDevices, readWarmRecord, readWorkspaceAgent, readWorkspaceState, recordMatches, recordedBytes, recordingDeviceName, recordingEnabled, rememberHostedAppBlobRename, requireAutomaticMachine, runId, saturation, serverLocalSocket, serverSetupDir, settingDefinition, settingValueError, settingsJsonSchema, setupJournalFile, sharedCcache, sharedCompilationCache, sharedGradle, sharedPods, sortByTs, statsFile, statsProjectKey, statusViews, stimBuildDigest, supervisorLogFile, supervisorPidFile, swiftpmCacheUsageFile, tailRead, trashRoot, trimCapacityRefusals, trimCapacityWaits, trimSamples, tryAcquireBuildSlotClaim, unreadableHostedAndroid, unreadableHostedIos, unreadableHostedNative, validEasSessionClaim, validHostedAppArguments, validHostedAppBlob, validRunId, validateAutomaticPool, wholePhases, windowsShortDir, windowsShortDirKey, withConfigLock, withConfigLockAsync, withDerivedFacts, withGitChip, withStateReadCache, workspaceAgentDeviceDir, workspaceBuildDetailFile, workspaceDerivedData, workspaceEndedAgentsFile, workspaceEndedAgentsLock, workspaceGradleBuild, workspaceLastUsed, workspaceLogErrorIndex, workspaceLogsDir, workspaceMetadataFile, workspaceRecordingsDir, workspaceStateFile, workspaceStateLock, workspaceSummary };
6723
+ export { ACTIVITY_RECENCY_BASES, AGENT_TOOLS, ANDROID_COMPILER_CACHE_CHOICES, ANDROID_EMULATOR_APPS, ANDROID_PCH_CHOICES, APP_PROCESS_STATES, BUILD_HISTORY_KEY, BUILD_HISTORY_LIMIT, BUILD_LEDGER_CAP, BUILD_PHASES, BUILD_RESULTS, CAPACITY_REFUSAL_LIMIT, CAPACITY_REFUSAL_MAX_AGE_MS, DEBUG_ENV, DEVICE_HOST_LIMITS, DEVICE_IDLE_SHUTDOWN_KEY, DEVICE_RECLAIM_REASON, DEV_SERVER_STOP_REQUEST_KEY, ENDED_AGENT_RETENTION_MS, ERROR_SOURCES, FINGERPRINT_MEMO_SCHEMA, HISTORY_LIMIT, HOSTED_AGENT_DRIVERS, HOSTED_APP_CHUNK_BYTES, HOSTED_LOGS_FIRST_BYTES, HOSTED_LOGS_PAGE_BYTES, HOSTED_MACOS_APP_SLOTS, HOSTED_METRO_GATEWAYS_KEY, HOSTED_METRO_REQUESTS_KEY, HOSTED_PARKED_CANDIDATES, IDLE_STOP_KEY, IOS_SIMULATOR_APPS, KeyedEntities, LAST_BUILD_KEYS, LEVELS, MACHINE_CREDENTIALS_VERSION, MACHINE_OWNER_KINDS, MAINTENANCE_LOG_NAME, MEMORY_SOURCES, NATIVE_BUILD_STEPS, NATIVE_CRASH_LOG_PREFIX, PHYSICAL_DEVICE_CONNECTIONS, PLACEMENT_DECISIONS, PLACEMENT_WORDS, READY_PHASE_MS, RECORDING_CAP_BYTES, RECORDING_FOOTAGE_MS, RECORDING_PLATFORMS, REMOTE_DEVICE_BACKENDS, REPLACED_SETTINGS, RUN_ID_ENV, SETTINGS, SETTINGS_SCHEMA_FILE, SETTINGS_SCHEMA_URL, SETTING_GROUPS, SETTING_SCOPES, SOURCES, STATS_VERSION, STATUS_ISSUE_CODES, SUMMARY_ARCHIVES, TAILNET_MACHINE_PATTERN, TRACE_ENV, TUNNEL_MODES, TUTORIAL_VERSION, WARM_KEY, WEB_PAGE_STATES, WEB_VIEWPORTS, WORKSPACE_AGENT_KEY, WORKSPACE_PHASES, WORKSPACE_STAGE_KINDS, acceptsShape, advanceTail, agentDeviceStateDirs, agentDeviceStateDirsAsync, agentDeviceUsageFile, agentSessionOf, agentSessionsCacheFile, allMetroPorts, applyKeyedDelta, archiveDir, archiveEnabled, archiveLock, archiveRoot, archivedUsage, assertHostedDeviceLedger, attachExpoErrorContext, automaticMachineEnabled, budgetSweepFile, budgetSweepLock, buildCriteria, buildDiagnostics, buildLedgerDir, buildLedgerFile, buildLedgerLock, buildMachinesFile, buildMachinesLock, buildSlotPath, buildSlotsDir, buildWorkerRoot, bundleMarkerPlatform, cannotHost, capDrops, clientIdentity, clientIdentityKeyFile, closedSegmentName, coerceSettingText, compileGrep, configCorruptRepair, configLockPath, countErrorEntries, createAgentActionReader, createAsyncAgentActionReader, createDebugLog, createNdjsonTail, createdDevicesFile, createdDevicesLock, debugLogDir, debugLoggingEnabled, decodeStats, deviceHostArea, deviceHostMachinesClaims, deviceHostMachinesFile, deviceHostMachinesLock, deviceHostRoot, deviceViewersDir, diskUsageCacheDir, diskUsageCacheFile, diskUsageFailureFile, diskUsageWalkClaims, easMachineStateRoot, easSessionLedgerFile, easSessionLedgerLock, emulatorLogFile, endedAgentSessionOf, endpoint, expectedShape, fileIdentity, fileSizes, findEnclosingWorktreeRoot, findPeer, findProjectRoot, fingerprintMemoDir, fingerprintMemoFile, fingerprintMemoLock, followLogs, footageDrops, gcLogDir, gcLogFile, getConcurrencyLimits, getConfigPath, getParkedMax, getProject, getProjectSettings, getRepoSettings, gitMergeCacheDir, hostedAgentDriverName, hostedAndroidDeviceName, hostedAndroidPlacements, hostedAndroidRecords, hostedAndroidStatus, hostedAppArea, hostedAppAttempt, hostedAppBlobs, hostedConsolePort, hostedDeviceId, hostedIosPlacements, hostedIosRecords, hostedIosStatus, hostedMacosAppSlot, hostedMacosBundleId, hostedMacosLogsDir, hostedMetroGateways, hostedMetroRequests, hostedNativeLogsDir, hostedNativeRecords, hostedWorkerSettleMs, isBuildLedgerRecord, isExpoErrorContext, isGcLogRecord, isJournalExpired, isJsonObject, isLayeredSetting, isPathPrefix, isSensitiveReference, isSetupJournalPrunable, lastNativeUseFrom, lastUseFrom, levelRank, linkReplacedArchives, listRecordedDevices, listRecordedDevicesAsync, listSegments, listSegmentsAsync, listStatusCacheEntries, loadConfig, logFiles, machineCacheUsageFile, machineCapacity, machineEndpoint, macosAppState, maintenanceAttemptFile, maintenanceChildLogFile, maintenanceDir, maintenanceNdjsonFile, maintenanceRunClaims, maintenanceStateFile, markerWindow, maxLoadPerCore, mayRunHere, offloadSummary, openLogDir, openSegmentName, parseHostedAgentAccess, parseHostedAgentGrant, parseHostedAndroidDevice, parseHostedAndroidPlacement, parseHostedAppManifest, parseHostedAppOffer, parseHostedChoice, parseHostedDevice, parseHostedIosPlacement, parseHostedLocalDeviceCount, parseHostedLogsCursor, parseHostedMacosChoice, parseHostedMacosDevice, parseHostedMacosPlacement, parseHostedNativeOffer, parseHostedNativePlacement, parseHostedOfferRequest, parseHostedPlatformDevice, parseHostedRequest, parseMachine, parseMachineCredential, parseMacosRecord, parseMaintenanceState, parseMissReason, parseNdjsonLine, parseNdjsonText, parseSetupJournal, parseSince, placementWord, planLogQuery, prefersRemote, projectRootDirectories, pullRequestCacheDir, pullRequestCacheFile, queryJsonLogs, queryLogs, readAgentDeviceUsage, readAgentDeviceUsageCache, readAgentSessionsCache, readArchive, readArchiveAsync, readArchiveState, readArchives, readArchivesAsync, readBuildDetail, readBuildHistory, readBuildLedger, readBuildMachines, readCreatedDevices, readDevServerStop, readDevServerStopRequest, readDeviceHostMachines, readDeviceIdleShutdowns, readDevicePlacement, readDiskUsage, readDiskUsageFailure, readEasSessionLedger, readEndedAgentSessions, readFingerprintMemo, readGcLog, readHomeIdentity, readHostedApp, readHostedAppMetadata, readHostedDevice, readHostedDeviceLedger, readHostedMacosApp, readHostedNativeLogsCheckpoint, readHostedSessions, readIdleStop, readJsonFile, readJsonObject, readLastBuilds, readLogRecords, readLogTimeline, readLogsSince, readMachineCacheUsage, readMacosRecord, readMaintenanceAttempt, readMaintenanceState, readNdjsonGenerations, readPullRequestCache, readRunEstimates, readSetupJournal, readStateFile, readStats, readStatsReport, readSwiftpmCacheUsage, readViewedDevices, readWarmRecord, readWorkspaceAgent, readWorkspaceState, recordMatches, recordedBytes, recordingDeviceName, recordingEnabled, redactArgv, redactCommandLine, rememberHostedAppBlobRename, replacementAdvice, requireAutomaticMachine, runId, saturation, serverLocalSocket, serverSetupDir, settingDefinition, settingValueError, settingsJsonSchema, setupJournalFile, sharedCcache, sharedCompilationCache, sharedGradle, sharedPods, sortByTs, statsFile, statsProjectKey, statusViews, stimBuildDigest, supervisorLogFile, supervisorPidFile, swiftpmCacheUsageFile, tailRead, trace, trashRoot, trimCapacityRefusals, trimCapacityWaits, trimSamples, tryAcquireBuildSlotClaim, unreadableHostedAndroid, unreadableHostedIos, unreadableHostedNative, validEasSessionClaim, validHostedAppArguments, validHostedAppBlob, validRunId, validateAutomaticPool, wholePhases, windowsShortDir, windowsShortDirKey, withConfigLock, withConfigLockAsync, withDerivedFacts, withGitChip, withStateReadCache, workspaceAgentDeviceDir, workspaceBuildDetailFile, workspaceDerivedData, workspaceEndedAgentsFile, workspaceEndedAgentsLock, workspaceGradleBuild, workspaceLastUsed, workspaceLightenedFile, workspaceLogErrorIndex, workspaceLogsDir, workspaceMetadataFile, workspaceRecordingsDir, workspaceStateFile, workspaceStateLock, workspaceSummary, worktreeArchiveRoot };