Skip to content

refactor(apple-runner): own close retention behind one runner operation #2615

Description

@thymikee

refactor(apple-runner): own close retention behind one runner operation

Purpose and evidence

PR #2605 (44f78a986d51aeb0aab3e031700a96c2302e299b) fixes reuse of a busy runner. Application lifecycle now combines stopRunnerSessionIfBusy, scheduleRunnerIdleStop and stopRunnerSession, although the runner owns occupancy and disposal state. Adding the busy primitive also changes shared contracts, forwarding modules and four replay fixtures.

Evidence: application close orchestration, runner state owner, host contract.

Required behavior

Expose one awaited close-finalization operation through the existing runner host seam, conceptually finalizeRunnerClose(deviceId, { retainForReuse: boolean }): Promise<void>.

The application lifecycle supplies reuse intent; runner-session.ts chooses using its own occupancy state. Preserve this truth table:

Caller intent / state Required result
Retain + busy runner Await disposal and lease release; never schedule reuse
Retain + idle runner Schedule the existing idle stop; retain healthy warm reuse
Do not retain Await the existing unconditional stop
Retain + no in-memory runner Preserve existing idle-stop scheduling/cancellation behavior; do not create a runner
Do not retain + no in-memory runner Still await the existing stop path, including idle-timer cancellation and owned-lease cleanup
Daemon shutdown Preserve the separate shutdown/alert-cleanup path; do not introduce the ordinary close-finalization call

Preserve alert-dismissal order, request behavior, error propagation, idle-stop timing and all occupancy update semantics from #2605. Keep lifecycle's shutdown decision outside this operation. Do not return early merely because the session map has no runner: unconditional stop also owns durable lease cleanup under its existing locks.

Scope and exclusions

Runner session implementation, Apple lifecycle, current client/facade/host bindings, AppleApplicationTools, root composition and directly affected fixtures/tests. Retire the new busy-only public plumbing once unused. Keep unconditional stop wherever other callers still need it. Preserve ADR 0005 and ADR 0019's injected host and lazy loader; no direct lifecycle import of runner implementation, new hook bag, Swift protocol change or recovery-policy redesign. #2524 and #2475 own different recovery/readiness behavior.

Completion and validation

  • Characterize the truth table and call ordering on the fix(ios-runner): dispose a busy runner on close so open boots clean (#2552) #2605 result before changing the API, including owned-lease cleanup without an in-memory session, disposal rejection before alert dismissal, and a close/open sequence that cannot reuse a busy runner. Exercise an idle-retain decision with a queued occupancy/drain transition around the existing awaited busy check; preserve observable ordering without pinning arbitrary microtask counts or introducing broader locking/concurrency policy.
  • Drive tests through the real lifecycle-to-runner boundary where practical; retain independent runner tests for occupancy stamps, transport failures and disposal. Do not reduce proof to a mocked method being called.
  • The lifecycle supplies intent through one operation instead of orchestrating runner state checks. The busy-only operation and unused forwarding exports are removed; other consumers retain genuinely required primitives.
  • Demonstrate a temporary additional runner-local reuse condition needs no extra contract method, forwarding adapter or replay fixture edit. Remove it before publication.
  • pnpm check:affected --run passes; preserve existing eager-closure constraints and follow docs/agents/device-verification.md for a live close/open check on a verified Apple target. Report native/CI obligations separately; a nondeterministic live wedge is not required proof of this behavior-preserving API refactor.

Dependencies and readiness

Blocked by: #2605 landing. Re-audit the merged result and all primitive consumers first. Do not implement against pre-#2605 main. Stop if the proposed seam cannot preserve shutdown or lease ordering without moving application policy into the runner. This is a follow-up, not a blocker for #2605.

Effort: M. Risk: medium (shutdown, lease disposal, warm reuse). No existing issue found for this ownership change.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions