stim 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/{android-CqcW1hrP.mjs → android-CT-PkXUh.mjs} +22 -19
- package/dist/{android-cas-BR5YJBYv.mjs → android-cas-DXorPCi_.mjs} +2 -2
- package/dist/{android-BqVIJoG7.mjs → android-hMj83VpN.mjs} +12 -6
- package/dist/{build-slots-C3-R4XQr.mjs → build-slots-C4AouyNz.mjs} +1 -1
- package/dist/cli.mjs +12 -12
- package/dist/{deps-Spz8ozgo.mjs → deps-0Yt0Inly.mjs} +1 -1
- package/dist/{dev-client-BjisHDB5.mjs → dev-client-VfSZNLT4.mjs} +4 -4
- package/dist/{device-BkiW-gkk.mjs → device-Bbv45Z9Z.mjs} +3 -3
- package/dist/{device-lease-BJYybF-2.mjs → device-lease-CJwK7OZr.mjs} +1 -1
- package/dist/{device-pool-CPbLGfrB.mjs → device-pool-CcBNTvM7.mjs} +1 -1
- package/dist/{device-remote-AkYCKS8U.mjs → device-remote-DAA0Zm6Z.mjs} +1 -1
- package/dist/{doctor-Bmv86UUW.mjs → doctor-B4EITgQB.mjs} +5 -5
- package/dist/{doctor-fAMXC4vl.mjs → doctor-BueDfLYG.mjs} +2 -2
- package/dist/{error-diagnostics-DHC31rXA.mjs → error-diagnostics-DwhNBFDU.mjs} +3 -3
- package/dist/{gc-GGu-8ULN.mjs → gc-BRu62v4o.mjs} +7 -7
- package/dist/{guide-92CPA21s.mjs → guide-D95E0u3i.mjs} +111 -61
- package/dist/{ios-BSXFeO5H.mjs → ios-DAju3TVy.mjs} +12 -12
- package/dist/{logs-DPNF4C9s.mjs → logs-CAdwW6c2.mjs} +29 -4
- package/dist/{logs-query-R-Cqc6Qv.mjs → logs-query-Cdp5aaCH.mjs} +1 -1
- package/dist/{ownership-BpCKiRlQ.mjs → ownership-DXcol4oU.mjs} +1 -1
- package/dist/{ownership-claim-Bf2CAfw3.mjs → ownership-claim-BtPtJVmq.mjs} +35 -21
- package/dist/{reclaim-iW9Cad7k.mjs → reclaim-CUmwucWG.mjs} +4 -4
- package/dist/{reload-DazHDSFA.mjs → reload-CWpXoOgN.mjs} +2 -2
- package/dist/{slot-launch-cci0xvmC.mjs → slot-launch-CZklomj6.mjs} +1 -1
- package/dist/{start-mObjQH2W.mjs → start-B5G4NjiA.mjs} +3 -3
- package/dist/{status-BxQNqu9t.mjs → status-CI9clRSb.mjs} +6 -6
- package/dist/{stop-CrHGcjrV.mjs → stop-CQhffpmX.mjs} +2 -2
- package/dist/{stop-DimGXEKY.mjs → stop-CjlgDk0a.mjs} +5 -5
- package/dist/{teardown-ClFp1Aax.mjs → teardown--gESs9ck.mjs} +103 -4
- package/dist/{workspace-process-lock-3NcQnZ0X.mjs → workspace-process-lock-IBj1Towr.mjs} +1 -1
- package/dist/{worktree-DxTgN1CJ.mjs → worktree-DtQGO9-s.mjs} +116 -106
- package/dist/{xcode-D7sAp-Zy.mjs → xcode-xnxyvJkD.mjs} +81 -44
- package/package.json +5 -5
|
@@ -62,6 +62,8 @@ warm checks for existing entries before copying, not during the copy. Do not
|
|
|
62
62
|
edit files, install dependencies, or run another warm in that worktree until
|
|
63
63
|
it finishes; concurrent files can be overwritten or removed.
|
|
64
64
|
If warm fails or reports incomplete, resolve the reported failure first.
|
|
65
|
+
A warm that cannot record its ownership claim refuses before copying. Follow
|
|
66
|
+
the printed remedy and keep concurrent runs on the same STIM_HOME.
|
|
65
67
|
|
|
66
68
|
Before native worktree work, run doctor for the platform in scope. It checks
|
|
67
69
|
the source checkout from a linked worktree. Fix relevant findings and inspect the
|
|
@@ -80,6 +82,12 @@ current and highest observed pressure; a timeout does not establish OOM.
|
|
|
80
82
|
Avoid repeated reboots under unchanged pressure; do not restart other
|
|
81
83
|
workspaces' devices or close their apps without asking. That guide covers
|
|
82
84
|
the recovery steps and profile tradeoffs.
|
|
85
|
+
An Android boot timeout under observed elevated memory pressure gets one
|
|
86
|
+
extra wait while the emulator process this run started is alive. It never
|
|
87
|
+
launches a second emulator. For a timeout, read guide errors STIM_NO_DEVICE
|
|
88
|
+
and free memory by stopping only unneeded devices in workspaces you own;
|
|
89
|
+
ask before closing other apps or devices. Device count alone is not evidence
|
|
90
|
+
of memory pressure.
|
|
83
91
|
For a linked native library carrying Git metadata, add the printed .git entries to
|
|
84
92
|
.fingerprintignore only when the native build does not read Git state.
|
|
85
93
|
|
|
@@ -180,8 +188,9 @@ RULES DURING THE LOOP
|
|
|
180
188
|
- A clean logs --errors check requires exit code 0 AND no matching errors in
|
|
181
189
|
captured logs. Exit code 0 alone means the query succeeded, even when errors
|
|
182
190
|
were printed. Human output shows "No matching log records" on stderr for
|
|
183
|
-
zero matches; JSON mode prints zero bytes.
|
|
184
|
-
|
|
191
|
+
zero matches; JSON mode prints zero bytes. A workspace with no captured
|
|
192
|
+
timeline refuses with STIM_NO_PROJECT and, in a monorepo, names the nearest
|
|
193
|
+
registered descendant app with logs. Do not read the NDJSON files directly.
|
|
185
194
|
- Use stim status when resuming a workspace or recovering missing device,
|
|
186
195
|
port, server, or build facts. A normal start and platform run already print
|
|
187
196
|
them. Use stim doctor when a build is unexpectedly slow or the environment
|
|
@@ -196,6 +205,8 @@ the stim-<label> (<model> <runtime>) name. Never point Stim at a user-created
|
|
|
196
205
|
emulator or simulator.
|
|
197
206
|
|
|
198
207
|
worktree remove parks the workspace's simulator or emulator for later adoption.
|
|
208
|
+
Before owned-device teardown, Stim best-effort closes local agent-device sessions
|
|
209
|
+
on that exact device; failures warn and teardown continues (guide cleanup).
|
|
199
210
|
A parked device is Stim-owned: never delete one by hand. gc --delete clears verified
|
|
200
211
|
entries and keeps failures; see guide lifecycle pool. First launch on a
|
|
201
212
|
physical iPhone can need the one-time taps named by the remedy.
|
|
@@ -898,10 +909,12 @@ discovered, not enumerated.
|
|
|
898
909
|
|
|
899
910
|
EXIT 0 MEANS THE QUERY SUCCEEDED, whether or not records matched. A clean
|
|
900
911
|
\`stim logs --errors\` check requires exit code 0 AND no matching errors in
|
|
901
|
-
captured logs.
|
|
902
|
-
|
|
912
|
+
captured logs. A workspace that has never produced a timeline refuses with
|
|
913
|
+
STIM_NO_PROJECT instead of passing with an empty result. In a monorepo the
|
|
914
|
+
refusal names the nearest registered descendant app with logs, when there is one.
|
|
903
915
|
|
|
904
|
-
|
|
916
|
+
Once a timeline file exists, zero matches after filtering means STDOUT IS EMPTY,
|
|
917
|
+
exit code 0, and
|
|
905
918
|
one dim note on STDERR reading \`No matching log records in <logs dir>\`
|
|
906
919
|
(human mode only -- \`--json\` prints nothing at all, on either stream).
|
|
907
920
|
The only exit-1 paths are a malformed query and no project.
|
|
@@ -1404,14 +1417,13 @@ code, never on the message.`,
|
|
|
1404
1417
|
\`worktree warm\` reports it for the repository-wide warm claim under
|
|
1405
1418
|
~/.stim/warm-locks on both paths, including a \`--refresh\` that spawned its
|
|
1406
1419
|
install and was killed before recording which process: nothing was refreshed
|
|
1407
|
-
and nothing was copied.
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
performed before them and \`--refresh\` still refuses.`
|
|
1420
|
+
and nothing was copied. A STIM_HOME or warm-locks ancestor that is a file
|
|
1421
|
+
also refuses. The message names that blocking path and prints a shell-quoted
|
|
1422
|
+
move-aside command. Inspect it first: the file may contain unrelated data.
|
|
1423
|
+
An existing backup prompts before overwriting; preserve both files.`
|
|
1412
1424
|
},
|
|
1413
1425
|
STIM_CLAIM_UNAVAILABLE: {
|
|
1414
|
-
summary: "
|
|
1426
|
+
summary: "a process identity or warm claim store is unavailable, so the protected operation refuses",
|
|
1415
1427
|
body: () => `STIM_CLAIM_UNAVAILABLE
|
|
1416
1428
|
Every ownership claim records the holder's process identity, captured through
|
|
1417
1429
|
the \`unique-pid\` native module. This code is that capture failing: no
|
|
@@ -1423,16 +1435,15 @@ code, never on the message.`,
|
|
|
1423
1435
|
the same fingerprint while each believed it was alone. Reinstall Stim so the
|
|
1424
1436
|
module for this platform is present, then run the command again. Nothing was
|
|
1425
1437
|
built, installed or removed.
|
|
1426
|
-
\`worktree warm
|
|
1427
|
-
the
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
warming is copied without a claim.`
|
|
1438
|
+
Both plain \`worktree warm\` and \`worktree warm --refresh\` refuse before
|
|
1439
|
+
copying for the same reason. A copy without a claim would be invisible to a
|
|
1440
|
+
refresh starting after it, allowing the source dependencies to change while
|
|
1441
|
+
they are read.
|
|
1442
|
+
Warm also reports this code for EACCES, EPERM, EROFS and ENOENT while taking a claim.
|
|
1443
|
+
The message names the claim path and original filesystem error. Restore write
|
|
1444
|
+
access to the existing claim store, checking parent permissions, symlink
|
|
1445
|
+
targets, mount access and sandbox rules, then retry. Do not switch STIM_HOME to evade a claim:
|
|
1446
|
+
concurrent runs must coordinate through the same store.`
|
|
1436
1447
|
},
|
|
1437
1448
|
STIM_INSTALL_FAILED: {
|
|
1438
1449
|
summary: "simctl, adb, or devicectl refused the artifact; the one signer-conflict retry",
|
|
@@ -1717,6 +1728,20 @@ so a Debug run on one is wired to a LAN origin instead of localhost.`,
|
|
|
1717
1728
|
normally live under ~/.android/avd, and a booted AVD can use several GB. A
|
|
1718
1729
|
boot whose emulator process exited is also reported at once rather than after
|
|
1719
1730
|
the full cold-boot timeout.
|
|
1731
|
+
Before a local Android emulator boot, a memory phase line reports observed
|
|
1732
|
+
warning or critical macOS host memory pressure. If the initial boot wait
|
|
1733
|
+
times out under that pressure and the process this run started is still
|
|
1734
|
+
alive, Stim retries the WAIT once for up to 240 seconds more on the same
|
|
1735
|
+
serial; it never starts a second emulator. New-device preparation normally
|
|
1736
|
+
waits 120 seconds first; the later boot check waits 240 seconds. There is
|
|
1737
|
+
no extra wait for normal or unavailable pressure, a process that exited,
|
|
1738
|
+
or a process whose liveness this run cannot check. adb probes are bounded;
|
|
1739
|
+
final diagnostic queries share a separate budget of up to five seconds.
|
|
1740
|
+
A timeout remedy reports observed pressure and the running owned-device
|
|
1741
|
+
count when available. Device count alone does not establish memory pressure
|
|
1742
|
+
or trigger the extra wait. Stop an unneeded device with \`stim stop\` only
|
|
1743
|
+
in a workspace you own, then retry \`stim android\`; ask before closing
|
|
1744
|
+
other apps or devices. Specific emulator log errors retain their remedies.
|
|
1720
1745
|
|
|
1721
1746
|
"this project's sim is X, but --device-type asked for Y"
|
|
1722
1747
|
The project already owns a simulator of a different model, and Stim will
|
|
@@ -1984,7 +2009,9 @@ captured" (in metro.ndjson, bare RN)
|
|
|
1984
2009
|
with no package.json above it, or one whose nearest package.json does not
|
|
1985
2010
|
parse or depends on neither react-native nor expo, so the directory is not
|
|
1986
2011
|
an app (the refusal names that package.json and says which of the two it
|
|
1987
|
-
is; \`doctor\` reports the same directory as a finding),
|
|
2012
|
+
is; \`doctor\` reports the same directory as a finding), a \`logs\` query in
|
|
2013
|
+
a workspace that has never produced a log timeline (the refusal names the
|
|
2014
|
+
nearest registered descendant app with logs when one exists), an
|
|
1988
2015
|
android/app/build.gradle that declares product flavors with
|
|
1989
2016
|
no variant selected (the refusal names the debug variants), or a
|
|
1990
2017
|
\`--device-type\`, \`--runtime\` or \`--system-image\` name that is BLANK or
|
|
@@ -2142,24 +2169,14 @@ not on any remote" (worktree remove)
|
|
|
2142
2169
|
which is usually the repository root, so every app of it reads the same one.`
|
|
2143
2170
|
},
|
|
2144
2171
|
warm: {
|
|
2145
|
-
summary: "
|
|
2146
|
-
body: () => `
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
"... the claim path is a file, not a claim directory", with a \`rm -rf\` that
|
|
2155
|
-
changes nothing (worktree warm --refresh)
|
|
2156
|
-
When \`$STIM_HOME/warm-locks\` or STIM_HOME itself is a regular FILE, the
|
|
2157
|
-
refusal names \`warm-locks/<name>.lock\` -- a path that cannot exist under a
|
|
2158
|
-
file -- so running the printed removal does nothing and the next run refuses
|
|
2159
|
-
identically. Remove the file that is in the way and run it again. A plain
|
|
2160
|
-
warm copies unsynchronised in this state.
|
|
2161
|
-
|
|
2162
|
-
Both are documented rather than fixed: appandflow/stim#696.`
|
|
2172
|
+
summary: "worktree warm claim storage refusals and recovery",
|
|
2173
|
+
body: () => `Both plain warm and --refresh require an ownership claim.
|
|
2174
|
+
Permission-denied or read-only claim storage reports STIM_CLAIM_UNAVAILABLE
|
|
2175
|
+
and names the path. Restore access to the existing claim store and retry.
|
|
2176
|
+
A non-directory claim ancestor reports STIM_CLAIM_REFUSED and names the
|
|
2177
|
+
blocking file. Inspect it and use the printed move-aside command to preserve
|
|
2178
|
+
its contents before retrying. See guide errors STIM_CLAIM_UNAVAILABLE and
|
|
2179
|
+
guide errors STIM_CLAIM_REFUSED for the recovery details.`
|
|
2163
2180
|
},
|
|
2164
2181
|
carry: {
|
|
2165
2182
|
summary: "worktree warm copy results, lockfile mismatches, and remedies",
|
|
@@ -2340,6 +2357,7 @@ a seed belongs to this workflow.
|
|
|
2340
2357
|
# For a clean check, require exit 0 AND no matching errors.
|
|
2341
2358
|
# Human mode prints "No matching log records" on stderr for zero matches.
|
|
2342
2359
|
# Exit 0 alone means the query succeeded, even when it printed errors.
|
|
2360
|
+
# A workspace with no captured timeline refuses with STIM_NO_PROJECT.
|
|
2343
2361
|
stim logs --errors
|
|
2344
2362
|
|
|
2345
2363
|
# 5. Edit the JS. Fast Refresh applies it; no Stim command is involved.
|
|
@@ -2435,6 +2453,12 @@ ANDROID EMULATOR RESTARTS
|
|
|
2435
2453
|
Rerun \`stim android\` with the same build options in that workspace to restore Metro
|
|
2436
2454
|
forwarding, then reopen agent-device on the serial that run reports.
|
|
2437
2455
|
Other workspaces' simulators and automation sessions remain theirs.
|
|
2456
|
+
A local emulator boot reports observed warning or critical macOS memory
|
|
2457
|
+
pressure before starting. A timeout under elevated pressure gets one
|
|
2458
|
+
additional wait of up to 240 seconds only while the process this run
|
|
2459
|
+
started is alive. Stim keeps waiting on the same emulator; it never
|
|
2460
|
+
launches a duplicate. See \`stim guide errors STIM_NO_DEVICE\` for the
|
|
2461
|
+
wait windows, diagnostics, and recovery steps.
|
|
2438
2462
|
|
|
2439
2463
|
DESTRUCTIVE COMMANDS -- ask the user first
|
|
2440
2464
|
gc --delete deletes orphaned stim-* devices, tens of GB
|
|
@@ -2707,9 +2731,11 @@ result as proof instead of requiring an unrelated screenshot.`
|
|
|
2707
2731
|
|
|
2708
2732
|
\`--refresh\` always prints a \`lock\` line, then its own facts, one per
|
|
2709
2733
|
step, before those. A plain warm prints the \`lock\` line only when its copy
|
|
2710
|
-
actually waited for another warm
|
|
2734
|
+
actually waited for another warm. A current refresh reports
|
|
2735
|
+
\`lock acquired shared (seed current)\`; a refresh needing changes
|
|
2736
|
+
reports \`acquired exclusive\` with the reason from its initial check:
|
|
2711
2737
|
|
|
2712
|
-
lock acquired (waited 12s for stim worktree warm --refresh pid 41233) -- stim guide lifecycle options
|
|
2738
|
+
lock acquired exclusive (fast-forward 2 commits) (waited 12s for stim worktree warm --refresh pid 41233) -- stim guide lifecycle options
|
|
2713
2739
|
checkout janic/wip 2 commits behind origin/janic/wip -> fast-forwarded to 4b81e0c
|
|
2714
2740
|
not the default branch (main); worktrees seeded from this copy
|
|
2715
2741
|
carry janic/wip's dependencies
|
|
@@ -3129,6 +3155,20 @@ WHAT MAKES THE CACHE ACTUALLY HIT: .FINGERPRINTIGNORE
|
|
|
3129
3155
|
Never ignore a real native input -- a Podfile, a gradle file, the app config
|
|
3130
3156
|
-- to force a hit: that trades a slow build for a wrong one.
|
|
3131
3157
|
|
|
3158
|
+
|
|
3159
|
+
React Native Test App can generate checkout-specific Android output under
|
|
3160
|
+
node_modules/react-native-test-app/android/support/build. If fingerprint
|
|
3161
|
+
differences point only there, add these project-specific entries:
|
|
3162
|
+
|
|
3163
|
+
node_modules/react-native-test-app/android/support/build
|
|
3164
|
+
node_modules/react-native-test-app/android/support/build/**/*
|
|
3165
|
+
|
|
3166
|
+
Put them in the app root's .fingerprintignore and use the path as it appears
|
|
3167
|
+
in the fingerprint sources; a hoisted or linked dependency may differ.
|
|
3168
|
+
Keep android/support/build.gradle and native sources included. Confirm equal
|
|
3169
|
+
fingerprints across built worktrees, and confirm a real native input edit
|
|
3170
|
+
still changes the hash. These exclusions are not Stim defaults.
|
|
3171
|
+
|
|
3132
3172
|
\`stim doctor\` measures this directly rather than reading the file: it
|
|
3133
3173
|
fingerprints HEAD in a temporary clean worktree, compares, and reports a
|
|
3134
3174
|
mismatch naming the differing sources. Untracked, non-gitignored files under
|
|
@@ -3274,8 +3314,9 @@ OPT-IN CONCURRENCY LIMITS (UNLIMITED BY DEFAULT)
|
|
|
3274
3314
|
Running it in the source checkout refuses.
|
|
3275
3315
|
|
|
3276
3316
|
\`--refresh\` WRITES TO THE SOURCE CHECKOUT before the copy, which is why it
|
|
3277
|
-
is opt-in: it
|
|
3278
|
-
its \`@{upstream}\`, and installs
|
|
3317
|
+
is opt-in: it checks the upstream, fetches changes when needed, and fast-forwards
|
|
3318
|
+
whatever branch is checked out there to its \`@{upstream}\`, and installs
|
|
3319
|
+
what the new commits moved. It refuses a
|
|
3279
3320
|
source checkout it cannot move -- uncommitted changes to tracked files or a
|
|
3280
3321
|
rebase or merge in progress (STIM_MAIN_DIRTY), a detached HEAD
|
|
3281
3322
|
(STIM_MAIN_DETACHED), or a branch that is both ahead and behind
|
|
@@ -3309,9 +3350,15 @@ OPT-IN CONCURRENCY LIMITS (UNLIMITED BY DEFAULT)
|
|
|
3309
3350
|
writes no failure anywhere -- is recovered the same way a failed one is.
|
|
3310
3351
|
|
|
3311
3352
|
One lock per repository serialises this, whether or not you pass the flag:
|
|
3312
|
-
\`--refresh\`
|
|
3313
|
-
|
|
3314
|
-
|
|
3353
|
+
\`--refresh\` first checks under a shared claim. It uses \`git ls-remote\`
|
|
3354
|
+
to compare the upstream's advertised commit with the local tracking ref without
|
|
3355
|
+
updating Git refs or FETCH_HEAD. When the checkout, dependencies and Pods are
|
|
3356
|
+
current, it keeps that shared claim through the copy, overlapping other copies.
|
|
3357
|
+
A changed or unconfirmed upstream, fast-forward, dependency install or Pods
|
|
3358
|
+
install requires an exclusive claim. It releases shared before waiting for
|
|
3359
|
+
exclusive, then checks the checkout again before fetching or writing. Every
|
|
3360
|
+
copy holds shared, so no copy reads a node_modules a refresh is rewriting.
|
|
3361
|
+
The lock is keyed on the repository root, so
|
|
3315
3362
|
two apps of one monorepo share it. It is the same ownership claim the build
|
|
3316
3363
|
locks take: the holder's process IDENTITY decides, so a holder that dies frees
|
|
3317
3364
|
it, a recycled pid cannot keep it, and a refresh whose install runs in a
|
|
@@ -3319,20 +3366,13 @@ OPT-IN CONCURRENCY LIMITS (UNLIMITED BY DEFAULT)
|
|
|
3319
3366
|
holder every 30s and gives up with STIM_LOCK_TIMEOUT; a claim Stim cannot
|
|
3320
3367
|
resolve refuses with STIM_CLAIM_REFUSED and names the removal rather than
|
|
3321
3368
|
waiting on it or removing it.
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
if a refresh holds this repository, or a claim in it cannot be resolved, the
|
|
3330
|
-
copy refuses rather than reading a tree that is being rewritten. That read is
|
|
3331
|
-
not a lock, so a refresh that starts after it is not covered; it closes the
|
|
3332
|
-
window in which one is already installing. Closing the rest needs a claim,
|
|
3333
|
-
which is the one thing that state cannot record, so the residual is
|
|
3334
|
-
documented rather than fixed (appandflow/stim#696), as is the
|
|
3335
|
-
\`acquired (waited 0s ...)\` a contended-but-fast wait prints.
|
|
3369
|
+
Both plain warm and --refresh refuse before copying when no claim can be
|
|
3370
|
+
recorded. Missing process identity, denied write access and read-only storage
|
|
3371
|
+
report STIM_CLAIM_UNAVAILABLE with recovery instructions. Restore access to the
|
|
3372
|
+
same claim store before retrying; choosing a different STIM_HOME would hide
|
|
3373
|
+
concurrent warm operations. A non-directory claim path reports
|
|
3374
|
+
STIM_CLAIM_REFUSED and names the blocking file with a move-aside command that
|
|
3375
|
+
preserves its contents. Sub-second waits omit the elapsed-time suffix.
|
|
3336
3376
|
|
|
3337
3377
|
Wait for warm to exit successfully (exit code 0) before running start,
|
|
3338
3378
|
ios, android, or a dependency install in that worktree. If a shell tool
|
|
@@ -3814,6 +3854,16 @@ Those are the only two commands that delete. \`stim stop\` shuts a device
|
|
|
3814
3854
|
DOWN and leaves it assigned, which is what makes returning to a branch cost a
|
|
3815
3855
|
boot rather than a create, a provision and a reinstall.
|
|
3816
3856
|
|
|
3857
|
+
Before shutting down, parking or deleting an owned device, Stim best-effort
|
|
3858
|
+
closes local agent-device sessions bound to its exact iOS UDID or live Android
|
|
3859
|
+
serial. It rechecks device ownership and uses agent-device's rejecting session
|
|
3860
|
+
target guard; sessions on other devices stay open. Physical devices are outside
|
|
3861
|
+
this cleanup. agent-device is optional: a missing binary skips this step, and a
|
|
3862
|
+
failed or timed-out list/close prints a device line on stderr while teardown
|
|
3863
|
+
continues. Cleanup allows at most 15 seconds of agent-device calls per device.
|
|
3864
|
+
A local daemon that cannot use socket transport or a CLI without the target guard
|
|
3865
|
+
skips cleanup with a warning; no remote daemon is used.
|
|
3866
|
+
|
|
3817
3867
|
Neither touches $STIM_HOME/stats.json: \`gc\` never reports or trims the run
|
|
3818
3868
|
counters \`stats\` prints, and there is no reset flag. Delete that one file to
|
|
3819
3869
|
start the counters over. A file this version cannot read -- unparseable, or
|
|
@@ -7,24 +7,24 @@ import { a as findProjectRoot, c as projectShortcut, i as detectIsExpo, r as det
|
|
|
7
7
|
import { i as resolveProjectMetro, r as pidExists } from "./metro-CORqXyTL.mjs";
|
|
8
8
|
import { n as verifyCollectorOwnership } from "./ownership-8O073GIC.mjs";
|
|
9
9
|
import { _ as launchErrorPreview, c as launchErrorReport, g as stepTimer, h as stepClock, i as formatDuration, l as phaseLine, m as shortUdid, n as appReadinessMessage, p as shortHash } from "./command-output-8wHMEde0.mjs";
|
|
10
|
-
import { r as claimFailure } from "./ownership-claim-
|
|
11
|
-
import { $ as providerDownloadPath, G as buildCacheKey, J as filesystemBuildCapability, K as describeFingerprintMiss, Q as prepareProviderDownloadDir, R as WAIT_CEILING_MS, U as takeoverLine, V as releaseBuildLock, W as waitForBuild, X as fingerprintDiffSuffix, Y as fingerprintDiffRecord, Z as fingerprintProject, at as untrackedMissLine, et as providerUploadOutcome, nt as resolveBuild, ot as untrackedNativeFiles, rt as storeBuild, tt as refingerprintAfterMutation, z as acquireBuildLock } from "./android-
|
|
10
|
+
import { r as claimFailure } from "./ownership-claim-BtPtJVmq.mjs";
|
|
11
|
+
import { $ as providerDownloadPath, G as buildCacheKey, J as filesystemBuildCapability, K as describeFingerprintMiss, Q as prepareProviderDownloadDir, R as WAIT_CEILING_MS, U as takeoverLine, V as releaseBuildLock, W as waitForBuild, X as fingerprintDiffSuffix, Y as fingerprintDiffRecord, Z as fingerprintProject, at as untrackedMissLine, et as providerUploadOutcome, nt as resolveBuild, ot as untrackedNativeFiles, rt as storeBuild, tt as refingerprintAfterMutation, z as acquireBuildLock } from "./android-hMj83VpN.mjs";
|
|
12
12
|
import { A as resolveSettings, B as artifactCachePolicy, D as remoteDeviceSettingError, F as tunnelModeSetting, H as optimizationBuildProfile, I as unknownSettingKeys, N as settingShapeErrors, O as remoteIosSetting, R as detectProviders, T as publicUrlSetting, U as resolveOptimizations, _ as iosSigningIdentitySha1SettingError, a as SETTING_SHAPE_REMEDY, d as cacheProviderSettingError, f as iosLanHostSetting, g as iosSigningIdentitySha1Setting, h as iosSigningIdentitySettingError, k as resolveCacheProviderConfig, m as iosSigningIdentitySetting, p as iosLanHostSettingError, r as REMOTE_DEVICE_BACKENDS, x as metroWarmupUrlSetting } from "./settings-DEJf6_kJ.mjs";
|
|
13
|
-
import { C as uploadRemote, S as resolveRemote, _ as isEasAuthFailureText, a as POOL_SETTING_REMEDY, c as parkedMaxSetting, d as RESOLVE_TIMEOUT_MS, f as UPLOAD_TIMEOUT_MS, g as exitAfterFlush, h as easAuthNote, m as checkEasAuth, p as cacheLevel, v as loadProjectProvider, x as resolveEasCliBin } from "./teardown
|
|
14
|
-
import { _ as easDeviceBuildRemedy, a as swapJsBundle, c as ensureWorkspaceStorageSafely, d as launchOutcomeRecord, f as noMetroMessage, g as warmMetro, h as sleep, l as gateShouldRetry, m as resolveMetroWithRetry, n as pickDevClientScheme, o as needsPrebuild, p as noMetroRemedy, r as schemesFromInfoPlist, s as runPrebuild, t as devClientScheme, u as isPhysicalDeviceRequest, v as isEasBuildFailure, y as resolveEasDevelopmentBuild } from "./dev-client-
|
|
15
|
-
import { t as withWorkspaceProcessLock } from "./workspace-process-lock-
|
|
13
|
+
import { C as uploadRemote, S as resolveRemote, _ as isEasAuthFailureText, a as POOL_SETTING_REMEDY, c as parkedMaxSetting, d as RESOLVE_TIMEOUT_MS, f as UPLOAD_TIMEOUT_MS, g as exitAfterFlush, h as easAuthNote, m as checkEasAuth, p as cacheLevel, v as loadProjectProvider, x as resolveEasCliBin } from "./teardown--gESs9ck.mjs";
|
|
14
|
+
import { _ as easDeviceBuildRemedy, a as swapJsBundle, c as ensureWorkspaceStorageSafely, d as launchOutcomeRecord, f as noMetroMessage, g as warmMetro, h as sleep, l as gateShouldRetry, m as resolveMetroWithRetry, n as pickDevClientScheme, o as needsPrebuild, p as noMetroRemedy, r as schemesFromInfoPlist, s as runPrebuild, t as devClientScheme, u as isPhysicalDeviceRequest, v as isEasBuildFailure, y as resolveEasDevelopmentBuild } from "./dev-client-VfSZNLT4.mjs";
|
|
15
|
+
import { t as withWorkspaceProcessLock } from "./workspace-process-lock-IBj1Towr.mjs";
|
|
16
16
|
import { C as launchIosApp, E as unverifiedLaunchLines, O as verifyLaunch, T as readMetroRecords, b as isBundleProof, c as RELEASE_VERIFY_WAIT_MS, f as clearOtherUserApps, i as LAUNCH_BUNDLING, k as verifyReleaseLaunch, m as devClientUrl, n as DEFAULT_METRO_PORT, o as LAUNCH_FATAL, s as LAUNCH_UNVERIFIED, v as installIosApp, w as readCollectorRecords, y as iosAppProcess } from "./app-install-DIp9riNx.mjs";
|
|
17
17
|
import { f as listIosRuntimes } from "./ios-Deh5js5V.mjs";
|
|
18
|
-
import { a as lostLine, c as releaseLeaseOnSignal, i as leaseExpiryText, l as runLease, n as DEBUG_VERIFY_STEP_MS, o as lostRefusal, r as acquireRunLease, s as parseDeviceWait, t as selectFromPool, u as waitFlagConflict } from "./device-pool-
|
|
19
|
-
import { r as releaseBuildSlot, t as acquireBuildSlot } from "./build-slots-
|
|
18
|
+
import { a as lostLine, c as releaseLeaseOnSignal, i as leaseExpiryText, l as runLease, n as DEBUG_VERIFY_STEP_MS, o as lostRefusal, r as acquireRunLease, s as parseDeviceWait, t as selectFromPool, u as waitFlagConflict } from "./device-pool-CcBNTvM7.mjs";
|
|
19
|
+
import { r as releaseBuildSlot, t as acquireBuildSlot } from "./build-slots-C4AouyNz.mjs";
|
|
20
20
|
import { a as statsProjectKey, i as recordRunStats, n as readRunEstimates, t as createRunRecorder } from "./stats-BR-kwj0B.mjs";
|
|
21
|
-
import {
|
|
22
|
-
import { a as ensureMetroReachable, b as ownedSessionName, c as remoteIosDeps, l as resolveRemoteContext, n as binOnPath, o as ensureRemoteBootOwned, r as bundleEntryPoint, w as gateMetroOrigin } from "./device-remote-
|
|
23
|
-
import { n as nativeRunCommand, t as launchSlotScope } from "./slot-launch-
|
|
21
|
+
import { E as unknownIosRuntimeRefusal, S as ensureOwnedDevice, T as unknownIosDeviceTypeRefusal, b as clearIosAdoptionPending, c as discoverXcodeProject, d as resolveScheme, i as buildIos, l as readBundleExecutable, m as describeDiagnostic, n as COMPILATION_CACHE_UNAVAILABLE, o as compilationCacheActivityLine, t as COMPILATION_CACHE_NOT_RUN, u as readBundleId, x as ensureBooted, y as checkDeviceCapacity } from "./xcode-xnxyvJkD.mjs";
|
|
22
|
+
import { a as ensureMetroReachable, b as ownedSessionName, c as remoteIosDeps, l as resolveRemoteContext, n as binOnPath, o as ensureRemoteBootOwned, r as bundleEntryPoint, w as gateMetroOrigin } from "./device-remote-DAA0Zm6Z.mjs";
|
|
23
|
+
import { n as nativeRunCommand, t as launchSlotScope } from "./slot-launch-CZklomj6.mjs";
|
|
24
24
|
import { t as spawnEntry } from "./spawn-entry-nCE6m770.mjs";
|
|
25
|
-
import { a as printNativeCrashReport, n as IOS_CRASH_REPORT_RETRY, o as simulatorConsolePaths, r as captureNativeCrashes, t as errorDiagnostics } from "./error-diagnostics-
|
|
25
|
+
import { a as printNativeCrashReport, n as IOS_CRASH_REPORT_RETRY, o as simulatorConsolePaths, r as captureNativeCrashes, t as errorDiagnostics } from "./error-diagnostics-DwhNBFDU.mjs";
|
|
26
26
|
import { a as iosDeviceProcess, c as listIosDevices, d as verifyIosDeviceReleaseLaunch, i as installIosDeviceApp, l as localNetworkPending, n as LAUNCH_PROBE_TIMEOUT_MS, o as iosPoolCandidates, r as awaitIosDeviceLaunch, s as iosPoolNoCandidatesRefusal, t as DEVICECTL_INSTALL_TIMEOUT_MS, u as resolveIosPhysicalDevice } from "./ios-device-CWOM_S44.mjs";
|
|
27
|
-
import { a as runPodInstall, n as podsAreStale, r as readPodState } from "./deps-
|
|
27
|
+
import { a as runPodInstall, n as podsAreStale, r as readPodState } from "./deps-0Yt0Inly.mjs";
|
|
28
28
|
import { existsSync, mkdirSync, mkdtempSync, openSync, rmSync, writeFileSync } from "node:fs";
|
|
29
29
|
import { InvalidArgumentError } from "commander";
|
|
30
30
|
import { X509Certificate } from "node:crypto";
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { V as validateDeviceSlot } from "./config-CcefMY2Q.mjs";
|
|
1
|
+
import { V as validateDeviceSlot, g as loadConfig, h as isPathPrefix } from "./config-CcefMY2Q.mjs";
|
|
2
2
|
import { n as SOURCES, t as LEVELS } from "./ndjson-BZwI1NBv.mjs";
|
|
3
3
|
import { D as workspaceLogsDir, p as readWorkspaceState } from "./state-B3XA2wp2.mjs";
|
|
4
4
|
import { a as findProjectRoot } from "./project-fKmuIaMI.mjs";
|
|
5
5
|
import { _ as launchErrorPreview } from "./command-output-8wHMEde0.mjs";
|
|
6
|
-
import { i as captureWorkspaceCrashes, t as errorDiagnostics } from "./error-diagnostics-
|
|
7
|
-
import { a as followLogs, i as fileSizes, n as buildCriteria, o as
|
|
6
|
+
import { i as captureWorkspaceCrashes, t as errorDiagnostics } from "./error-diagnostics-DwhNBFDU.mjs";
|
|
7
|
+
import { a as followLogs, c as queryLogs, i as fileSizes, n as buildCriteria, o as logFiles, r as compileGrep, s as parseSince } from "./logs-query-Cdp5aaCH.mjs";
|
|
8
|
+
import { realpathSync } from "node:fs";
|
|
9
|
+
import { relative, sep } from "node:path";
|
|
8
10
|
import chalk from "chalk";
|
|
9
11
|
//#region src/commands/logs.ts
|
|
10
12
|
const LEVEL_WIDTH = 5;
|
|
@@ -61,6 +63,28 @@ function validateLevel(level) {
|
|
|
61
63
|
return { error: `Invalid --level value ${JSON.stringify(level)}. Use one of: ${LEVELS.join(", ")}.` };
|
|
62
64
|
}
|
|
63
65
|
const ERRORS_PRINT_CAP = 20;
|
|
66
|
+
function nearestRegisteredLogsProject(root, candidates) {
|
|
67
|
+
return candidates.filter((candidate) => candidate !== root && isPathPrefix(root, candidate)).toSorted((a, b) => {
|
|
68
|
+
const depth = (path) => relative(root, path).split(sep).length;
|
|
69
|
+
return depth(a) - depth(b) || a.length - b.length || a.localeCompare(b);
|
|
70
|
+
})[0] ?? null;
|
|
71
|
+
}
|
|
72
|
+
function registeredDescendantWithLogs(root) {
|
|
73
|
+
const candidates = Object.keys(loadConfig()?.projects ?? {}).flatMap((path) => {
|
|
74
|
+
try {
|
|
75
|
+
const canonical = realpathSync(path);
|
|
76
|
+
return logFiles(workspaceLogsDir(canonical)).length > 0 ? [canonical] : [];
|
|
77
|
+
} catch {
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
return nearestRegisteredLogsProject(root, [...new Set(candidates)]);
|
|
82
|
+
}
|
|
83
|
+
function requireLogsWorkspace(root, dir) {
|
|
84
|
+
if (logFiles(dir).length > 0) return;
|
|
85
|
+
const descendant = registeredDescendantWithLogs(root);
|
|
86
|
+
fail(`STIM_NO_PROJECT: No Stim workspace has run in ${root}.${descendant ? ` The nearest registered app with logs is ${descendant}; run this command from there.` : " Run `stim start`, `stim ios`, or `stim android` in the app first."}`);
|
|
87
|
+
}
|
|
64
88
|
const LEVEL_COLOURS = {
|
|
65
89
|
debug: chalk.dim,
|
|
66
90
|
info: chalk.reset,
|
|
@@ -69,7 +93,7 @@ const LEVEL_COLOURS = {
|
|
|
69
93
|
fatal: chalk.bgRed
|
|
70
94
|
};
|
|
71
95
|
function logsCommand(program) {
|
|
72
|
-
program.command("logs").description("Query this workspace's merged NDJSON log timeline (bundler, client, device, build). Prints and exits; nothing matching is a successful, empty result. Use --follow to stream.").option("--slot <name>", "Only records attributed to this device slot", validateDeviceSlot).option("--source <s...>", "Only these sources: metro, client, device, build, or all").option("--level <l>", `Minimum level: ${LEVELS.join(", ")}`).option("--since <d>", "Only records newer than this, e.g. 30s, 5m, 2h").option("--grep <re>", "Only records whose message matches this regular expression").option("--tail <n>", "Only the last n matching records").option("--errors", "Errors and fatals since the last marker, from metro, client and build, plus confirmed native app-crash reports. Add --source device or --source all for general device errors.").option("--follow", "Keep streaming new records until interrupted").option("--json", "Emit the raw records, one per line (valid NDJSON; zero matches is zero bytes, exit 0)").action(async (opts) => {
|
|
96
|
+
program.command("logs").description("Query this workspace's merged NDJSON log timeline (bundler, client, device, build). Prints and exits; an existing timeline with nothing matching is a successful, empty result. Use --follow to stream.").option("--slot <name>", "Only records attributed to this device slot", validateDeviceSlot).option("--source <s...>", "Only these sources: metro, client, device, build, or all").option("--level <l>", `Minimum level: ${LEVELS.join(", ")}`).option("--since <d>", "Only records newer than this, e.g. 30s, 5m, 2h").option("--grep <re>", "Only records whose message matches this regular expression").option("--tail <n>", "Only the last n matching records").option("--errors", "Errors and fatals since the last marker, from metro, client and build, plus confirmed native app-crash reports. Add --source device or --source all for general device errors.").option("--follow", "Keep streaming new records until interrupted").option("--json", "Emit the raw records, one per line (valid NDJSON; zero matches is zero bytes, exit 0)").action(async (opts) => {
|
|
73
97
|
const root = findProjectRoot(process.cwd());
|
|
74
98
|
if (!root) {
|
|
75
99
|
console.error(chalk.red("Not in a React Native project (no package.json found)."));
|
|
@@ -102,6 +126,7 @@ function logsCommand(program) {
|
|
|
102
126
|
const compiled = compileGrep(opts.grep);
|
|
103
127
|
if (compiled.error) fail(compiled.error);
|
|
104
128
|
}
|
|
129
|
+
requireLogsWorkspace(root, dir);
|
|
105
130
|
const query = {
|
|
106
131
|
slot: opts.slot,
|
|
107
132
|
dir,
|
|
@@ -287,4 +287,4 @@ function sortByTs(records) {
|
|
|
287
287
|
});
|
|
288
288
|
}
|
|
289
289
|
//#endregion
|
|
290
|
-
export { followLogs as a,
|
|
290
|
+
export { followLogs as a, queryLogs as c, fileSizes as i, readLogRecords as l, buildCriteria as n, logFiles as o, compileGrep as r, parseSince as s, attachExpoErrorContext as t };
|
|
@@ -2,7 +2,7 @@ import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
|
2
2
|
import { E as inspectProcessIdentity, T as captureProcessToken, u as getConfigDir } from "./config-CcefMY2Q.mjs";
|
|
3
3
|
import { t as createLineReader } from "./process-output-C7IlIzd7.mjs";
|
|
4
4
|
import { r as pidExists } from "./metro-CORqXyTL.mjs";
|
|
5
|
-
import { t as withWorkspaceProcessLock } from "./workspace-process-lock-
|
|
5
|
+
import { t as withWorkspaceProcessLock } from "./workspace-process-lock-IBj1Towr.mjs";
|
|
6
6
|
import { closeSync, mkdirSync, openSync, readFileSync, unlinkSync } from "node:fs";
|
|
7
7
|
import { createHash, randomUUID } from "node:crypto";
|
|
8
8
|
import { basename, join, resolve, sep } from "node:path";
|
|
@@ -6,12 +6,6 @@ import { dirname, join } from "node:path";
|
|
|
6
6
|
//#region src/ownership-claim.ts
|
|
7
7
|
const CLAIM_REFUSED = "STIM_CLAIM_REFUSED";
|
|
8
8
|
const CLAIM_UNAVAILABLE = "STIM_CLAIM_UNAVAILABLE";
|
|
9
|
-
/**
|
|
10
|
-
* The refusal reason for a claim store whose own path is occupied by a file. It names a filesystem
|
|
11
|
-
* state that predates any claim, so a caller that only reads can tell it apart from an unresolvable
|
|
12
|
-
* claim record and fall back to what it did before claims existed.
|
|
13
|
-
*/
|
|
14
|
-
const CLAIM_PATH_NOT_A_DIRECTORY = "the claim path is a file, not a claim directory";
|
|
15
9
|
const EXCLUSIVE_DIR = "exclusive";
|
|
16
10
|
const SHARED_DIR = "shared";
|
|
17
11
|
const CLAIM_SUFFIX = ".claim";
|
|
@@ -23,9 +17,9 @@ var ClaimRefusedError = class extends Error {
|
|
|
23
17
|
claimPath;
|
|
24
18
|
reason;
|
|
25
19
|
removeCommand;
|
|
26
|
-
constructor({ claimPath, root, reason, label }) {
|
|
27
|
-
const removeCommand = claimRemoveCommand(claimPath.startsWith(root) ? claimPath : root);
|
|
28
|
-
super(`Stim cannot tell whether the ${label} claim at ${claimPath} is still held: ${reason}. It will not remove a claim it cannot prove is dead, and it will not wait on one either. If nothing is using it, remove the claim and run the command again:\n ${removeCommand}`);
|
|
20
|
+
constructor({ claimPath, root, reason, label, blockingFile = false }) {
|
|
21
|
+
const removeCommand = blockingFile ? `mv -i ${quotedPath(claimPath)} ${quotedPath(`${claimPath}.stim-backup`)}` : claimRemoveCommand(claimPath.startsWith(root) ? claimPath : root);
|
|
22
|
+
super(blockingFile ? `The ${label} claim store is blocked by a non-directory path at ${claimPath}. Inspect it before moving it aside; its contents may be unrelated to Stim. Preserve it with the command below (an existing backup prompts before overwriting), then run the command again:\n ${removeCommand}` : `Stim cannot tell whether the ${label} claim at ${claimPath} is still held: ${reason}. It will not remove a claim it cannot prove is dead, and it will not wait on one either. If nothing is using it, remove the claim and run the command again:\n ${removeCommand}`);
|
|
29
23
|
this.claimPath = claimPath;
|
|
30
24
|
this.reason = reason;
|
|
31
25
|
this.removeCommand = removeCommand;
|
|
@@ -34,9 +28,11 @@ var ClaimRefusedError = class extends Error {
|
|
|
34
28
|
var ClaimUnavailableError = class extends Error {
|
|
35
29
|
code = CLAIM_UNAVAILABLE;
|
|
36
30
|
reason;
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
remedy;
|
|
32
|
+
constructor(reason, { claimPath } = {}) {
|
|
33
|
+
super(claimPath ? `Stim could not write the ownership claim at ${claimPath}: ${reason}.` : `Stim could not record a process identity, so it cannot take an ownership claim: ${reason}.`);
|
|
39
34
|
this.reason = reason;
|
|
35
|
+
this.remedy = claimPath ? `Restore write access to the existing claim store at ${quotedPath(claimPath)} (check parent permissions, symlink targets, mount access and sandbox rules)` : "Reinstall Stim so the unique-pid native module for this platform is present";
|
|
40
36
|
}
|
|
41
37
|
};
|
|
42
38
|
/**
|
|
@@ -53,12 +49,7 @@ function isClaimRefusal(err) {
|
|
|
53
49
|
function isClaimUnavailable(err) {
|
|
54
50
|
return err?.code === CLAIM_UNAVAILABLE;
|
|
55
51
|
}
|
|
56
|
-
/**
|
|
57
|
-
* The refusal a command reports for either error the claim primitive raises, and null for anything else.
|
|
58
|
-
* Both are refusals: a claim Stim cannot resolve and a process identity it cannot record are the two
|
|
59
|
-
* states in which it holds no claim, and running the operation a claim serializes without one gives a
|
|
60
|
-
* competing run no protection at all.
|
|
61
|
-
*/
|
|
52
|
+
/** Convert an unresolved claim, unavailable identity or inaccessible warm claim store into command recovery guidance. */
|
|
62
53
|
function claimFailure(err, retryCommand) {
|
|
63
54
|
const retry = retryCommand === null ? "retry the same Stim command" : `run \`${retryCommand}\` again`;
|
|
64
55
|
if (isClaimRefusal(err)) return {
|
|
@@ -69,7 +60,7 @@ function claimFailure(err, retryCommand) {
|
|
|
69
60
|
if (isClaimUnavailable(err)) return {
|
|
70
61
|
code: CLAIM_UNAVAILABLE,
|
|
71
62
|
message: err.message,
|
|
72
|
-
remedy:
|
|
63
|
+
remedy: `${err.remedy}, then ${retry}.`
|
|
73
64
|
};
|
|
74
65
|
return null;
|
|
75
66
|
}
|
|
@@ -174,6 +165,29 @@ function refuse(root, claimPath, label, reason) {
|
|
|
174
165
|
reason
|
|
175
166
|
});
|
|
176
167
|
}
|
|
168
|
+
function refuseNonDirectory(root, path, label) {
|
|
169
|
+
let blocking = null;
|
|
170
|
+
for (let level = path;; level = dirname(level)) {
|
|
171
|
+
try {
|
|
172
|
+
if (!statSync(level).isDirectory()) {
|
|
173
|
+
blocking = level;
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
} catch (error) {
|
|
177
|
+
const code = error?.code;
|
|
178
|
+
if (code !== "ENOENT" && code !== "ENOTDIR") break;
|
|
179
|
+
}
|
|
180
|
+
if (dirname(level) === level) break;
|
|
181
|
+
}
|
|
182
|
+
if (blocking === null) throw new ClaimUnavailableError("the non-directory path could not be identified; the claim store may have changed", { claimPath: root });
|
|
183
|
+
throw new ClaimRefusedError({
|
|
184
|
+
root,
|
|
185
|
+
claimPath: blocking,
|
|
186
|
+
label,
|
|
187
|
+
reason: "the claim path is a file, not a claim directory",
|
|
188
|
+
blockingFile: true
|
|
189
|
+
});
|
|
190
|
+
}
|
|
177
191
|
function names(dir) {
|
|
178
192
|
try {
|
|
179
193
|
return readdirSync(dir).toSorted();
|
|
@@ -405,7 +419,7 @@ function publishExclusive(root, payload, claimId, label) {
|
|
|
405
419
|
});
|
|
406
420
|
const code = err?.code;
|
|
407
421
|
if (contended(err)) return null;
|
|
408
|
-
if (code === "ENOTDIR")
|
|
422
|
+
if (code === "ENOTDIR") refuseNonDirectory(root, target, label);
|
|
409
423
|
throw err;
|
|
410
424
|
}
|
|
411
425
|
}
|
|
@@ -439,7 +453,7 @@ function tryAcquireClaim({ root, mode, details = {}, label = "ownership" }) {
|
|
|
439
453
|
createClaimDir(root);
|
|
440
454
|
} catch (err) {
|
|
441
455
|
const code = err?.code;
|
|
442
|
-
if (code === "EEXIST" || code === "ENOTDIR")
|
|
456
|
+
if (code === "EEXIST" || code === "ENOTDIR") refuseNonDirectory(root, root, label);
|
|
443
457
|
if (contended(err)) continue;
|
|
444
458
|
throw err;
|
|
445
459
|
}
|
|
@@ -567,4 +581,4 @@ function writeChild(handle, body) {
|
|
|
567
581
|
}
|
|
568
582
|
}
|
|
569
583
|
//#endregion
|
|
570
|
-
export { clearClaimChild as a,
|
|
584
|
+
export { clearClaimChild as a, markClaimChildPending as c, releaseClaim as d, setClaimChild as f, claimRemoveCommand as i, processGroupAlive as l, tryAcquireClaim as m, ClaimUnavailableError as n, clearFreeClaimSet as o, settleClaim as p, claimFailure as r, isClaimRefusal as s, ClaimRefusedError as t, readClaimSet as u };
|
|
@@ -2,10 +2,10 @@ import { D as sameProcessRecord, O as waitForProcessExit, f as getProject, v as
|
|
|
2
2
|
import { T as workspaceDir, a as clearRemoteSession, c as readMetroTunnel, d as readRemoteSessionId, i as clearManagedMetroTunnel, p as readWorkspaceState } from "./state-B3XA2wp2.mjs";
|
|
3
3
|
import { i as resolveProjectMetro, n as killMetroTree, r as pidExists } from "./metro-CORqXyTL.mjs";
|
|
4
4
|
import { n as verifyCollectorOwnership } from "./ownership-8O073GIC.mjs";
|
|
5
|
-
import { c as parkedMaxSetting, n as teardownOwnedIosSim, t as teardownOwnedAvd, x as resolveEasCliBin } from "./teardown
|
|
6
|
-
import { l as releaseWorkspaceLeases } from "./device-lease-
|
|
7
|
-
import { i as endRecordedSession } from "./device-remote-
|
|
8
|
-
import { r as stopTunnel, t as resolveSupervisorTarget } from "./ownership-
|
|
5
|
+
import { c as parkedMaxSetting, n as teardownOwnedIosSim, t as teardownOwnedAvd, x as resolveEasCliBin } from "./teardown--gESs9ck.mjs";
|
|
6
|
+
import { l as releaseWorkspaceLeases } from "./device-lease-CJwK7OZr.mjs";
|
|
7
|
+
import { i as endRecordedSession } from "./device-remote-DAA0Zm6Z.mjs";
|
|
8
|
+
import { r as stopTunnel, t as resolveSupervisorTarget } from "./ownership-DXcol4oU.mjs";
|
|
9
9
|
import { existsSync, rmSync } from "node:fs";
|
|
10
10
|
//#region src/reclaim.ts
|
|
11
11
|
async function reapCollectors(root, { verify = verifyCollectorOwnership, collectors }) {
|
|
@@ -3,10 +3,10 @@ import { f as readWorkspaceLaunches } from "./state-B3XA2wp2.mjs";
|
|
|
3
3
|
import { a as findProjectRoot } from "./project-fKmuIaMI.mjs";
|
|
4
4
|
import { i as resolveProjectMetro } from "./metro-CORqXyTL.mjs";
|
|
5
5
|
import { l as phaseLine } from "./command-output-8wHMEde0.mjs";
|
|
6
|
-
import { N as resolveOwnedAvdSerial } from "./android-
|
|
6
|
+
import { N as resolveOwnedAvdSerial } from "./android-hMj83VpN.mjs";
|
|
7
7
|
import { u as androidAppProcess, y as iosAppProcess } from "./app-install-DIp9riNx.mjs";
|
|
8
8
|
import { x as resolveOwnedIosSim } from "./ios-Deh5js5V.mjs";
|
|
9
|
-
import { n as nativeRunCommand } from "./slot-launch-
|
|
9
|
+
import { n as nativeRunCommand } from "./slot-launch-CZklomj6.mjs";
|
|
10
10
|
import chalk from "chalk";
|
|
11
11
|
import { WebSocket } from "ws";
|
|
12
12
|
//#region src/engine/reload.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { f as getProject } from "./config-CcefMY2Q.mjs";
|
|
2
2
|
import { p as readWorkspaceState } from "./state-B3XA2wp2.mjs";
|
|
3
3
|
import { h as deviceShellArg } from "./app-install-DIp9riNx.mjs";
|
|
4
|
-
import { n as fileLeaseIo } from "./device-lease-
|
|
4
|
+
import { n as fileLeaseIo } from "./device-lease-CJwK7OZr.mjs";
|
|
5
5
|
//#region src/engine/slot-launch.ts
|
|
6
6
|
function launchSlotScope(root, slot = "default") {
|
|
7
7
|
if (slot !== "default") return slot;
|
|
@@ -9,10 +9,10 @@ import { g as stepTimer, l as phaseLine } from "./command-output-8wHMEde0.mjs";
|
|
|
9
9
|
import { A as resolveSettings, D as remoteDeviceSettingError, E as remoteAndroidSetting, F as tunnelModeSetting, I as unknownSettingKeys, L as PUBLIC_METRO_ENV, N as settingShapeErrors, O as remoteIosSetting, R as detectProviders, S as ngrokUrlSetting, T as publicUrlSetting, a as SETTING_SHAPE_REMEDY, b as metroTunnelSettingError, d as cacheProviderSettingError, k as resolveCacheProviderConfig, z as planMetroReach } from "./settings-DEJf6_kJ.mjs";
|
|
10
10
|
import { n as expoMetroConfigPath } from "./metro-store-CDDZHtPl.mjs";
|
|
11
11
|
import { o as expoSdkMajor } from "./server-expo-DizT4OMk.mjs";
|
|
12
|
-
import { n as workspaceProcessLockError, t as withWorkspaceProcessLock } from "./workspace-process-lock-
|
|
12
|
+
import { n as workspaceProcessLockError, t as withWorkspaceProcessLock } from "./workspace-process-lock-IBj1Towr.mjs";
|
|
13
13
|
import { t as spawnEntry } from "./spawn-entry-nCE6m770.mjs";
|
|
14
|
-
import {
|
|
15
|
-
import { a as withManagedRemoteWorktreeLock, i as terminateChild, n as startTunnelSequence, r as stopTunnel, s as withManagedTunnelLock, t as resolveSupervisorTarget } from "./ownership-
|
|
14
|
+
import { c as queryLogs } from "./logs-query-Cdp5aaCH.mjs";
|
|
15
|
+
import { a as withManagedRemoteWorktreeLock, i as terminateChild, n as startTunnelSequence, r as stopTunnel, s as withManagedTunnelLock, t as resolveSupervisorTarget } from "./ownership-DXcol4oU.mjs";
|
|
16
16
|
import { mkdirSync, openSync, readFileSync } from "node:fs";
|
|
17
17
|
import { randomUUID } from "node:crypto";
|
|
18
18
|
import { dirname } from "node:path";
|