@stim-cli/core 1.17.2 → 1.19.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 { _ as releaseClaim, f as isClaimRefusal, g as readClaimSet, x as tryAcquireClaim } from "./ownership-claim-O31Y5iIb.mjs";
2
2
  import { inspectProcessIdentity } from "./process-identity.mjs";
3
- import { C as workspaceStateDir, h as rotatedLogPath, j as withDirLock, l as configDir, x as workspaceName } from "./core-DWOUn9xp.mjs";
4
- import { closeSync, existsSync, fstatSync, lstatSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, realpathSync, statSync } from "node:fs";
3
+ import { C as workspaceStateDir, h as rotatedLogPath, j as withDirLock, l as configDir, m as rotateLog, t as LOG_ROTATE_BYTES, x as workspaceName } from "./core-DWOUn9xp.mjs";
4
+ import { appendFileSync, closeSync, existsSync, fstatSync, lstatSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, realpathSync, statSync } from "node:fs";
5
5
  import { availableParallelism, homedir, loadavg } from "node:os";
6
6
  import { basename, dirname, isAbsolute, join, posix, relative, resolve, sep } from "node:path";
7
- import { createHash } from "node:crypto";
7
+ import { createHash, randomBytes } from "node:crypto";
8
8
  import { isIP } from "node:net";
9
9
  import { AsyncLocalStorage } from "node:async_hooks";
10
10
  import { StringDecoder } from "node:string_decoder";
