Skip to content

Commit 034a99f

Browse files
committed
fix(ios): document daemon scoping of the usbmux route override
The env is re-read per resolve but from the daemon's environment, which is captured at daemon launch — a later CLI invocation cannot flip the route on a running daemon. Correct the source comment and experiment doc, and lock the read-point semantics with a regression test.
1 parent b7baccd commit 034a99f

3 files changed

Lines changed: 33 additions & 4 deletions

File tree

docs/usbmux-runner-transport-experiment.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33
Live results from 2026-07-30, thymikee-iphone (iPhone 17 Pro, iOS 26.5.2, UDID
44
00008150-001849640CF8401C), macOS host with Xcode 26.2. Method: forced-route
55
env override `AGENT_DEVICE_IOS_RUNNER_ROUTE=usbmux` in `runner-command-route.ts`
6-
(uncommitted experiment patch), isolated `--state-dir` daemons per leg, timings
7-
from per-request `--debug` ndjson plus wall-clock. Every timing sample was
6+
(committed with this doc), isolated `--state-dir` daemons per leg, timings
7+
from per-request `--debug` ndjson plus wall-clock. The override is
8+
**daemon-scoped**: the daemon captures its environment at launch, so setting
9+
the variable on a later CLI invocation against a running daemon silently
10+
keeps the previous route — every route leg needs a fresh isolated
11+
state-dir/daemon launched with the desired value. Every timing sample was
812
validated against real command output after an early instrument artifact (see
913
Pitfalls).
1014

@@ -77,5 +81,9 @@ xctestrun prep (~13 s cold) and runner startup; fresh device resolution costs
7781
error latency is indistinguishable from a fast success unless output is
7882
asserted. Runner-lease contention ("already owned by another daemon")
7983
produced exactly this artifact.
84+
- The route override is daemon-scoped (env captured at daemon launch). Never
85+
flip `AGENT_DEVICE_IOS_RUNNER_ROUTE` between commands against the same
86+
daemon and expect the route to change — start a fresh isolated
87+
state-dir/daemon per leg, then verify with `ps eww <daemon-pid>`.
8088
- Sessions are cwd-scoped; run every command of a leg from the same cwd.
8189
- Auto-Lock must be Never during measurement or the runner dies mid-series.

src/platforms/apple/core/__tests__/runner-transport.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,25 @@ test('sendRunnerCommandOnce routes coredevice physical devices through usbmux wh
242242
]);
243243
});
244244

245+
test('runner route override follows the daemon process env across resolves', async () => {
246+
// The override is daemon-scoped: resolves re-read the daemon's process env,
247+
// which is fixed at daemon launch. Clearing it here models a fresh daemon
248+
// launched without the variable — the only way the route can change.
249+
vi.stubEnv('AGENT_DEVICE_IOS_RUNNER_ROUTE', 'usbmux');
250+
stubSuccessfulFetch();
251+
mockRunCmd.mockImplementation(async () => ({ exitCode: 1, stdout: '', stderr: '' }));
252+
253+
await sendRunnerCommandOnce(iosDevice, 8100, { command: 'uptime' }, 5_000);
254+
assert.equal(mockUsbmuxPostCommand.mock.calls.length, 1);
255+
assert.equal(vi.mocked(fetch).mock.calls.length, 0);
256+
257+
vi.unstubAllEnvs();
258+
await sendRunnerCommandOnce(iosDevice, 8100, { command: 'uptime' }, 5_000);
259+
260+
assert.equal(mockUsbmuxPostCommand.mock.calls.length, 1);
261+
assert.equal(vi.mocked(fetch).mock.calls[0]?.[0], 'http://127.0.0.1:8100/command');
262+
});
263+
245264
test('waitForRunner routes coredevice physical devices through usbmux when overridden', async () => {
246265
vi.stubEnv('AGENT_DEVICE_IOS_RUNNER_ROUTE', 'usbmux');
247266
const fetchMock = vi.fn();

src/platforms/apple/core/runner/runner-command-route.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ const RUNNER_DEVICE_TUNNEL_IP_CACHE_TTL_MS = 30_000;
55

66
/**
77
* Experimental override for #1403: forces physical-device runner commands
8-
* through usbmux regardless of backend. Read per-resolve so daemon restarts
9-
* are not required between experiment runs.
8+
* through usbmux regardless of backend. Daemon-scoped: the value is re-read
9+
* on every resolve, but from the daemon's environment, which is captured at
10+
* daemon launch — a later CLI invocation cannot change it. Use a fresh
11+
* isolated state-dir/daemon per experiment route leg.
1012
*/
1113
const RUNNER_ROUTE_OVERRIDE_ENV = 'AGENT_DEVICE_IOS_RUNNER_ROUTE';
1214

0 commit comments

Comments
 (0)