refactor(apple-runner): encapsulate XCTest-channel penalty state
Les mainteneurs répondent en général sous 1 jour
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Accessibilité débutants
- 35/100
- Type d'issue
- Refactorisation
- Clarté
- Plutôt claire
- Activité
- Active
- Stack technique
- swift
- Domaine
- mobile-dev, testing-qa
Piste de recherche
First read the deletion gate and inspect RunnerTests+SnapshotCapturePlan.swift:133–162, RunnerTests.swift:118–122, and SnapshotTiming.swift:119–154 under apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/. Confirm a concrete deletion or correctness case before starting, since the issue is currently deferred. If resumed, use the owner-matched tests and consuming suites named in the issue; done means penalty behavior and effective-plan outputs remain unchanged and the required focused checks pass.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Encapsulate the runner's XCTest-channel penalty state with its existing operations
Deletion-first acceptance
This is part of #2803's simplify-and-shrink initiative. Before production simplification, name the production mechanism, duplicated decision, state, fallback, forwarding layer, or public/internal interface this change removes. Compare deletion and inlining against extraction. Moving the same state into another file is not a deletion case.
Every PR reports baseline/final SHAs; added, deleted and net production lines; test/fixture/documentation changes separately; and the exact mechanisms removed. Use a rename-aware diff (git diff --numstat -M BASE...HEAD) and account for all affected production paths, including destination packages. Moving tests out of production files, generated output, formatting churn, and moving code elsewhere are not production-code deletion. Preserve readable code; no compressed formatting to hit a number.
Default for simplification work: net production reduction. A required behavior-preserving size split may be line-neutral. Growth needs an explicit, quantified explanation of the correctness or type guarantee it buys, why deletion/inlining cannot achieve it, and what old mechanism is removed; it is not automatically acceptable because ownership looks cleaner. If the only benefit is relocating fields or adding a wrapper, defer the change. Required regression tests and a minimal correctness fix are allowed to grow without inventing unrelated deletion to offset them.
Priority and scope gate
Readiness: deferred; remove ready-for-agent. Existing operations are already collocated and no penalty-state defect has been demonstrated. Resume only for a named deletion of duplicate state/coordination or a concrete correctness need. A new class with the same fields plus forwarding methods does not meet this initiative's goal. Preserve the distinct penalty, warmup and depth lifetimes. Run shared Swift work one issue at a time.
Parent: #2803. Readiness: deferred pending a concrete deletion or correctness case. Evidence baseline: 5712a3552e209c9c853bc1f42cb3e007f1213139; recheck current main. If resumed after its deletion/correctness gate, coordinate edits with target-transition characterization and ownership work; the current penalty operations are already explicit. #2911 has merged and #2882 owns additional actor source guards.
Problem and evidence
RunnerTests+SnapshotCapturePlan.swift:133–162 already colocates arm, clear and lookup functions. The missing piece is concrete ownership: their lock, bundle identity, deadline and duration remain writable on the entire XCTest case (RunnerTests.swift:118–122). This extraction should close that seam, not claim to discover a missing state machine or rewrite capture-plan policy.
The current penalty is a single retained record, not a per-app map. SnapshotTiming.swift:119–154 decides whether an XCTest-backed attempt deserves it from acquisition timing, typed timeout and deadline exhaustion. Main-thread abandonment can also arm it. Lifecycle explicitly clears it for process replacement/external relaunch; ordinary invalidation does not mean the same thing.
Small interface and ownership
Create one concrete SnapshotXCTestChannelPenalty module owning its private lock, optional bundle and expiration. Expose arm, clear and isActive(for:). Preserve the 120-second duration, existing log markers, and strict now < expiresAt lookup. Accept the current instant as an explicit operation input, or reuse an existing production clock seam, so expiry tests advance time without production-length sleeps. Do not add test-only setters or a scheduler framework.
Place the instance on RunnerTests, replace direct accesses, and delete superseded fields/functions. The existing acquisition classifier, capture-plan reordering and presentation-quality decisions retain their owners. The new module must not know backend capabilities, app activation or snapshot node shapes.
Keep SnapshotXCTestPenaltyWarmupExemption separate: it already has lock-protected ownership and a different contract (one pending exemption consumed by an actual plan). Keep private-AX accepted-depth memory separate: its positive-PID matching and non-renewing successful reuse are not this penalty's semantics. Shared duration values today do not justify a combined cache or lifetime abstraction.
Required preservation and completion checks
- Arming replaces the single previous penalty; it does not accumulate one entry per app. A nil-bundle penalty applies to any requested bundle; a named penalty only matches that bundle.
- Re-arming retains current deadline renewal behavior. Expiry itself need not mutate storage. Clearing emits its existing marker only when the old penalty was still active.
- An independently recovered capture must still avoid occupied XCTest work; physical-device plans retain bounded XCTest probes while eligible simulator plans can defer to independent acquisition.
- Slow presentation alone never arms the penalty; acquisition timeout or an exhausted XCTest tier can arm it without crossing the slow-duration threshold. Preserve warmup suppression at its current decision point.
- Before: lock/state exposed across all runner extensions. After: only the owner accesses penalty state, with exactly the same effective-plan and quality outputs for the same observations.
Validation and exclusions
Move penalty-specific cases into the owner-matched test file; retain the consuming assertions in SnapshotCapturePlanTests, SnapshotTimingTests, LifecycleCacheTests, SnapshotCaptureTargetTests and SnapshotCapturePlanOccupancyTests. Cover nil/named bundle, replacement, exact expiry, clear, renewal and concurrent arm/read through the public interface. Plant a nil-bundle mismatch and a presentation-only penalty mutation to prove the nearest negative cases fail.
Run pnpm check:xctest-selection, unit-enabled iOS/macOS builds and selected XCTest cases, pnpm check:packaged-runner-swift, and pnpm check:affected --run. Preserve source-guard lane ownership. No claim of hostile-screen recovery improvement follows from extraction alone; report live evidence separately. No new retry strategy, clock-domain migration, penalty duration change, actor rewrite or host-side bridge-cache change belongs here.
Source paths in this issue are rooted at apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/; extension names abbreviate the RunnerTests+ prefix where stated. Tests live in its UnitTests/ directory. For a fresh worktree, run pnpm install --frozen-lockfile && pnpm build before the focused checks. Read docs/agents/testing.md and docs/agents/device-verification.md for native lane selection and build freshness.
- Langage dominant
- TypeScript
- Étoiles
- 4.7k
- Forks
- 304
- Merge moyen
- 11 h 31 min
- PR mergées (30 j)
- 513
Préparer son environnement
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de callstack/agent-device
-
Difficulté 2/5 1-3 heures Accessibilité débutants 88/100
callstack/agent-device#2998 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 84/100
callstack/agent-device#2995 ·
Les mainteneurs répondent en général sous 1 jour
-
Proxy lease refuses every iOS install/open: connection platform 'ios' compared with internal 'apple'Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
callstack/agent-device#2962 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 68/100
callstack/agent-device#1869 ·
Les mainteneurs répondent en général sous 1 jour
-
Maestro `eraseText` fails on real Android devices: `test` and `replay` cannot opt in to the test IMEOuverte
Difficulté 3/5 1-2 jours Accessibilité débutants 74/100
callstack/agent-device#2997 ·
Les mainteneurs répondent en général sous 1 jour
Toutes les issues de callstack/agent-device
Issues similaires
-
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
rohitg00/agentmemory#1428 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 86/100
boxlite-ai/boxlite#1729 ·
Les mainteneurs répondent en général sous 1 jour
-
Detect Deno tasks from deno.jsonOuvertedetectors enhancement good first issue
Difficulté 2/5 1-3 heures Accessibilité débutants 86/100
SM260845/readme-gen#1 ·
-
Difficulté 2/5 1-3 heures Accessibilité débutants 88/100
angular/angularfire#3774 ·
Les mainteneurs répondent en général sous 2 jours