@@ -148,8 +148,8 @@ function readCompleteLines(path, start) {
148
148
  let fd;
149
149
  try {
150
150
  fd = openSync(path, "r");
151
- const stat = fstatSync(fd);
152
- const size = stat.size;
151
+ const stat = fstatSync(fd, { bigint: true });
152
+ const size = Number(stat.size);
153
153
  const identity = `${stat.dev}:${stat.ino}`;
154
154
  if (size <= start) return {
155
155
  text: "",
@@ -488,6 +488,10 @@ function agentSessionsCacheFile() {
488
488
  function diskUsageCacheDir() {
489
489
  return join(configDir(), "disk-usage");
490
490
  }
491
+ /** The ownership claim root that admits one disk-usage walk at a time on this machine. */
492
+ function diskUsageWalkClaims() {
493
+ return join(configDir(), "disk-usage-walk.claims");
494
+ }
491
495
  /** The remote Macs this Mac paired with, each with its pinned tailnet node and device token. */
492
496
  function buildMachinesFile() {
493
497
  return join(configDir(), "build-machines.json");
@@ -1009,10 +1013,10 @@ const SETTINGS = [
1009
1013
  type: {
1010
1014
  kind: "string",
1011
1015
  pattern: TAILNET_MACHINE_PATTERN,
1012
- patternHelp: "eas, proxy, auto, or a tailnet machine name"
1016
+ patternHelp: "eas, proxy, auto, local, or a tailnet machine name"
1013
1017
  },
1014
1018
  scopes: EVERY,
1015
- description: "Default iOS remote target: eas, proxy, or an approved Mac in remote.machines; auto places on an approved Mac when this Mac is full or busy"
1019
+ description: "Default iOS remote target: eas, proxy, or an approved Mac in remote.machines; auto places on an approved Mac when this Mac is full or busy; local runs here, overriding a lower layer"
1016
1020
  },
1017
1021
  {
1018
1022
  key: "ios.simslimProfile",
@@ -1107,10 +1111,10 @@ const SETTINGS = [
1107
1111
  type: {
1108
1112
  kind: "string",
1109
1113
  pattern: TAILNET_MACHINE_PATTERN,
1110
- patternHelp: "eas, proxy, auto, or a tailnet machine name"
1114
+ patternHelp: "eas, proxy, auto, local, or a tailnet machine name"
1111
1115
  },
1112
1116
  scopes: EVERY,
1113
- description: "Default Android remote target: eas, proxy, or an approved Mac in remote.machines; auto places on an approved Mac when this Mac is full or busy"
1117
+ description: "Default Android remote target: eas, proxy, or an approved Mac in remote.machines; auto places on an approved Mac when this Mac is full or busy; local runs here, overriding a lower layer"
1114
1118
  },
1115
1119
  {
1116
1120
  key: "metro.tunnel",
@@ -1435,14 +1439,18 @@ const SETTINGS = [
1435
1439
  key: "maintenance.mode",
1436
1440
  type: {
1437
1441
  kind: "choice",
1438
- choices: ["off", "report"]
1442
+ choices: [
1443
+ "off",
1444
+ "report",
1445
+ "on"
1446
+ ]
1439
1447
  },
1440
1448
  scopes: MACHINE,
1441
- default: "report",
1449
+ default: "on",
1442
1450
  env: "STIM_MAINTENANCE",
1443
1451
  scopedHomeValue: "off",
1444
1452
  ciValue: "off",
1445
- description: "Automatic resource maintenance. report measures, plans and logs what it would do and never deletes or stops anything; off disables it. Off under STIM_HOME or CI unless STIM_MAINTENANCE is set"
1453
+ description: "Automatic resource maintenance. on removes what gc would remove under the caps and floors below and logs every action; report measures, plans and logs what it would do and never deletes anything; off disables it. Off under STIM_HOME or CI unless STIM_MAINTENANCE is set"
1446
1454
  },
1447
1455
  {
1448
1456
  key: "maintenance.pressureCheckMinutes",
@@ -1560,6 +1568,69 @@ const SETTINGS = [
1560
1568
  env: "STIM_MAINTENANCE_CAP_TARGET_PERCENT",
1561
1569
  description: "Plan toward this percentage of each size cap"
1562
1570
  },
1571
+ {
1572
+ key: "maintenance.worktreeCheckMinutes",
1573
+ type: {
1574
+ kind: "number",
1575
+ integer: true,
1576
+ minimum: 1
1577
+ },
1578
+ scopes: MACHINE,
1579
+ default: 15,
1580
+ env: "STIM_MAINTENANCE_WORKTREE_CHECK_MINUTES",
1581
+ description: "Finished-worktree check interval in minutes"
1582
+ },
1583
+ {
1584
+ key: "maintenance.sweepHours",
1585
+ type: {
1586
+ kind: "number",
1587
+ integer: true,
1588
+ minimum: 0
1589
+ },
1590
+ scopes: MACHINE,
1591
+ default: 24,
1592
+ env: "STIM_MAINTENANCE_SWEEP_HOURS",
1593
+ description: "Age sweep interval in hours; 0 turns the age sweep off"
1594
+ },
1595
+ {
1596
+ key: "maintenance.olderThanDays",
1597
+ type: {
1598
+ kind: "number",
1599
+ integer: true,
1600
+ minimum: 1
1601
+ },
1602
+ scopes: MACHINE,
1603
+ default: 7,
1604
+ env: "STIM_MAINTENANCE_OLDER_THAN_DAYS",
1605
+ description: "Age in days for the age sweep: unused workspace build outputs and shared cache entries"
1606
+ },
1607
+ {
1608
+ key: "maintenance.protectRecentHours",
1609
+ type: {
1610
+ kind: "number",
1611
+ integer: true,
1612
+ minimum: 0
1613
+ },
1614
+ scopes: MACHINE,
1615
+ default: 2,
1616
+ env: "STIM_MAINTENANCE_PROTECT_RECENT_HOURS",
1617
+ description: "Cache entries used within this many hours are never evicted"
1618
+ },
1619
+ {
1620
+ key: "maintenance.removeFinishedWorktrees",
1621
+ type: BOOLEAN,
1622
+ scopes: MACHINE,
1623
+ default: true,
1624
+ env: "STIM_MAINTENANCE_REMOVE_FINISHED_WORKTREES",
1625
+ description: "Remove clean linked worktrees whose branch or pull request finished, under gc.worktreeGraceMinutes"
1626
+ },
1627
+ {
1628
+ key: "maintenance.keep",
1629
+ type: BOOLEAN,
1630
+ scopes: PROJECT,
1631
+ default: false,
1632
+ description: "Pin this workspace: automatic maintenance never clears its build outputs or removes its worktree"
1633
+ },
1563
1634
  {
1564
1635
  key: "maintenance.workspaceOutputsMaxGb",
1565
1636
  type: {
@@ -1604,6 +1675,17 @@ const SETTINGS = [
1604
1675
  env: "STIM_CACHES_SWIFT_COMPILATION_CACHE_MAX_GB",
1605
1676
  description: "Swift compilation-cache cap in GiB; planned emptying is whole; 0 means no cap"
1606
1677
  },
1678
+ {
1679
+ key: "caches.ccacheMaxGb",
1680
+ type: {
1681
+ kind: "number",
1682
+ exclusiveMinimum: 0
1683
+ },
1684
+ scopes: MACHINE,
1685
+ default: 5,
1686
+ env: "STIM_CACHES_CCACHE_MAX_GB",
1687
+ description: "ccache size limit in GiB, passed to ccache as CCACHE_MAXSIZE; ccache evicts by itself"
1688
+ },
1607
1689
  {
1608
1690
  key: "gc.worktreeGraceMinutes",
1609
1691
  type: CAPACITY,
@@ -1630,6 +1712,14 @@ const SETTINGS = [
1630
1712
  scopedHomeValue: 0,
1631
1713
  description: "Parked emulators kept for adoption; 0 turns parking off"
1632
1714
  },
1715
+ {
1716
+ key: "debug.logs",
1717
+ type: { kind: "boolean" },
1718
+ scopes: MACHINE,
1719
+ default: false,
1720
+ env: "STIM_DEBUG",
1721
+ description: "Debug-level logging. While on, the CLI records its commands, child processes and requests to other Macs, and stim-server records every request with its timings, under STIM_HOME/logs/debug/ with rotation. Nothing is sent anywhere, and records never carry arguments, tokens or tickets"
1722
+ },
1633
1723
  {
1634
1724
  key: "hosting.agentDriver",
1635
1725
  type: {
@@ -1653,6 +1743,27 @@ const SETTINGS = [
1653
1743
  scopes: MACHINE,
1654
1744
  description: "Tailscale names of the remote Macs this Mac 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"
1655
1745
  },
1746
+ {
1747
+ key: "remote.buildPoolDisabled",
1748
+ type: { kind: "strings" },
1749
+ scopes: MACHINE,
1750
+ default: [],
1751
+ description: "Members excluded from this requester's automatic build placement: local or exact remote.machines entries. Explicit placement and running builds are unaffected; at least one local or configured, approved remote member must stay enabled"
1752
+ },
1753
+ {
1754
+ key: "remote.devicePoolDisabled",
1755
+ type: { kind: "strings" },
1756
+ scopes: MACHINE,
1757
+ default: [],
1758
+ description: "Members excluded from this requester's automatic simulator and emulator placement: local or exact remote.machines entries. Explicit placement and existing sessions are unaffected; at least one local or configured, approved remote member must stay enabled"
1759
+ },
1760
+ {
1761
+ key: "remote.easFallback",
1762
+ type: BOOLEAN,
1763
+ scopes: EVERY,
1764
+ default: false,
1765
+ description: "When ios.remote or android.remote is auto, this Mac is at its concurrency.maxDevices cap and no Mac in remote.machines takes the run, run the simulator or emulator on a billed EAS Simulator instead of waiting or refusing, when eas-cli can"
1766
+ },
1656
1767
  {
1657
1768
  key: "remote.build",
1658
1769
  type: {
@@ -1663,7 +1774,7 @@ const SETTINGS = [
1663
1774
  scopes: MACHINE,
1664
1775
  default: "auto",
1665
1776
  env: "STIM_REMOTE_BUILD",
1666
- description: "Build placement: auto follows remote.buildMode with local fallback; local always builds here; a name in remote.machines requires that remote Mac without fallback. The ios, android and macos --remote-build flag overrides this setting and its environment override"
1777
+ description: "Build placement: auto follows remote.buildMode within enabled automatic pool members; local always builds here; a name in remote.machines requires that remote Mac without fallback. The ios, android and macos --remote-build flag overrides this setting and its environment override"
1667
1778
  },
1668
1779
  {
1669
1780
  key: "remote.buildMode",
@@ -1674,7 +1785,7 @@ const SETTINGS = [
1674
1785
  scopes: MACHINE,
1675
1786
  default: "auto",
1676
1787
  env: "STIM_REMOTE_BUILD_MODE",
1677
- description: "When remote.build is auto, where iOS simulator Debug, Android emulator debug and macOS SwiftPM Debug builds run: auto builds here while this Mac has a free concurrency.maxBuilds slot and its load is under server.maxLoadPerCore, and otherwise builds on a less loaded Mac in remote.machines; force builds on a remote Mac whenever one can take the build; off always builds here"
1788
+ description: "When remote.build is auto, where iOS simulator Debug, Android emulator debug and macOS SwiftPM Debug builds run: auto builds here while this Mac has a free concurrency.maxBuilds slot and its load is under server.maxLoadPerCore, and otherwise builds on a less loaded Mac in remote.machines; force builds on an enabled remote Mac whenever one can take the build; off builds here when local is enabled in remote.buildPoolDisabled"
1678
1789
  },
1679
1790
  {
1680
1791
  key: "server.maxLoadPerCore",
@@ -1971,6 +2082,136 @@ function readBuildMachines() {
1971
2082
  }
1972
2083
  }
1973
2084
  //#endregion
2085
+ //#region state/device-host-machines.ts
2086
+ /** An absent store is empty; unreadable or malformed credentials refuse access without discarding pins. */
2087
+ function readDeviceHostMachines() {
2088
+ let value;
2089
+ try {
2090
+ value = readJsonFile(deviceHostMachinesFile());
2091
+ } catch (error) {
2092
+ if (error.code === "ENOENT") return [];
2093
+ throw error;
2094
+ }
2095
+ if (!isJsonObject(value) || value.version !== 1 || !Array.isArray(value.machines)) throw new Error("Invalid device-host machine credential store");
2096
+ const machines = [];
2097
+ for (const entry of value.machines) {
2098
+ if (!isJsonObject(entry) || ![
2099
+ "machine",
2100
+ "nodeId",
2101
+ "dnsName",
2102
+ "deviceId",
2103
+ "deviceToken",
2104
+ "requestedAt"
2105
+ ].every((key) => typeof entry[key] === "string" && entry[key]) || entry.state !== "pending" && entry.state !== "approved" || machines.some((each) => each.machine === entry.machine)) throw new Error("Invalid device-host machine credential store");
2106
+ const { ticketHash, expiresAt, ...credential } = entry;
2107
+ machines.push({
2108
+ ...credential,
2109
+ ...typeof expiresAt === "string" && expiresAt ? { expiresAt } : {},
2110
+ ...typeof ticketHash === "string" ? { ticketHash } : {}
2111
+ });
2112
+ }
2113
+ return machines;
2114
+ }
2115
+ //#endregion
2116
+ //#region state/automatic-pools.ts
2117
+ function automaticMachineEnabled(role, machine, config = loadConfig()) {
2118
+ const key = `${role}PoolDisabled`;
2119
+ const disabled = config?.remote?.[key];
2120
+ if (disabled === void 0) return true;
2121
+ if (!Array.isArray(disabled) || disabled.some((entry) => typeof entry !== "string" || !entry.trim())) throw Object.assign(/* @__PURE__ */ new Error(`remote.${key} must be a list of machine names or local.`), { code: "STIM_BAD_ARG" });
2122
+ return !disabled.includes(machine);
2123
+ }
2124
+ function requireAutomaticMachine(role, machine) {
2125
+ if (automaticMachineEnabled(role, machine)) return;
2126
+ throw Object.assign(/* @__PURE__ */ new Error(`${machine} is disabled in this requester's automatic ${role} pool.`), {
2127
+ code: role === "build" ? "STIM_OFFLOAD_REFUSED" : "STIM_HOSTING_REFUSED",
2128
+ remedy: `Enable it in remote.${role}PoolDisabled or select a machine explicitly.`
2129
+ });
2130
+ }
2131
+ function validateAutomaticPool(role, config) {
2132
+ if (automaticMachineEnabled(role, "local", config)) return;
2133
+ const configured = config.remote?.machines;
2134
+ const approved = role === "build" ? readBuildMachines() : readDeviceHostMachines();
2135
+ if (Array.isArray(configured) && configured.some((machine) => typeof machine === "string" && automaticMachineEnabled(role, machine, config) && approved.some((entry) => entry.machine === machine && entry.state === "approved"))) return;
2136
+ throw Object.assign(/* @__PURE__ */ new Error(`Keep at least one enabled automatic ${role} pool member: local or a configured, approved remote machine.`), { code: "STIM_BAD_ARG" });
2137
+ }
2138
+ //#endregion
2139
+ //#region state/debug-log.ts
2140
+ const DEBUG_ENV = "STIM_DEBUG";
2141
+ const ENABLED_RECHECK_MS = 5e3;
2142
+ const ROTATE_CHECK_BYTES = 262144;
2143
+ const SECRET_KEY = /token|secret|ticket|password|passphrase|authorization|credential|cookie|apikey/i;
2144
+ const MAX_DEPTH = 4;
2145
+ function debugLogDir() {
2146
+ return join(configDir(), "logs", "debug");
2147
+ }
2148
+ /** The `STIM_DEBUG` override (1/true on, 0/false off, anything else off), else the machine setting `debug.logs`. Never throws. */
2149
+ function debugLoggingEnabled(env = process.env) {
2150
+ const definition = settingDefinition("debug.logs");
2151
+ const raw = env[DEBUG_ENV];
2152
+ if (raw !== void 0 && raw !== "") {
2153
+ const value = coerceSettingText(definition, raw);
2154
+ return settingValueError(definition, value) === null && value === true;
2155
+ }
2156
+ try {
2157
+ return loadConfig()?.debug?.logs === true;
2158
+ } catch {
2159
+ return false;
2160
+ }
2161
+ }
2162
+ function scrub(value, depth = 0) {
2163
+ if (depth > MAX_DEPTH) return "[truncated]";
2164
+ if (Array.isArray(value)) return value.slice(0, 50).map((each) => scrub(each, depth + 1));
2165
+ if (value && typeof value === "object") {
2166
+ const out = {};
2167
+ for (const [key, each] of Object.entries(value)) out[key] = SECRET_KEY.test(key) ? "[redacted]" : scrub(each, depth + 1);
2168
+ return out;
2169
+ }
2170
+ return typeof value === "string" && value.length > 500 ? `${value.slice(0, 500)}...` : value;
2171
+ }
2172
+ /**
2173
+ * Debug-level records for one component (`cli` or `server`). Off by default; `STIM_DEBUG=1` or `debug.logs` turns it
2174
+ * on. Callers pass names, durations and codes, never arguments, environment values, tokens or tickets.
2175
+ */
2176
+ function createDebugLog(component, { env = process.env, now = Date.now, base = () => ({}) } = {}) {
2177
+ let checkedAt = Number.NEGATIVE_INFINITY;
2178
+ let on = false;
2179
+ let unchecked = ROTATE_CHECK_BYTES;
2180
+ const enabled = () => {
2181
+ const at = now();
2182
+ if (at - checkedAt >= ENABLED_RECHECK_MS) {
2183
+ checkedAt = at;
2184
+ on = debugLoggingEnabled(env);
2185
+ }
2186
+ return on;
2187
+ };
2188
+ return {
2189
+ enabled,
2190
+ log(event, fields = {}) {
2191
+ if (!enabled()) return;
2192
+ try {
2193
+ const file = join(debugLogDir(), `${component}.ndjson`);
2194
+ const line = `${JSON.stringify({
2195
+ ts: now(),
2196
+ level: "debug",
2197
+ src: component,
2198
+ event,
2199
+ pid: process.pid,
2200
+ ...base(),
2201
+ ...scrub(fields)
2202
+ })}\n`;
2203
+ mkdirSync(debugLogDir(), { recursive: true });
2204
+ if (unchecked >= ROTATE_CHECK_BYTES) {
2205
+ unchecked = 0;
2206
+ rotateLog(file, LOG_ROTATE_BYTES);
2207
+ }
2208
+ appendFileSync(file, line, { mode: 384 });
2209
+ unchecked += line.length;
2210
+ } catch {}
2211
+ }
2212
+ };
2213
+ }
2214
+ //#endregion
1974
2215
  //#region state/ledgers.ts
1975
2216
  function ids(value) {
1976
2217
  return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && entry !== "") : [];
@@ -2128,7 +2369,8 @@ const SOURCES = [
2128
2369
  "device",
2129
2370
  "build",
2130
2371
  "agent",
2131
- "maintenance"
2372
+ "maintenance",
2373
+ "placement"
2132
2374
  ];
2133
2375
  function levelRank(level) {
2134
2376
  const i = LEVELS.indexOf(level);
@@ -2740,6 +2982,23 @@ function recordingEnabled(env, layers) {
2740
2982
  return true;
2741
2983
  }
2742
2984
  //#endregion
2985
+ //#region state/run-id.ts
2986
+ const RUN_ID_ENV = "STIM_RUN_ID";
2987
+ const RUN_ID_PATTERN = /^[A-Za-z0-9._-]{1,64}$/;
2988
+ /** A run id as the CLI and stim-server accept it: letters, digits, `.`, `_` and `-`, at most 64. Null otherwise. */
2989
+ function validRunId(value) {
2990
+ return typeof value === "string" && RUN_ID_PATTERN.test(value) ? value : null;
2991
+ }
2992
+ let current = null;
2993
+ /**
2994
+ * The id of this CLI invocation: `STIM_RUN_ID` when it holds a valid id (Stim Desktop passes one), else a random one.
2995
+ * The CLI entry exports it back to `STIM_RUN_ID` so processes the run starts inherit it; this function does not.
2996
+ */
2997
+ function runId(env = process.env) {
2998
+ if (current === null) current = validRunId(env["STIM_RUN_ID"]) ?? randomBytes(6).toString("hex");
2999
+ return current;
3000
+ }
3001
+ //#endregion
2743
3002
  //#region state/settings-schema.ts
2744
3003
  const SETTINGS_SCHEMA_FILE = "settings.schema.json";
2745
3004
  const SETTINGS_SCHEMA_URL = `https://unpkg.com/stim/dist/${SETTINGS_SCHEMA_FILE}`;
@@ -2923,7 +3182,7 @@ const WORKSPACE_PHASES = [
2923
3182
  "idle"
2924
3183
  ];
2925
3184
  /** The tutorial format version the installed Stim writes into the tutorial app. */
2926
- const TUTORIAL_VERSION = 1;
3185
+ const TUTORIAL_VERSION = 2;
2927
3186
  /**
2928
3187
  * Where a memory figure comes from. `footprint` is each process's physical footprint, which Activity Monitor's Memory
2929
3188
  * column shows. `rss` sums resident set sizes, which count pages shared between processes once per process, so a
@@ -3103,6 +3362,10 @@ function cacheName(path) {
3103
3362
  function diskUsageCacheFile(path) {
3104
3363
  return join(diskUsageCacheDir(), cacheName(path));
3105
3364
  }
3365
+ /** The file that records when the last walk of `path` failed, so other processes do not repeat it at once. */
3366
+ function diskUsageFailureFile(path) {
3367
+ return join(diskUsageCacheDir(), cacheName(path).replace(/\.json$/, ".failed.json"));
3368
+ }
3106
3369
  /** The file that caches the pull request of the worktree at `path`. */
3107
3370
  function pullRequestCacheFile(path) {
3108
3371
  return join(pullRequestCacheDir(), cacheName(path));
@@ -3202,6 +3465,12 @@ function readDiskUsage(path) {
3202
3465
  measuredAt
3203
3466
  };
3204
3467
  }
3468
+ /** When the last walk of `path` failed (an ISO time), or null when none is recorded. */
3469
+ function readDiskUsageFailure(path) {
3470
+ const entry = readJsonObject(diskUsageFailureFile(path));
3471
+ if (!entry || entry.path !== path || typeof entry.failedAt !== "string") return null;
3472
+ return Number.isFinite(Date.parse(entry.failedAt)) ? entry.failedAt : null;
3473
+ }
3205
3474
  function countOrNull(value) {
3206
3475
  return typeof value === "number" && Number.isInteger(value) && value >= 0 ? value : null;
3207
3476
  }
@@ -3443,7 +3712,7 @@ function buildDiagnostics(value) {
3443
3712
  function devicePlacement(value) {
3444
3713
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
3445
3714
  const record = value;
3446
- if (record.decision !== "local" && record.decision !== "hosted" && record.decision !== "waited-locally" || typeof record.reason !== "string") return null;
3715
+ if (record.decision !== "local" && record.decision !== "hosted" && record.decision !== "waited-locally" && record.decision !== "eas" || typeof record.reason !== "string") return null;
3447
3716
  return {
3448
3717
  decision: record.decision,
3449
3718
  reason: record.reason,
@@ -3513,7 +3782,8 @@ function historyEntry(platform, value) {
3513
3782
  slot: typeof record.slot === "string" && record.slot ? record.slot : "default",
3514
3783
  configuration: typeof record.configuration === "string" ? record.configuration : null,
3515
3784
  cacheKey: typeof record.cacheKey === "string" ? record.cacheKey : null,
3516
- phases: historyPhases(record.phases)
3785
+ phases: historyPhases(record.phases),
3786
+ ...typeof record.compileSteps === "number" && Number.isInteger(record.compileSteps) && record.compileSteps >= 0 ? { compileSteps: record.compileSteps } : {}
3517
3787
  };
3518
3788
  }
3519
3789
  /** Each platform's recorded runs, newest first, at most `BUILD_HISTORY_LIMIT` each. */
@@ -3544,11 +3814,13 @@ function lastUseFrom(state, logMtimes) {
3544
3814
  ].filter(Number.isFinite);
3545
3815
  return candidates.length ? Math.max(...candidates) : NaN;
3546
3816
  }
3817
+ const MAINTENANCE_LOG_NAME = "maintenance.ndjson";
3547
3818
  function workspaceLastUsed(root) {
3548
3819
  const logs = workspaceLogsDir(root);
3549
3820
  let mtimes = [];
3550
3821
  try {
3551
3822
  mtimes = readdirSync(logs).flatMap((name) => {
3823
+ if (name.startsWith("maintenance.ndjson")) return [];
3552
3824
  try {
3553
3825
  return [statSync(join(logs, name)).mtimeMs];
3554
3826
  } catch {
@@ -3985,7 +4257,7 @@ function readStatsReport(key, now) {
3985
4257
  note
3986
4258
  };
3987
4259
  }
3988
- function findProjectRoot(startDir) {
4260
+ function* projectRootDirectories(startDir) {
3989
4261
  let dir;
3990
4262
  try {
3991
4263
  dir = realpathSync(resolve(startDir));
@@ -3993,12 +4265,16 @@ function findProjectRoot(startDir) {
3993
4265
  dir = resolve(startDir);
3994
4266
  }
3995
4267
  while (true) {
3996
- if (existsSync(join(dir, "package.json")) || existsSync(join(dir, "Package.swift"))) return dir;
4268
+ yield dir;
3997
4269
  const parent = dirname(dir);
3998
- if (parent === dir) return null;
4270
+ if (parent === dir) return;
3999
4271
  dir = parent;
4000
4272
  }
4001
4273
  }
4274
+ function findProjectRoot(startDir) {
4275
+ for (const dir of projectRootDirectories(startDir)) if (existsSync(join(dir, "package.json")) || existsSync(join(dir, "Package.swift"))) return dir;
4276
+ return null;
4277
+ }
4002
4278
  //#endregion
4003
4279
  //#region state/device-host.ts
4004
4280
  function deviceHostRoot() {
@@ -4320,37 +4596,6 @@ function readHostedApp(session, attempt, workerHome) {
4320
4596
  };
4321
4597
  }
4322
4598
  //#endregion
4323
- //#region state/device-host-machines.ts
4324
- /** An absent store is empty; unreadable or malformed credentials refuse access without discarding pins. */
4325
- function readDeviceHostMachines() {
4326
- let value;
4327
- try {
4328
- value = readJsonFile(deviceHostMachinesFile());
4329
- } catch (error) {
4330
- if (error.code === "ENOENT") return [];
4331
- throw error;
4332
- }
4333
- if (!isJsonObject(value) || value.version !== 1 || !Array.isArray(value.machines)) throw new Error("Invalid device-host machine credential store");
4334
- const machines = [];
4335
- for (const entry of value.machines) {
4336
- if (!isJsonObject(entry) || ![
4337
- "machine",
4338
- "nodeId",
4339
- "dnsName",
4340
- "deviceId",
4341
- "deviceToken",
4342
- "requestedAt"
4343
- ].every((key) => typeof entry[key] === "string" && entry[key]) || entry.state !== "pending" && entry.state !== "approved" || machines.some((each) => each.machine === entry.machine)) throw new Error("Invalid device-host machine credential store");
4344
- const { ticketHash, expiresAt, ...credential } = entry;
4345
- machines.push({
4346
- ...credential,
4347
- ...typeof expiresAt === "string" && expiresAt ? { expiresAt } : {},
4348
- ...typeof ticketHash === "string" ? { ticketHash } : {}
4349
- });
4350
- }
4351
- return machines;
4352
- }
4353
- //#endregion
4354
4599
  //#region state/macos.ts
4355
4600
  function processRecord(value) {
4356
4601
  if (!value || typeof value !== "object") return void 0;
@@ -4365,7 +4610,7 @@ function processRecord(value) {
4365
4610
  }
4366
4611
  function parseMacosRecord(value) {
4367
4612
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
4368
- const { launchId, arguments: args, product, bundle, bundleId, executable, build, supervisor, app, host, hostLaunched } = value;
4613
+ const { launchId, arguments: args, product, displayName, bundle, bundleId, executable, build, supervisor, app, host, hostLaunched } = value;
4369
4614
  if (typeof launchId !== "string" || !Array.isArray(args) || args.some((arg) => typeof arg !== "string")) return null;
4370
4615
  if ([
4371
4616
  product,
@@ -4387,6 +4632,7 @@ function parseMacosRecord(value) {
4387
4632
  launchId,
4388
4633
  arguments: args,
4389
4634
  product,
4635
+ ...typeof displayName === "string" ? { displayName } : {},
4390
4636
  bundle,
4391
4637
  bundleId,
4392
4638
  executable,
@@ -4667,7 +4913,10 @@ const KINDS = [
4667
4913
  "would-trim-cache",
4668
4914
  "would-empty-cache",
4669
4915
  "would-shutdown-device",
4670
- "would-stop-workspace"
4916
+ "would-stop-workspace",
4917
+ "would-remove-worktree",
4918
+ "would-remove-orphan",
4919
+ "would-unregister-cache"
4671
4920
  ];
4672
4921
  /** Rejects missing, corrupt or unsupported payloads without throwing. */
4673
4922
  function parseMaintenanceState(value) {
@@ -4683,7 +4932,11 @@ function parseMaintenanceState(value) {
4683
4932
  "ccache",
4684
4933
  "other"
4685
4934
  ].includes(String(size.category)) && (size.workspace === void 0 || typeof size.workspace === "string") && (size.blocked === void 0 || typeof size.blocked === "string") && (size.idleDays === void 0 || nullableNumber(size.idleDays)))) return null;
4686
- if (!Array.isArray(value.plan) || !value.plan.every((action) => isJsonObject(action) && KINDS.includes(String(action.kind)) && typeof action.target === "string" && finite(action.bytes) && typeof action.reason === "string" && (action.workspace === void 0 || typeof action.workspace === "string"))) return null;
4935
+ if (!Array.isArray(value.plan) || !value.plan.every((action) => isJsonObject(action) && KINDS.includes(String(action.kind)) && typeof action.target === "string" && finite(action.bytes) && typeof action.reason === "string" && (action.workspace === void 0 || typeof action.workspace === "string") && (action.dir === void 0 || typeof action.dir === "string") && (action.olderThanDays === void 0 || finite(action.olderThanDays)) && (action.check === void 0 || [
4936
+ "worktree",
4937
+ "sweep",
4938
+ "disk"
4939
+ ].includes(String(action.check))))) return null;
4687
4940
  if (!Array.isArray(value.recent) || !value.recent.every((record) => isJsonObject(record) && record.src === "maintenance" && finite(record.ts) && typeof record.msg === "string" && [
4688
4941
  "debug",
4689
4942
  "info",
@@ -4695,8 +4948,8 @@ function parseMaintenanceState(value) {
4695
4948
  "maintenance_skip",
4696
4949
  "maintenance_failure",
4697
4950
  "maintenance_check"
4698
- ].includes(String(record.event)) && typeof record.pass === "string" && typeof record.trigger === "string" && record.mode === "report")) return null;
4699
- if (value.lastPass !== null && (!isJsonObject(value.lastPass) || !finite(value.lastPass.startedAt) || !finite(value.lastPass.durationMs) || typeof value.lastPass.trigger !== "string" || value.lastPass.mode !== "report" || value.lastPass.freedBytes !== 0 || value.lastPass.stopped !== 0 || !finite(value.lastPass.actions) || !strings(value.lastPass.blocked))) return null;
4951
+ ].includes(String(record.event)) && typeof record.pass === "string" && typeof record.trigger === "string" && (record.mode === "report" || record.mode === "on"))) return null;
4952
+ if (value.lastPass !== null && (!isJsonObject(value.lastPass) || !finite(value.lastPass.startedAt) || !finite(value.lastPass.durationMs) || typeof value.lastPass.trigger !== "string" || value.lastPass.mode !== "report" && value.lastPass.mode !== "on" || !finite(value.lastPass.freedBytes) || value.lastPass.stopped !== 0 || !finite(value.lastPass.actions) || !strings(value.lastPass.blocked))) return null;
4700
4953
  if (value.pressure !== null) {
4701
4954
  const pressure = value.pressure;
4702
4955
  if (!isJsonObject(pressure) || !Array.isArray(pressure.disk) || !pressure.disk.every((disk) => isJsonObject(disk) && typeof disk.volume === "string" && finite(disk.freeMb)) || !nullableNumber(pressure.warningSince) || !isJsonObject(pressure.memory) || ![
@@ -4875,4 +5128,4 @@ function isSetupJournalPrunable(journal, now) {
4875
5128
  return Date.parse(journal.expiresAt) + 36e5 < now;
4876
5129
  }
4877
5130
  //#endregion
4878
- 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, DEVICE_IDLE_SHUTDOWN_KEY, DEVICE_RECLAIM_REASON, DEV_SERVER_STOP_REQUEST_KEY, ENDED_AGENT_RETENTION_MS, ERROR_SOURCES, 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, IDLE_STOP_KEY, IOS_SIMULATOR_APPS, LAST_BUILD_KEYS, LEVELS, MACHINE_OWNER_KINDS, 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, SETTINGS, SETTINGS_SCHEMA_FILE, SETTINGS_SCHEMA_URL, SETTING_GROUPS, SETTING_SCOPES, SOURCES, STATS_VERSION, STATUS_ISSUE_CODES, 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, agentDeviceUsageFile, agentSessionOf, agentSessionsCacheFile, allMetroPorts, archiveDir, archiveEnabled, archiveLock, archiveRoot, archivedUsage, assertHostedDeviceLedger, attachExpoErrorContext, buildCriteria, buildDiagnostics, buildMachinesFile, buildMachinesLock, buildSlotPath, buildSlotsDir, buildWorkerRoot, bundleMarkerPlatform, capDrops, closedSegmentName, coerceSettingText, compileGrep, configCorruptRepair, configLockPath, countErrorEntries, createAgentActionReader, createdDevicesFile, createdDevicesLock, decodeStats, deviceHostArea, deviceHostMachinesClaims, deviceHostMachinesFile, deviceHostMachinesLock, deviceHostRoot, deviceViewersDir, diskUsageCacheDir, diskUsageCacheFile, easMachineStateRoot, easSessionLedgerFile, easSessionLedgerLock, emulatorLogFile, endedAgentSessionOf, endpoint, expectedShape, fileSizes, findEnclosingWorktreeRoot, findPeer, findProjectByMetroPort, findProjectRoot, followLogs, footageDrops, getConcurrencyLimits, getConfigPath, getParkedMax, getProject, getProjectSetting, getProjectSettings, getRepoSettings, gitMergeCacheDir, hostedAndroidDeviceName, hostedAndroidPlacements, hostedAndroidRecords, hostedAndroidStatus, hostedAppArea, hostedAppAttempt, hostedAppBlobs, hostedConsolePort, hostedDeviceId, hostedIosPlacements, hostedIosRecords, hostedIosStatus, hostedMacosAppSlot, hostedMacosBundleId, hostedMacosLogsDir, hostedMetroGateways, hostedMetroRequests, hostedNativeLogsDir, hostedNativeRecords, isJournalExpired, isJsonObject, isLayeredSetting, isPathPrefix, isSensitiveReference, isSetupJournalPrunable, lastUseFrom, levelRank, linkReplacedArchives, listRecordedDevices, listSegments, listStatusCacheEntries, loadConfig, logFiles, machineCapacity, macosAppState, maintenanceAttemptFile, maintenanceChildLogFile, maintenanceDir, maintenanceNdjsonFile, maintenanceRunClaims, maintenanceStateFile, markerWindow, offloadSummary, openSegmentName, parseHostedAgentAccess, parseHostedAgentGrant, parseHostedAndroidDevice, parseHostedAndroidPlacement, parseHostedAppManifest, parseHostedAppOffer, parseHostedChoice, parseHostedDevice, parseHostedIosPlacement, parseHostedLocalDeviceCount, parseHostedLogsCursor, parseHostedMacosChoice, parseHostedMacosDevice, parseHostedMacosPlacement, parseHostedNativeOffer, parseHostedNativePlacement, parseHostedOfferRequest, parseHostedPlatformDevice, parseHostedRequest, parseMachine, parseMacosRecord, parseMaintenanceState, parseMissReason, parseNdjsonLine, parseNdjsonText, parseSetupJournal, parseSince, pinnedEndpoint, pullRequestCacheDir, pullRequestCacheFile, queryJsonLogs, queryLogs, readAgentDeviceUsage, readAgentDeviceUsageCache, readAgentSessionsCache, readArchive, readArchiveState, readArchives, readBuildDetail, readBuildHistory, readBuildMachines, readCreatedDevices, readDevServerStop, readDevServerStopRequest, readDeviceHostMachines, readDeviceIdleShutdowns, readDevicePlacement, readDiskUsage, readEasSessionLedger, readEndedAgentSessions, readHostedApp, readHostedAppMetadata, readHostedDevice, readHostedDeviceLedger, readHostedMacosApp, readHostedNativeLogsCheckpoint, readHostedSessions, readIdleStop, readJsonFile, readJsonObject, readLastBuilds, readLogRecords, readLogTimeline, readLogsSince, readMacosRecord, readMaintenanceAttempt, readMaintenanceState, readNdjsonGenerations, readPullRequestCache, readRunEstimates, readSetupJournal, readStateFile, readStats, readStatsReport, readSwiftpmCacheUsage, readViewedDevices, readWarmRecord, readWorkspaceAgent, readWorkspaceState, recordMatches, recordedBytes, recordingDeviceName, recordingEnabled, rememberHostedAppBlobRename, saturation, serverSetupDir, settingDefinition, settingValueError, settingsJsonSchema, setupJournalFile, sharedCcache, sharedCompilationCache, sharedGradle, sharedPods, sortByTs, statsFile, statsProjectKey, stimBuildDigest, supervisorLogFile, supervisorPidFile, swiftpmCacheUsageFile, tailRead, trimCapacityRefusals, trimCapacityWaits, trimSamples, tryAcquireBuildSlotClaim, unreadableHostedAndroid, unreadableHostedIos, unreadableHostedNative, validEasSessionClaim, validHostedAppArguments, validHostedAppBlob, wholePhases, withConfigLock, withDerivedFacts, withGitChip, withStateReadCache, workspaceAgentDeviceDir, workspaceBuildDetailFile, workspaceDerivedData, workspaceEndedAgentsFile, workspaceEndedAgentsLock, workspaceGradleBuild, workspaceLastUsed, workspaceLogErrorIndex, workspaceLogsDir, workspaceMetadataFile, workspaceRecordingsDir, workspaceStateFile, workspaceStateLock };
5131
+ 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_IDLE_SHUTDOWN_KEY, DEVICE_RECLAIM_REASON, DEV_SERVER_STOP_REQUEST_KEY, ENDED_AGENT_RETENTION_MS, ERROR_SOURCES, 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, IDLE_STOP_KEY, IOS_SIMULATOR_APPS, LAST_BUILD_KEYS, LEVELS, 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, 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, agentDeviceUsageFile, agentSessionOf, agentSessionsCacheFile, allMetroPorts, archiveDir, archiveEnabled, archiveLock, archiveRoot, archivedUsage, assertHostedDeviceLedger, attachExpoErrorContext, automaticMachineEnabled, buildCriteria, buildDiagnostics, buildMachinesFile, buildMachinesLock, buildSlotPath, buildSlotsDir, buildWorkerRoot, bundleMarkerPlatform, capDrops, closedSegmentName, coerceSettingText, compileGrep, configCorruptRepair, configLockPath, countErrorEntries, createAgentActionReader, createDebugLog, createdDevicesFile, createdDevicesLock, debugLogDir, debugLoggingEnabled, decodeStats, deviceHostArea, deviceHostMachinesClaims, deviceHostMachinesFile, deviceHostMachinesLock, deviceHostRoot, deviceViewersDir, diskUsageCacheDir, diskUsageCacheFile, diskUsageFailureFile, diskUsageWalkClaims, easMachineStateRoot, easSessionLedgerFile, easSessionLedgerLock, emulatorLogFile, endedAgentSessionOf, endpoint, expectedShape, fileSizes, findEnclosingWorktreeRoot, findPeer, findProjectByMetroPort, findProjectRoot, followLogs, footageDrops, getConcurrencyLimits, getConfigPath, getParkedMax, getProject, getProjectSetting, getProjectSettings, getRepoSettings, gitMergeCacheDir, hostedAndroidDeviceName, hostedAndroidPlacements, hostedAndroidRecords, hostedAndroidStatus, hostedAppArea, hostedAppAttempt, hostedAppBlobs, hostedConsolePort, hostedDeviceId, hostedIosPlacements, hostedIosRecords, hostedIosStatus, hostedMacosAppSlot, hostedMacosBundleId, hostedMacosLogsDir, hostedMetroGateways, hostedMetroRequests, hostedNativeLogsDir, hostedNativeRecords, isJournalExpired, isJsonObject, isLayeredSetting, isPathPrefix, isSensitiveReference, isSetupJournalPrunable, lastUseFrom, levelRank, linkReplacedArchives, listRecordedDevices, listSegments, listStatusCacheEntries, loadConfig, logFiles, machineCapacity, macosAppState, maintenanceAttemptFile, maintenanceChildLogFile, maintenanceDir, maintenanceNdjsonFile, maintenanceRunClaims, maintenanceStateFile, markerWindow, offloadSummary, openSegmentName, parseHostedAgentAccess, parseHostedAgentGrant, parseHostedAndroidDevice, parseHostedAndroidPlacement, parseHostedAppManifest, parseHostedAppOffer, parseHostedChoice, parseHostedDevice, parseHostedIosPlacement, parseHostedLocalDeviceCount, parseHostedLogsCursor, parseHostedMacosChoice, parseHostedMacosDevice, parseHostedMacosPlacement, parseHostedNativeOffer, parseHostedNativePlacement, parseHostedOfferRequest, parseHostedPlatformDevice, parseHostedRequest, parseMachine, parseMacosRecord, parseMaintenanceState, parseMissReason, parseNdjsonLine, parseNdjsonText, parseSetupJournal, parseSince, pinnedEndpoint, projectRootDirectories, pullRequestCacheDir, pullRequestCacheFile, queryJsonLogs, queryLogs, readAgentDeviceUsage, readAgentDeviceUsageCache, readAgentSessionsCache, readArchive, readArchiveState, readArchives, readBuildDetail, readBuildHistory, readBuildMachines, readCreatedDevices, readDevServerStop, readDevServerStopRequest, readDeviceHostMachines, readDeviceIdleShutdowns, readDevicePlacement, readDiskUsage, readDiskUsageFailure, readEasSessionLedger, readEndedAgentSessions, readHostedApp, readHostedAppMetadata, readHostedDevice, readHostedDeviceLedger, readHostedMacosApp, readHostedNativeLogsCheckpoint, readHostedSessions, readIdleStop, readJsonFile, readJsonObject, readLastBuilds, readLogRecords, readLogTimeline, readLogsSince, readMacosRecord, readMaintenanceAttempt, readMaintenanceState, readNdjsonGenerations, readPullRequestCache, readRunEstimates, readSetupJournal, readStateFile, readStats, readStatsReport, readSwiftpmCacheUsage, readViewedDevices, readWarmRecord, readWorkspaceAgent, readWorkspaceState, recordMatches, recordedBytes, recordingDeviceName, recordingEnabled, rememberHostedAppBlobRename, requireAutomaticMachine, runId, saturation, serverSetupDir, settingDefinition, settingValueError, settingsJsonSchema, setupJournalFile, sharedCcache, sharedCompilationCache, sharedGradle, sharedPods, sortByTs, statsFile, statsProjectKey, stimBuildDigest, supervisorLogFile, supervisorPidFile, swiftpmCacheUsageFile, tailRead, trimCapacityRefusals, trimCapacityWaits, trimSamples, tryAcquireBuildSlotClaim, unreadableHostedAndroid, unreadableHostedIos, unreadableHostedNative, validEasSessionClaim, validHostedAppArguments, validHostedAppBlob, validRunId, validateAutomaticPool, wholePhases, withConfigLock, withDerivedFacts, withGitChip, withStateReadCache, workspaceAgentDeviceDir, workspaceBuildDetailFile, workspaceDerivedData, workspaceEndedAgentsFile, workspaceEndedAgentsLock, workspaceGradleBuild, workspaceLastUsed, workspaceLogErrorIndex, workspaceLogsDir, workspaceMetadataFile, workspaceRecordingsDir, workspaceStateFile, workspaceStateLock };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stim-cli/core",
3
- "version": "1.17.2",
3
+ "version": "1.19.0",
4
4
  "description": "Shared internal cache and runtime primitives for Stim packages.",
5
5
  "license": "MIT",
6
6
  "repository": {