Apple platform + runner: simplify, shrink, and preserve correctness (tracking)
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 25/100
- issue の種類
- リファクタリング
- 明瞭さ
- おおむね明確
- 活発さ
- 活発
- 技術スタック
- swift, typescript
- 領域
- mobile, testing-qa, tooling
調査の方向性
This is a tracking issue for a large-scale audit and refactor of the Apple platform code. It references many child issues. To start, examine the packages/platform-apple TypeScript code and apple/runner Swift code. The suggested order is to begin with bugs #2781-#2783 related to runner main-thread correctness. Understanding the runner lifecycle, lease detach/adopt, and command journal is necessary before making changes.
索引モデルが issue の本文から書いたものです。
説明
Apple runner: simplify, shrink, and preserve correctness
This initiative removes unnecessary Apple runner/platform-apple production code while preserving device-proven behavior. Correctness and regression proof come first; abstractions must earn their cost by removing decisions, state or mechanisms. Cleaner file layout alone is not success.
Source baseline: 5712a3552e209c9c853bc1f42cb3e007f1213139, including #2911 isolation and #2961 placeholder propagation. GitHub main 8c89891b215c8504d1881eef06031d1d5f223726 was also checked: its SDK exports do not alter these implementation scopes. Every executor must check drift before editing. Findings here are source-verified; this audit did not rerun simulators or physical devices.
Core success criterion: less production machinery
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.
The initiative must report its cumulative production delta and the mechanisms actually eliminated. Separate correctness/type-safety growth from cleanup savings; the cleanup tranche should shrink. A positive overall production delta is not “simplify-and-shrink complete” without an explicit maintainer decision to rescope the goal. Historical removals before this follow-through baseline do not count as new savings. Do not set an arbitrary deletion quota before measurement, and do not delete necessary recovery just to make the total negative.
Architecture constraints
Keep one host session/resource owner and one accounting owner. Separate command exchange only enough to satisfy the owning-module and size rules. Keep the existing main-actor target state; preserve distinct native-work, penalty, warmup and private-AX lifetimes. Shared native-build mechanics should shed snapshot-specific dependencies. Swift/TypeScript presenters retain shared semantic proof. No new actor, retry, cache, or generic service framework is part of this initiative; an actor experiment must independently demonstrate a deletion/coordination benefit before becoming implementation work.
The earlier concrete scheduler and penalty extractions are retained as deferred candidates, not required end-state modules.
Execution order and status
Verified 2026-09-25: #2911 is merged; #2963 remains open. This tracking update does not merge either PR. Complete/rebase overlapping host cleanup onto #2963's exact merged head (or explicitly declare a stack on its published head); do not block independent classification/tests on unrelated host files.
| Order | Work | Gate / success |
|---|---|---|
| 1 | Finish the in-flight deletion in #2963; preserve merged #2911 | Establish the overlapping host baseline; do not redo landed isolation work |
| 2 | #2965 accounting model and correctness fix | Decide command-identity settlement, then smallest fix; minimal required size extraction only |
| 3 | #2972 typed AX; #2974 differential; #2970 native-build seam | Delete redundant classification/plumbing; add decisive regression proof; native-build move needs an actual deletion case |
| 4 | #2967 session/exchange split → #2971 payload types | Required split targets neutral/negative lines; type-safety growth reported as such |
| 5 | #2968 characterization → conditional #2969 | Characterization must establish a real gap or deletable repeated logic before ownership migration |
| Deferred | #2966 scheduler owner; #2973 penalty owner | No implementation until redundant state/coordination can be deleted or a concrete correctness need is shown |
| Measurement track | Outer transport resend; private AX | Establish whether larger paths can be removed; keep or delete based on working control evidence |
Run shared runner Swift work (#2966/#2968/#2969/#2972/#2973, and any overlapping native harness edits) one issue at a time, rebasing after each merge. Disjoint TS/test research may proceed independently; devices and full host gates remain exclusive. Do not infer scheduling readiness from an old paragraph or an unchecked box: child labels and the scope gates above must agree.
Measure before deleting: explicit workstream
These are research deliverables, not authorization to remove fallbacks speculatively. A measured “retain” result is valid and must name the concrete capability/failure it still serves.
- Outer read-only transport resend. Owner: this umbrella,
packages/platform-apple/src/runner/runner-client.ts. Current source distinguishes three transport attempts from eightRUNNER_BUSYattempts; do not treat them as one redundant loop. Trace which lower layer already retries/recycles, prove both paths reachable, and compare transport retries enabled versus a one-attempt experimental control. Record command IDs, native execution count, transport send count, final outcome, elapsed budget and cancellation behavior for initial connection failure, recoverable post-send loss, startup failure, busy/draining and stale-session recovery. Use the existing fake-runner wiring plus simulator/physical lanes relevant to the claimed removal. Deliver a retain/delete/narrow verdict, exact production paths/lines removable and required regression cases. Coordinate #2894/#2475; do not silently reduce the busy drain window or replay mutations. Temporary diagnostics must be removed or justified as an owning diagnostic. - Runner private-AX tier. Owner: this umbrella, with ADR 0004 and #1626 as related existing work. Inventory which consumers still require custom actions, unavailable/disabled host bridge, occupied XCTest recovery, raw/depth semantics, real-device/provider support and differing quality/viewport facts. Prove the proposed substitute actually serves each required case with matching fidelity and budget before any deletion. Include bridge-circuit-open and hostile-screen controls; a success on the healthy simulator path is insufficient. Deliver a capability/evidence matrix, retain/delete/partial-reduction verdict, net implementation delta including any new bridge features, and precise unsupported cases. The earlier ~1.4k-line estimate is historical, not a guaranteed saving; count current reachable code. Do not expand #1626's shallow-acquisition task into tier removal.
Curl-through-simctl disposition (2026-10-02): #2662 is closed as not planned for its remaining instrumentation/deletion investigation. Retain the reachable simulator curl fallback and its scoped-set, timeout and cancellation semantics; no measured redundancy or correctness defect currently justifies the campaign. This is a priority decision, not a measured retain/delete result. Reopen only for a concrete transport incident or a measured removal case. The consumer retry-safety contract shipped as typeddetails.dispatchedin #3071/#3082/#3099; no seconddispatchOutcomefield is planned.
Each research result is recorded here or on its named owner with baseline SHA, conditions, artifacts, counterexample coverage, and deletable production scope. Any implementation decision becomes a bounded child contract before coding; a research result alone does not change a device support guarantee.
Before/after scorecard
Every implementation PR records its baseline SHA, final SHA, actual commands/results, and the following applicable measures:
| Dimension | Before | Required after |
|---|---|---|
| Behavioral correctness | Existing successes plus each named gap | Existing suite remains green; bug/proof work includes a demonstrated failing case or planted policy mutation |
| Ownership | Direct state writers and mixed responsibilities listed in child | One authoritative writer/transition seam; no mirrored registry, counters, compatibility facade, or public mutable cache |
| Contract strength | Optional payload bag / prose-based inference / hidden test exclusions | Negative type or classification cases rejected; new differential arms actually execute |
| Change locality | List concrete files needed for one representative policy change | Policy and its tests colocated; callers express intent without reconstructing ordering or reset subsets |
| Code removed | Record production additions/deletions/net delta and old mechanisms | Cleanup shrinks; mandatory splits may be neutral; correctness/type growth explicitly justified; no moved-code savings |
| Code structure | Record touched-module/test line counts | Source and matching tests split together where required; no new >1,000-line files or forwarding-only layers |
| Runtime behavior | Matched fixture outputs, retry counts, transport sends, busy/handoff and cache outcomes | Exact preservation except #2965's accounting correction and #2972's code-only AX classification correction; genuine native AX paths retain their outcome; unchanged deadlines, fallback order and wire omissions |
| Performance | No new measurements were collected by this audit | No claimed speedup; investigate any observed regression with matched device, toolchain, backend and fidelity |
For a suspected timing regression, use scripts/ios-snapshot-benchmark/README.md: at least 10 matched cold/first-interaction samples and 20 warm/relaunch samples, retaining raw results and backend/quality facts. These sample counts support comparison, not a universal latency promise or a new invented percentage threshold. Do not demand device timing for a type-only or pure-classification change.
Fresh worktrees require pnpm install --frozen-lockfile && pnpm build. Follow docs/agents/testing.md, docs/agents/device-verification.md, and each child's focused checks; run pnpm check:affected --run on the final diff. Stage new files before trusting tracked-file layering gates. Do not hide a module split with eager-closure allowlists or bulk Fallow baseline regeneration. Selected native/device lanes are obligations; distinguish local fake-runner proof, simulator proof, and physical-device proof. Mark unavailable device evidence pending.
Existing owners, preservation rules, and exclusions
- #2882 owns static main-actor enforcement. Keep the already-landed
RunnerMainOwnedStateisolation and compile canary; coordinate new owner files with its remaining source guards. - #2662 delivered response decoding and the session-state enum. Its remaining curl investigation is closed as not planned, with the existing fallback retained. Public retry safety now uses the dispatch-disclosure contract from #3071/#3082/#3099.
- #2754 remains the owner of broader membership attribution/ejection dispositions and capture surveys. The linked differential child owns only its still-missing runner-stage proof.
- Preserve independent launch/retry/recorded-failure traits, shared synthesized tap fallback, reported/derived/missing viewport facts, deadline-exhausted capture disqualification, and physical-iOS relaunch retention.
- Keep native main-thread occupancy distinct from host command completion. Terminal journal status is not proof that abandoned native work has drained.
- Keep target transition reset subsets distinct until characterization proves otherwise. In particular process refresh rearms warmup; external relaunch currently does not.
- Keep the Swift bundle-and-expiry XCTest penalty, private-AX accepted-depth cache, warmup exemption, and host app-generation bridge circuit separate.
- Screenshot/recording helpers presently located in
RunnerTests+Lifecycle.swiftare an opportunistic colocation step inside the target-transition child only when needed to isolate that owner. No standalone file-shuffling project. - Do not replace both snapshot presenters with one universal engine, rewrite the entire runner to actors/async, invent a generic retry/circuit-breaker framework, delete private-AX/curl fallbacks without measurement, or expand protocol/device support.
Non-blocking actor follow-up
#2976 compares a command-control actor with an equivalent concrete synchronized coordinator after the first cleanup wave (#2963, #2965, #2972, #2974, #2970). It requires preserved ordering/timeout behavior and a measured deletion/complexity case. It does not block this umbrella's completion and does not authorize a production actor migration. Run the experiment before reconsidering the deferred scheduler/penalty extractions or expanding target ownership; keep shared Swift edits serial. A negative result is a valid completion.
Closure
Close only after checking active child states and merged PRs, reporting the cumulative production delta and removed mechanisms, and recording retain/delete decisions for the measurement track. Deferred #2966/#2973 and conditional #2969 do not force low-value implementation: explicitly retain their deferral or close them with rationale after review. A positive production delta requires an explicit scope decision rather than a shrinkage claim. A design gate is not complete merely because it was written down.
Historical audit
Purpose
A tracking issue for a simplification and correctness audit of the Apple side: packages/platform-apple (about 32k lines of production TS) and apple/runner (about 17.5k lines of Swift plus ObjC bridges), at 01328de411.
Method:
- Four read-only audits applied community Swift skills: AvdLee and twostraws Swift Concurrency and Swift Testing, the Swift API Design Guidelines, and jazzychad's ios-code-audit.
- A second model cross-reviewed every finding against the code.
- The top claims were spot-checked by hand.
Findings refuted in review are not filed here.
Verdict: the core machinery earns its complexity: runner lifecycle, lease detach/adopt, recycle ledger, readiness preflight, command journal, three-tier snapshot plan, and the private-AX ladder pinned by conformance fixtures. The waste sits at the edges. Removing it cuts about 1–1.5k production lines, and moving the inline tests (#2792) takes about 3.9k lines out of production Swift files.
Each child issue is one PR (or a small series of pure-move PRs) inside one module group.
Original audit status (verified 2026-09-25)
The three previously outstanding issues are now closed: #2788 / #2865, #2796 / #2858, and #2797 / #2876. All three PRs are merged. The prior audit's checklists follow; these are historical results, not new improvement measurements.
Bugs (original audit)
- #2781 Snapshot plan data race on main-owned target state — #2836
- #2782 MAIN_THREAD_TIMEOUT reported for finished work — #2837
- #2783 Query sweep outlives its 1 s slice → RUNNER_BUSY — #2836
- #2784
simctl spawnmissing--set(AX bridge, fold) — #2818 - #2785 Physical install lost devicectl hints; dead install/uninstall/push — #2857
- #2788 Sequence tap and standalone tap fall back differently; one fallback helper — #2865
- #2789 visionOS taps request impossible synthesis — #2835
- #2796 Runtime clang
-Werror; fold recompiles every call — #2858; physical/Duo evidence remains scoped to the implementation report
Cuts (ready-for-agent)
- #2786 Swift retry on message text → typed codes — #2831
- #2787 TS retry on self-produced message text → typed reasons — #2820
- #2790 Dead
.continuousdrag profile — #2825 - #2791 Dead env knobs,
backcommand, unreachable paths — #2828 - #2792 Move inline Swift unit tests out; split CommandExecution under 1,000 lines — #2854, #2855
- #2793 Runner client forwarding chain; one TS trait table — #2822
- #2794 One simctl
--setbuilder and state parser (after #2784) — #2824 - #2795 xctrace dedupe; split perf.ts — #2823
- #2797 RUNNER_PROTOCOL.md drift — #2876
Decided 2026-09-23 (codex cross-check + code verification), now ready-for-agent
- #2798 Drop the inert
--device-hub(plain removal, not treated as breaking) — #2821 - #2799 Reject
--fullscreenfor macOS desktop/menubar helper surfaces; keep it for app sessions — #2849 (widened to every helper-captured surface, includingfrontmost-app) - #2800 Restrict the tap-witness type route to
'\n'— #2845 - #2801 Bound recorder frame capture through
runMainThreadWork; screenshots are already bounded — #2837 - #2802 Delete the Swift warning text (TS already renders every fact); keep the
treepin — #2834
Already tracked elsewhere
#2662 is closed: response decoding and session state shipped; curl transport removal is not planned and the existing fallback is retained. See its disposition comment for the public dispatch-disclosure contract.
Historical measurement candidates (now promoted above)
- The outer 3× read-only retry in
runner/runner-client.ts:42-56. It predates the recycle ledger (#1105). - The runner's private-AX tier, about 1.4k lines. It could go only if the host bridge learns to read custom actions, and removing it weakens recovery while the bridge circuit is open.
- 主要言語
- TypeScript
- スター
- 5.1k
- フォーク
- 339
- 平均マージ
- 12時間 50分
- マージ済み PR(30日)
- 632
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
callstack/agent-device のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 64/100
callstack/agent-device#3945 ·
メンテナーはふだん 1 日以内に返信
-
Limrun iOS fill reports success but drops non-ASCII text対応中かも @mvanhorn が 5 日前に担当しました。 オープンbug ready-for-agent
難易度 2/5 1〜3時間 初心者へのやさしさ 87/100
callstack/agent-device#3819 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
callstack/agent-device#1869 ·
メンテナーはふだん 1 日以内に返信
-
iOS keyboard capture can race dismissal and omit the input assistant bar対応中かも @shamilovtim が今日担当しました。 オープン
難易度 4/5 3〜5日 初心者へのやさしさ 51/100
callstack/agent-device#3957 ·
メンテナーはふだん 1 日以内に返信
-
iOS fill can report TEXT_ENTRY_MISMATCH before the confirmation deadline対応中かも @shamilovtim が今日担当しました。 オープン
難易度 3/5 1〜2日 初心者へのやさしさ 35/100
callstack/agent-device#3952 ·
メンテナーはふだん 1 日以内に返信
callstack/agent-device の issue をすべて見る
似ている issue
-
Native Web
難易度 1/5 1時間未満 初心者へのやさしさ 80/100
digitalfabrik/integreat-app#4517 ·
メンテナーはふだん 2 日以内に返信
-
TLS guide repeats certs/ in the certificate directory対応中かも @maheshrijal が今日担当しました。 オープン
難易度 1/5 1時間未満 初心者へのやさしさ 92/100
prometheus/docs#3156 ·
メンテナーはふだん 2 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 83/100
medusajs/dtc-starter#90 ·
メンテナーはふだん 1 日以内に返信
-
usability
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
inmanta/web-console#7632 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
zaidmukaddam/scira#261 ·