Repository navigation
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Size Report
Startup median (7 runs, lower is better):
|
c2841b2 to
5445f27
Compare
|
At 5445f27 I found one likely defect in the cancel path and one missing live run. CI is green (17 checks, 0 not passing), and there are no conflicts. Before merge, I found this by reading the code, not by running it, so please confirm it. If a caller cancels a runner-served describe (a cancelled request, or a wait/batch step that aborts its capture), On Limrun, Not blocking, take or leave: the runner budget at runner-snapshot-bridge.ts:152 is computed before What I did not check: whether a timed-out or cancelled read-only runner exchange on the Limrun session triggers runner recovery above |
1a5ca97 to
f165d9c
Compare
5445f27 to
7e0f29c
Compare
|
Thanks. Both points are fixed at 1. 2. Live system-surface run on Limrun at this head. No repo app presents a web sign-in sheet, so I used a 60-line UIKit probe app with two buttons:
Each Limrun sheet capture sent 2 Also changed: Xcode 27 is not expected on Limrun. An Xcode 27 simulator build embeds no XCTest frameworks, so it cannot start on Limrun's iOS 26 simulators. The release workflow now selects Xcode 26, the package script refuses a runner without Non-blocking items: the observe-only comment is corrected; Gate: Still not checked: the native abandoned-read path, and whether a timed-out read-only runner exchange on Limrun triggers runner recovery above |
|
The code looks good at 7e0f29c. The earlier review issues are addressed, and the Limrun system-surface run you posted covers the occluded case: supplied signal and deadline aborts now become request cancellation without triggering ready-session recovery, while unrelated transport failures retain recovery. All 17 checks passed. There are no conflicts. Not blocking: The cancellation assertion can accept an unrelated error; you can take or leave an assertion against cancelled.signal.reason, or a named typed cancellation reason, in the cancellation test: https://github.com/callstack/agent-device/blob/7e0f29c/packages/platform-apple/src/runner-snapshot-bridge.test.ts#L324. |
f165d9c to
00d77a6
Compare
7e0f29c to
fd56bac
Compare
|
The code looks good at 3a4eb6d. The surface proof is now fenced to one runner session, the dead limrun-ios-tree producer is gone, and the refusal codes are guarded against drift. All 16 checks pass and there are no conflicts. The native sources have not changed since fd56bac, so the earlier Limrun and local sheet runs still cover them. Not blocking: You can take or leave extending the emitter guard to enumerate deadline-helper and native-build forwarding paths and classify their codes in the fixture, while keeping bridgeFailureDisposition as the runtime policy owner; the current guard recognizes only literal TypeScript snapshotSourceError calls. Guard |
|
The code at c56942e looks good: a tree that changes during a bridge read is now refused for that capture only. This new native path still needs a live run. CI reports 16 passing checks and no failures. There are no known conflicts. No recorded live run reaches the new refusal on either production channel, so device validation remains incomplete despite green CI (SnapshotBridgeRuntime.m:50). Please rebuild c56942e and record |
Split request validation out of the guest bridge server into SnapshotBridgeRequest.m and name the reader translation units once (SHARED_SNAPSHOT_BRIDGE_READER_FILENAMES). The guest bridge compiles them with its socket server; the runner fingerprint and its CI cache key now cover them, because the runner compiles the same reader. A host that serves the reader for other work can turn off the watchdog that ends the guest process (SNAPSHOT_BRIDGE_WATCHDOG_ENDS_PROCESS).
createSnapshotBridgeSource owns bounds, depth hints, acquisition, and the recovery record; a transport supplies only how one accepted envelope arrives. The local guest process is the first transport. acceptSnapshotBridgeEnvelope is the one acceptance rule for a bridge reply.
A provider iOS Simulator, such as Limrun, cannot run the guest bridge process: its simctl spawn is restricted and it forwards no socket. The runner now compiles the same reader and answers the snapshotBridge command off its journal and off the XCTest main thread. It abandons a read that outlives its budget instead of ending itself. The Apple runner runtime routes captures through the shared snapshot route with a runner channel, so a provider Simulator gets the local tree, recovery, depth cut, producer, generation circuit, and typed XCTest fallback. The runner names the app generation itself (target) and refuses another process (stale_target). The route refreshes a cached target before it trusts an open circuit, so a relaunch re-enables the bridge; a failed refresh keeps the cached generation. Only the runner's foreground read can prove that no system surface covers a provider Simulator, so that read starts a runner that is not up yet, and the host-side reads now go out together. Runner commands answered off the queue carry an explicit queued: false trait, so the bridge read is never charged as queued work.
Limrun simulators run iOS 26. An Xcode 27 simulator build embeds no XCTest frameworks and resolves them from the build machine, so it cannot start on a remote simulator. The release workflow now builds with Xcode 26, the package script refuses a runner without XCTest.framework, and the Limrun runner products check refuses such a runner before upload.
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…drift Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
The bridge reader re-reads a node whose children the first read withheld. When a scrolling list recycles its cells between the two reads, the re-read returns fewer children, and the runtime reported every such reader error as snapshot-tree-malformed. The route then retired the app generation, so one scroll moved every later capture of the app to XCTest (seen on Bluesky's feed). The reader errors are now a typed enum, and the runtime maps each one to its refusal: a changed tree is snapshot-tree-changed with capture scope, and a foreground change during a continuation is foreground-owner-changed. Co-Authored-By: Claude <noreply@anthropic.com>
c56942e to
bacf32e
Compare
00d77a6 to
24be243
Compare
|
Live evidence for the Local Simulator
Commands (worktree CLI at AD="env AGENT_DEVICE_IOS_RUNNER_DERIVED_PATH=/private/tmp/ad-4182-local2/derived node bin/agent-device.mjs --state-dir /private/tmp/ad-4182-local2/state --session ax4182b --platform ios --udid 1B89356B-961C-4993-B0BE-4C0F3917D995"
$AD open com.callstack.agentdevicelab --relaunch
$AD open com.callstack.agentdevicelab 'agent-device-test-app://heavy-feed'
# repeated until the refusal appeared (iteration 2):
$AD swipe 210 300 210 880
$AD snapshot -i --json --debug
# then, after the scroll came to rest:
$AD snapshot -i --json --debug
1–2. Refusal, then XCTest serves that capture (request 3. Next capture: The refusal had capture scope: the generation was not retired ( Limrun: blockedThis host has only Xcode 27.1 and iOS 27 runtimes; no Xcode 26 is installed. So I cannot build the release-shaped Limrun runner from this head, and the release runner (v0.21.36) does not contain this PR's native change. As a fallback (at AGENT_DEVICE_SESSION=ax4182-limrun AGENT_DEVICE_LIMRUN_IOS_RUNNER_APP=<that .app> \
node bin/agent-device.mjs --state-dir /private/tmp/ad-4182-limrun/state connect limrun --platform ios
… install com.callstack.agentdevicelab ./AgentDeviceTester.app # Installed
… open com.callstack.agentdevicelab # Opened
… snapshot -i --json --debugThe runner never accepted a connection on the Limrun iOS 26 simulator: This matches the Xcode 27 limit that the PR documents. That runner shape is not the shipped one, so this run says nothing about the PR code on Limrun. The Limrun instance I started (lease To finish the Limrun run, one of these is needed: an Xcode 26.x install on this host ( 🤖 Generated with Claude Code |
|
At bacf32e, local live evidence now covers guest-process transport, but the Limrun run could not start the Xcode 27-built runner on its iOS 26 simulator. Could you run this head with an Xcode 26 runner on Limrun and capture CI reports 18 passing checks and no non-passing checks at head. No conflicts are known. Please post the head-specific Limrun evidence before merge. |
Summary
Limrun iOS snapshots now read the same Simulator AX bridge as a local Simulator. Limrun cannot start the guest bridge process: its
simctl spawnaccepts onlydefaults|notifyutil|limproxy, and it forwards no socket. The XCTest runner therefore compiles the sharedapple/snapshot-bridgereader and serves thesnapshotBridgecommand off its journal and XCTest main thread. The shared snapshot route keeps the generation circuit, the system-surface proof, and the one typed XCTest fallback. A slow read is abandoned, not fatal to the runner. ADR 0004 is amended.The runner admits one bridge read at a time. Its
bridge-read-in-flightrefusal is capture-scoped: a read that a cancelled capture left running costs only the next capture its bridge read, never the app generation. The daemon keeps no read queue of its own.The Limrun runner must be built with Xcode 26. Limrun simulators run iOS 26, and an Xcode 27 simulator build embeds no XCTest frameworks, so it cannot start there. The release workflow selects Xcode 26, the package script refuses a runner without
XCTest.framework, and the Limrun runner products check refuses one before upload.Review follow-ups in this PR: the provider surface proof reads only the runner session it started; the dead
limrun-ios-treeproducer is removed;contracts/fixtures/ios-snapshot-bridge-refusals.jsonclassifies every bridge refusal code, and a repo guard fails when an Objective-C, Swift or TypeScript emitter writes a code the fixture does not classify; ADR 0004 records that observe-only captures bypass the route. A bridge read whose continuation finds fewer children than the first read counted (a list scrolling between the reads) is nowsnapshot-tree-changedwith capture scope; before, it wassnapshot-tree-malformedand moved every later capture of the app to XCTest (found on Bluesky's feed). The reader's errors are a typed enum, and a foreground change during a continuation isforeground-owner-changed.On every Simulator, the system-surface foreground reads (one
appStateper registered host) now go out together instead of one after another.9 commits. Stacked on
stack/limrun-native-runner: the 3 layers of muvaf's Limrun work that are not onmainyet (#4174, #4194 and #4195 merged the others), rebased onto currentmain. The Limrun switch layer ("replace iOS AX automation with the shared XCTest runner") also restores the runner exports that the merged #4174 moved out of layer 1 (createLaunchedAppleRunnerProvider,RUNNER_STARTUP_TIMEOUT_MS,mintRunnerToken,runnerListenerEnv,RUNNER_XCTESTRUN_CAPTURE_OPTIONS). Retarget tomainonce those layers land. Overlaps #4172 (same bridge/route files).Validation
Head
bacf32eeb3, base24be24328d(onmain035c2b6cae).FALLOW_AUDIT_BASE=24be24328d pnpm check:affected --run --head bacf32eeb3: passed, exactCommit=true, receiptrun-A35qVo.children-shrink-during-continuationcase.--actionsXCTest read). Warm p50 0.69 s on Limrun, 0.20 s local. Forced XCTest on the same feed: 4.4–5.2 s with a depth-56 cut; the bridge tree has no cut.circuit-disabledanywhere; onesnapshot-tree-changed(local) cost exactly one capture, and the next was bridge-served.--timeoutcaptures and 2 killed CLIs per target; all 14 following captures bridge-served, no runner restart.Known issues on
main, not in this PR (found during the Bluesky run):lease-registry-scope.ts).LIMRUN_KEEP_ALIVEpings only the instance. A call every 45 s keeps the session.No element snapshot found for Application …→point.x != INFINITY):fillinto the composer on Limrun, and once atapon the compose button locally. The runner restarts and the next capture is bridge-served.Not reached live: the native abandoned-read path and a live
bridge-read-in-flightrefusal (a Limrun bridge read takes ~150 ms, shorter than any cancel-to-next-capture gap); unit tests cover both.