Conversation
Size Report
Startup median (7 runs, lower is better):
|
|
|
Two ownership cases still need fixing at f0ae9d7. In device-claim-reboot.ts:35, the original claim timestamp remains the only cutoff even after its owner successfully reopens the app after reboot. The existing-session open path preserves that claim, so a later foreign open can reclaim a device that the original session is actively using and clean up its resources. Renew or validate ownership against the current boot when the owner resumes, and cover owner reopen followed by foreign open. In packages/platform-android/src/device-boot.ts:18, subtracting sampled uptime from the time the ADB response arrives moves the inferred boot forward by response latency. Shortly after boot, this can make a valid newer claim look stale without another reboot. Use a conservative bound from before the probe and cover a delayed response. The diff is also 1,442 gross lines, above the repository’s 1,000-line PR limit; split the behavior-preserving extraction from the takeover change. The current smoke failure is the automation-longpress scroll assertion seen on #2565 before its successful retry, so it appears unrelated to these changes. |
21db6ff to
0dd2527
Compare
|
Both ownership cases are fixed at The bound is now the instant the owner last vouched for the device, not the first write. Android now samples the host clock before the adb round trip, so The diff is split as stack #2576: #2574 is the behavior-preserving claim-settlement move (772 gross), #2575 is the boot-observation contract, probes, and hub (489 gross), and this PR is the takeover alone at 957 gross lines. |
|
The Android timing fix and PR split resolve those two points, but the owner-reopen bug remains at 0dd2527. renewHeldClaim only runs through acquireDeviceClaim; the existing-session open path in session-open.ts:162–243 still calls completeOpenCommand directly and never renews the claim. The new regression calls acquireDeviceClaim twice, so it does not exercise the reported production path. Wire renewal into a successful existing-session reopen and cover that routed flow followed by a foreign open, with live confirmation. Checks are green; this remains a code blocker. |
|
Renewal now rides the production reopen at
Routed coverage: Live on a fresh iPhone 17 Pro simulator, two state dirs and one device, Safari as the app:
Sessions closed, daemons stopped, state dirs removed, simulator deleted, |
|
The sequential owner-reopen case is now fixed and has the requested live evidence. One ownership race remains at session-open-execution.ts:245: openApplication runs before renewal, so a foreign daemon can take the still-preboot claim while the owner is reopening. renewDeviceClaim then returns ownership-changed or absent, but the result is ignored and the old owner still reports success. The request execution locks are local to each daemon, so they do not serialize this case. Establish ownership across reopen and renewal, handle lost ownership, and cover a foreign takeover interleaved with owner reopen. The layer is also back over the 1,000-line budget: 848 additions plus 211 deletions, or 1,059 gross lines. Reduce it by at least 59 lines or move the behavior-preserving extraction into the lower layer. CI is green at 2f8cbfe; these remain the blockers. |
2f8cbfe to
512736c
Compare
|
Ownership now spans the reopen at Renewal moved ahead of all device work: Coverage: Live, two state dirs on one simulator: owner |
|
The lost-owner refusal and size limit are resolved at 512736c. One boot-order case remains: session-open.ts renews the claim before prepareOpenCommandDetails, which can cold-boot a stopped simulator through prepareApplicationOpen → ensureAppleReady → ensureBootedSimulator. That successful reopen leaves updatedAtMs earlier than the device’s new boot, so a later foreign open still treats the active owner as stale and takes its claim. The reported live run boots the simulator before reopening, so it does not cover this path. Keep ownership protected while open boots the device and establish the claim for that boot; cover owner open on a stopped simulator followed by foreign open. CI is green and the layer is now under budget. |
512736c to
a9a4b8e
Compare
|
Boot order fixed at Covered by the routed test |
|
The post-preparation renewal at a9a4b8e fixes the cold-boot ordering, and the reported stopped-Simulator run covers the original failure. CI is green. The remaining validation gap is the regression at request-router-open.test.ts:953: it sets the boot time before reopening, so the old pre-preparation renewal satisfies its timestamp assertion; the foreign open also shares the owner’s session store and is refused before reboot-based claim settlement. Make preparation advance the boot time, exercise the foreign claim path from a separate store, and show that removing the post-preparation renewal makes the regression fail. No remaining production-code finding in this follow-up; readiness is waiting on that regression proof. |
a9a4b8e to
3d58ec2
Compare
|
Regression proof at Preparation does the booting: the fixture's platform-tools readiness seam is armed before the reopen, so the fake device's boot instant lands strictly between the pre-preparation renewal and the post-preparation one, and every later probe reports it. The foreign open now runs through its own session store and lease registry, so nothing refuses it before reboot-based settlement. Removing only the post-preparation renewal fails it twice over: |
…lidated An open that found a claim belonging to another session gave up even when the device had rebooted since that claim was taken, leaving the surface unreachable for every session. A reboot already took the app and the runner away, so the claim guarded nothing. Ask the device when its current boot began and release a foreign claim whose stamp predates it. The stamp is the last instant the owner vouched for the device, renewed by every open that reaches it, including the one that boots the device on the way in, so an owner that boots the device for its own work keeps it and only an owner that never came back loses it. Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
3d58ec2 to
6e243cb
Compare
|
Regression proof is in at The boot-during-preparation test arms the fixture's platform-tools readiness seam before the reopen, so the fake device's boot instant falls strictly between the pre- and post-preparation renewals and every later probe reports it; the foreign open runs through its own session store and lease registry, so nothing refuses it before reboot-based settlement. Deleting only the post-preparation renewal fails it twice: One honest delta: the layer is 1,065 gross lines, not 924. The extra 65 is the new test module's own harness, which the regression the review asked for needs. If you want it back under 1,000 I would rather delete the settlement-level duplicate |
|
The regression gap is resolved at 3d58ec2: preparation supplies the boot timestamp, the foreign open uses a separate store, and the reported red run reproduces takeover when post-preparation renewal is removed. No remaining correctness or device-evidence finding on that revision. At that revision, merge still needed the coverage gate fixed: request-router-open.test.ts grew to 1,009 lines and must be split along its owning module. The iOS smoke failure is likely unrelated: it repeats the automation-longpress scroll-visibility failure, while this follow-up changes only the regression test. A newer head, 6e243cb, arrived before this comment was published. This verdict applies only to 3d58ec2; the new head still needs review. |
Summary
opennow settles a foreign device claim that the device's own reboot invalidated. Claims outlive the device they describe: shutting a Simulator down takes its app process, runner, and accessibility connection with it, while the claiming daemon and claim file stay healthy. Every lateropenrefused withDEVICE_IN_USE, naming an owner with nothing left to close.openasks the device when its current boot began, releases a claim predating that through the same exact-owner reconciliationdevice release --staleuses, and reports the release inwarnings. The bound is the lastopenits owner made, renewed by every open that reaches the device, including one that boots it. The probe runs only for a conflicting foreign claim, after owner-liveness answers.Part 3 of 3 for #2538, on #2575 and #2574. 1,065 gross lines.
Closes #2538
Validation
Tested at
6e243cb754.pnpm check:affected --runpasses every lane, including related vitest (1,986 tests), exceptmutation-model, which fails identically at base locally where CI is green.The routed claim tests live in
request-router-open-claim.test.ts. Its boot-during-preparation regression arms the fixture's readiness seam, so the device boots between the two renewals and the foreign open asks from a second store; it fails when either renewal is removed. Live, two state dirs on one simulator: a foreignopenon a simulator its owner's preparation had booted was refused; a reboot with no owner reopen let a foreignopentake the device and say so. Experiment device cleaned.