Repository navigation
Conversation
The engine keeps each worker slot's device across the attempts that run on it: DeviceWorker holds upstream's surface fields (client, bound, recording). An attempt's dispose keeps a leased device booted under its session; the run's finish closes the kept sessions, then releases the leases, as upstream's finish does. A provider recording whose stop failed stays marked on the worker and is finished before the next attempt records. Ports the device provider recording its (21 of 22, one skipped), the two device provider its, the provider-example its (one Partial_), and the tool-pixels it, which runs through Runner.RunAsync with a fake device and a scripted model. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Contributor
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
Matches upstream's cloudDevices example and its two provider-example its:
- CloudDevicesOptions is { Provider, StateDir }, as upstream's
cloudDevices({ provider, stateDir }). Each run's leases keep their state in
<StateDir>/<runId>. The example no longer picks a device, OS version, or app,
and no longer requires CLOUD_TOKEN, which upstream's it does not check.
- The lease allocate call no longer sends ttlMs, as upstream's does not. The
lease heartbeat still sends its ttl.
- Selectors are optional on AgentDeviceLeaseRequest. A lease without them
allocates only the scope and the platform, and its client carries only the
scope, as upstream's client does. BrowserStack still names its selectors.
- IAgentDeviceLeases.ReleaseAsync takes the DeviceReleaseContext the provider
was handed, as upstream's release(lease, releaseContext) does.
- The two Partial_ provider-example tests are full ports under upstream's names
and assertions: "hands a retained cloud grant to the worker and releases the
allocated scope" and "releases a declined retention grant before rejecting
acquisition, without keeping it for release". The token check, which upstream
does not have, is removed with its test.
- "asks the provider for the resolved build..." is renamed to upstream's name
and ports upstream's body, including the explicit installApp and apps.install
assertions it was missing.
Also adds the PreparedEngines run tests and the public API pages for
IDisposableEngine and EngineDisposeContext, and updates the mobile docs for
the new example shape.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1531
Ports the mobile worker retention of tester-army/e2e #1209 (
ef977f4856) and the tool-pixels change of #1437 (94e6e76548).What changed
DeviceWorker(.NET-only) holds upstream's surface fieldsclient,bound, andrecording.DisposeAsyncends the attempt and keeps the device booted under its agent-device session (upstream'sendAttempt). A device without a lease closes with its attempt, as before.MobileEngine.FinishAsynccloses the kept sessions and releases the leases together, as upstream's pool finish does.device provider recordingits (one skipped), the twodevice providerits, the twoprovider-exampleits, andoffers pixel verbs after a secret fill.Upstream parity
Upstream change: tester-army/e2e
ef977f4856(#1209, mobile parts only:surface.ts,pool.ts,options.ts,bindings.ts,provider.test.ts,provider-example.test.ts, and the docs) and94e6e76548(#1437,tool-pixels.test.ts). Thepackages/e2escheduler, worker, and protocol parts of #1209 are out of scope for this port.Verdict: gaps remain. Three gaps are listed below. This PR is a draft until they are closed or accepted.
Counts (mobile parts):
Partial_Hands_a_retained_cloud_grant_to_the_worker_and_releases_the_allocated_scope).Partial and skipped tests:
Partial_Hands_a_retained_cloud_grant_to_the_worker_and_releases_the_allocated_scope: upstream's worker client holds only the lease scope. The port's client also holds the selectors and platform, because its worker resolves the device from them (seeAgentDeviceLeasesTests). The allocation, the scope, and the release are checked as upstream checks them.refuses a provider whose record is not a function(the C# type says it)..NET-only symbols and tests (each has a reason):
DeviceWorker,WorkerOf,DropWorker,TakeWorkers,DisposeWorkerAsync: the holder and the per-slot map. Upstream keeps these fields on one surface per worker.MobileEngine.DisposeAsync(timeout, reuse, ct): upstream'sdispose({ reuseSignal }). The publicIEngineSessionhas no reuse signal, so the engine reaches this through its internal overload.DeviceSession.EndAttemptAsync: upstream'sendAttempt. TheAsyncsuffix is the only name difference.Harness.BootattemptId, andMobileRun(Helpers/MobileRun.cs): test helpers that run in-memory tests throughRunner.RunAsync.Reuses_the_leased_worker_across_attempts_through_the_standalone_host(the run's worker lifecycle throughStandalone.OpenWorkerAsync),Stops_the_daemon_when_a_declined_retention_grant_names_the_cloud_in_its_message, andKeeps_the_agent_device_recording_for_a_provider_that_records_nothing_of_this_device.Errors and contract sentences from #1209:
AgentDeviceLeases.AcquireAsync; covered byAgentDeviceLeasesTestsandReleases_a_declined_retention_grant….DeviceProviderRecordingTests.Clears_a_confirmed_provider_stop_before_rejecting_its_invalid_artifact.Keeps_a_reusable_leased_session_when_the_provider_recording_still_cannot_stop_during_disposal.Repo rules checked:
CLAUDE.mdtest layout:ProviderExample/,ToolPixels/, andProvider/follow the upstream file names. ThePartial_prefix is used for the partial it.CLAUDE.mddocs:COMPATIBILITY.md,docs-site/.../get-started/mobile.mdx, andskills/e2e-dotnet/references/mobile.mdare updated. The API reference was not regenerated because no public XML documentation changed.CLAUDE.mdreal-model tests: see the testing section.CLAUDE.md/code-review: run; the valid findings are fixed (lock on the close, cancellation not absorbed by the settle wait, finish ordering as upstream).Gaps that remain (named plainly)
Runner.RunAsyncnever call a mobile engine'sPrepareAsyncorFinishAsync. Only the standalone host (e2e explore,e2e mcp, and the open session) prepares one. This predates this PR. Upstream's run prepares every target, so a real test run never reuses a leased worker. Closing it needs a process-level prepare and finish in the test fixtures.IEngineSession.DisposeAsynchas no reuse signal. Worker replacement is reachable only through the internal overload, and the port has no scheduler that replaces workers.packages/e2escheduler, worker protocol, and engine index parts of Upstream test: ids.test.ts its for test id join, result id bytes, and title validation #1209.Tests
dotnet build E2E.slnx: 0 warnings, 0 errors.E2E.Mobile.Tests: 487 passed, 60 failed of 547. The 60 are the same failures asorigin/main: CRLF and path separators (CapturedSnapshots,Installs_*,Asks_*), andLeaseDaemontimeouts. None of the new tests fail.E2E.Limrun.Tests: 21 passed, 1 skipped.E2E.TestMu.Mobile.Tests: 99 passed.E2E.Mobile.DevFlow.Tests: 94 passed.E2E.Expo.Tests: 46 passed.E2E.BrowserStack.Tests: 51 passed, 2 failed (Path.GetFullPathon a non-rooted base path on Windows, already onorigin/main).TestCategory=RealModel), run on the build before the last review fixes. The GitHub Copilot login succeeded through the GitHub CLI token. Passed:TodoMvc20,E2E.Agent.Tests28,WebBenchmark33,E2E.Sample1,E2E.XUnit.V3.Sample1,E2E.NUnit.Tests3. Not run:MobileApp.E2ETests(9 failed: the agent-device daemon could not start on this Windows host, before any device work) andWinAppBenchmark(62 failed: the app executable is not built in this worktree). Both are environment failures, and the mobile real-model tests need a simulator or emulator that this host does not have.🤖 Generated with Claude Code