Skip to content

Revert "[build-tools] Confine agent-device sessions to the session device" - #4540

Merged
szdziedzic merged 1 commit into
mainfrom
revert-4499-szdziedzic-claude/agent-device-daemon-policy
Oct 5, 2026
Merged

szdziedzic merged 1 commit into
mainfrom
revert-4499-szdziedzic-claude/agent-device-daemon-policy

Conversation

@szdziedzic

@szdziedzic szdziedzic commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Reverts #4499


Devin Review

@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown

✅ Thank you for adding the changelog entry!

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 5 potential issues.

Devin Review

Comment on lines 157 to 164
sessionHost = await startDeviceSessionHostAsync(ctx, {
runtimePlatform,
env,
logger: taskLogger,
timeoutMs: STARTUP_TIMEOUT_MS,
// The daemon policy names this device, so the preview must show the same one.
device: bootedDevice,
networkCapture: capture.networkCapture,
networkCaptureFields: capture.networkCaptureFields,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Preview can show the wrong simulator

When another simulator is already booted, startDeviceSessionHostAsync starts serve-sim without the session's UDID. Serve-sim can select that other simulator, so the preview shows a different device from the installed app.

Learn more

An agent-device session boots the requested iOS simulator and installs the app there. The session host starts serve-sim after boot, but the new call does not pass the booted simulator's UDID. createServeSimArgs no longer supplies a device argument, and the host no longer checks the ID returned by /readyz. With more than one booted simulator, serve-sim can select a different one, making the preview and app diverge.

Example: The host already has simulator A booted. The session boots B and installs an app on B, but serve-sim selects A. The preview shows A instead of the app on B.

Recommended fix: Preserve the UDID returned by bootIosSimulatorAsync in device.booted, pass it to startDeviceSessionHostAsync, and pass it to serve-sim. Check the ready device against that UDID before reporting the session ready.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +304 to +307
stopAsync: async () => {
await daemonProcess.stopAsync();
await fs.promises.rm(installDir, { recursive: true, force: true });
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Failed daemon shutdown leaves installation behind

If daemonProcess.stopAsync() rejects, stopAsync never removes installDir. Failed session teardown leaves the agent-device installation on disk.

Suggested change
stopAsync: async () => {
await daemonProcess.stopAsync();
await fs.promises.rm(installDir, { recursive: true, force: true });
},
stopAsync: async () => {
try {
await daemonProcess.stopAsync();
} finally {
await fs.promises.rm(installDir, { recursive: true, force: true });
}
},

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +148 to +150
if (!deviceIdentifier) {
throw new Error('Could not find an iPhone among available simulator devices.');
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Missing iPhone loses server error classification

When no iPhone is available, bootIosSimulatorAsync throws a plain Error instead of SystemError. The failed step loses its SERVER_ERROR classification.

Learn more

The simulator boot helper runs in both the standalone simulator step and agent-device sessions. A missing iPhone is an infrastructure failure, previously represented by SystemError with the SERVER_ERROR error code; a plain Error loses that classification in the build error payload.

Example: A macOS worker lists only iPads. The step fails with a generic error rather than a server error that identifies the device host as the problem.

Recommended fix: Restore the SystemError import and throw new SystemError(...) for this branch.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread CHANGELOG.md

### 🎉 New features

- [build-tools] Confine agent-device sessions to the session's device and deny booting and shutting down devices, using agent-device's daemon policy. ([#4499](https://github.com/expo/eas-cli/pull/4499) by [@szdziedzic](https://github.com/szdziedzic))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Revert is absent from the changelog

The removed feature entry has no replacement describing the revert. Repository guidance requires a changelog entry for every PR.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +297 to +301
const daemonProcess = spawnDetached({
command: 'node',
args: [daemonPath],
installDir,
launchMessage: `Launching daemon from ${daemonPath} after ${add.command} install.`,
env: { ...env, ...AGENT_DEVICE_DAEMON_ENV },
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟥 Remote sessions can control other devices

Every agent-device daemon starts without AGENT_DEVICE_DAEMON_POLICY. Remote clients can control devices outside their session and boot or shut down devices on the host.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

@szdziedzic
szdziedzic merged commit 738ccb1 into main Oct 5, 2026
8 of 10 checks passed
@szdziedzic
szdziedzic deleted the revert-4499-szdziedzic-claude/agent-device-daemon-policy branch October 5, 2026 17:03
@codecov

codecov Bot commented Oct 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.18519% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.71%. Comparing base (c487bcf) to head (f6c0b6e).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...c/steps/functions/startAgentDeviceRemoteSession.ts 82.36% 3 Missing ⚠️
...ild-tools/src/steps/functions/startIosSimulator.ts 66.67% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4540      +/-   ##
==========================================
- Coverage   73.75%   73.71%   -0.03%     
==========================================
  Files         998      998              
  Lines       48816    48778      -38     
  Branches    10558    10548      -10     
==========================================
- Hits        35997    35953      -44     
- Misses      11825    11831       +6     
  Partials      994      994              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

szdziedzic added a commit that referenced this pull request Oct 6, 2026
#4398 was based on #4499, which renamed device to readyDevice in
startDeviceSessionHostAsync. #4540 reverted #4499 before #4398 merged, so
main referred to a readyDevice name that no longer exists and the
build-tools typecheck failed. Use device instead.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants