Conversation
Investigated selectPhotos, a step to pick images from PHPickerViewController's grid, along with a seedPhotos precondition for deterministic fixture content. On-device investigation found that every actuation technique tried against the picker's grid cells (handle-based tap, handle-based long-press at two durations, a raw coordinate tap) fails to reliably select a cell on an Apple silicon Simulator, matching independently reported limitations on Apple's own developer forums. Bajutsu retired its one alternative iOS actuator (idb) in BE-0290, leaving no existing fallback path around this. The item is recorded as Deferred with the full investigation, rather than shipped with a core mechanism that does not work on the architecture most contributors run. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved design issues affect fixture seeding, scenario determinism, and lifecycle metadata.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
This documentation-only PR adds a bilingual deferred roadmap item for PHPickerViewController image selection.
Changes:
- Proposes
selectPhotosandseedPhotosbehavior. - Records Simulator actuation failures and deferral rationale.
- Adds English and Japanese roadmap documentation.
File summaries
| File | Description |
|---|---|
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos.md |
English proposal and investigation |
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos-ja.md |
Japanese proposal mirror |
Review details
Suppressed comments (18)
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos-ja.md:280
- この参考文献でも「実演算経路」を使っています。本文と同じく、一般的でないこの語を「操作手段」などの明確な表現に置き換え、文末も文書の敬体にそろえてください。
— `idb`の廃止。Unit 3のブロッカーを迂回できていた可能性がある、iOSのもう1つの実演算経路で
あり、現在残っているのはXCUITestだけである。
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos-ja.md:111
- The Japanese formatting rules prohibit using an em dash as the separator in prose headings. Use a colon here, matching the corrected Unit 1 heading.
### Unit 2 — `selectPhotos` DSLアクション
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos-ja.md:136
- The Japanese formatting rules prohibit using an em dash as the separator in prose headings. Use a colon here, matching the other corrected Unit headings.
### Unit 3 — セルのアクチュエーション(ブロック中)
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos-ja.md:189
- The Japanese formatting rules prohibit using an em dash as the separator in prose headings. Use a colon here, matching the other corrected Unit headings.
### Unit 4 — Capability、他バックエンド、showcaseでの実証
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos-ja.md:254
- The same em-dash separator is used in this Japanese checklist label, but the formatting rules require a colon for this heading-like label. Please apply the same replacement to the other Unit checklist entries.
- [ ] Unit 1 — `addmedia_cmd`、`seedPhotos`プリコンディション、`_prepare_simulator`での
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos-ja.md:256
- The same em-dash separator is used in this Japanese checklist label, but the formatting rules require a colon for this heading-like label.
- [ ] Unit 2 — `SelectPhotos` DSLアクションとそのバリデーション。
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos-ja.md:257
- The same em-dash separator is used in this Japanese checklist label, but the formatting rules require a colon for this heading-like label.
- [ ] Unit 3 — ピッカーのグリッドセルを確実にアクチュエーションする手段(ブロック中。
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos-ja.md:259
- The same em-dash separator is used in this Japanese checklist label, but the formatting rules require a colon for this heading-like label.
- [ ] Unit 4 — `SELECT_PHOTOS`ケーパビリティ、他バックエンドの`UnsupportedAction`、showcase
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos-ja.md:99
contained_refはシナリオファイルのディレクトリを基準に参照を解決し、スイートルートは包含境界としてだけ使います。これは現在のdataFileの挙動です。seedPhotosをスイートルート基準と記述すると、ネストしたシナリオのパス規約が既存DSLと異なり、解決方法が曖昧になります。ファイル基準で解決してスイート内に制限する仕様を明記するか、別のルート基準リゾルバーを設計してください。
`seed_photos: list[str]`(YAMLでは`seedPhotos`)を追加します。値はスイートルートを起点とした
相対パスの配列です。`dataFile`がすでに使っているものと同じ`contained_ref`の関所
(`bajutsu/common/scenario/load_expanded.py`)を通して解決するため、スイートの外を指すパスは
投入できません。投入先は`_prepare_simulator`
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos-ja.md:207
- 設計では投入が
cold and pre.eraseの場合に限られますが、showcaseのターゲットは組み込み既定値のerase: falseを継承しており、このシナリオの説明にも消去の前提がありません。このままではseedPhotosが実行されず、Simulatorのサンプル画像を使うため、決定的なフィクスチャになりません。説明するシナリオにpreconditions: { erase: true }を追加してください。
`demos/showcase/scenarios/select_photos.yaml`が`seedPhotos`でこれらを投入し、
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos-ja.md:10
- 🤖 Claude Code — issue (non-blocking): This is a new
BE-XXXXitem, but the roadmap workflow requires every new item to start withStatus: Proposal;Deferredis a later dashboard state. Keep the Japanese metadata in the same proposal-first state so the two language files do not initialize the item in different lifecycle stages.
| 状態 | **保留** |
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos-ja.md:103
- 🤖 Claude Code — issue (non-blocking):
seedPhotosis silently skipped unless the run is both cold and erasing, but warm resume passescold=Falseand the scenario shape does not require an erase. The scenario can therefore pass validation while selecting pre-existing photos instead of its declared fixtures; choose an explicit reset or an early validation error rather than silently ignoring the seed.
投入できません。投入先は`_prepare_simulator`
(`bajutsu/common/platform_lifecycle/environments/xcuitest/xcuitest_environment.py:866-939`)
に限ります。対象は、コールド起動かつ`erase`を伴う経路(`cold and pre.erase`)だけです。この
経路はすでにSimulatorの既存状態を消去する経路であり、ここに乗せることで、ウォーム再開や
`erase`を伴わないリースでの重複投入を防げます。
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos-ja.md:109
- 🤖 Claude Code — question (non-blocking): The reverse-order contract is based on three separate
addmediacalls, butaddmedia_cmdaccepts a sequence and the planned shape reads as one batch command. Specify whether the implementation must call it once per fixture or establish the batch ordering; otherwise the documented indices may refer to the wrong images.
ピッカーはライブラリを新しい順に並べます。実測では、数秒間隔で3枚のフィクスチャを別々の
`addmedia`呼び出しで追加したところ、追加順とは逆順に並びました。最後に追加したフィクスチャが
インデックス0に来ます。これは、Simulatorにあらかじめ入っているサンプル画像よりも前に来ます。
したがって、シナリオの`indices`は、`seedPhotos`に列挙した順序とは逆順でフィクスチャを指す
ことになります。この対応は、動作から発見させるのではなく、DSLのリファレンスに明記します。
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos-ja.md:160
- 🤖 Claude Code — suggestion (non-blocking):
Realデバイスis an unnatural mixed-language term in Japanese technical prose. Use the established Japanese term実機for the contrast with Simulator.
Simulator上のXCUITestでは登録されない一方、Intel SimulatorやRealデバイスでは機能する、
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos-ja.md:197
- 🤖 Claude Code — issue (non-blocking):
SELECT_PHOTOSis declared by the wholeXcuitestDriver, which also supports real devices, while the seeding design only runs through_prepare_simulator. On a real device,seedPhotoswould be ignored even though capability preflight succeeds, so ordinal selection is not deterministic. Define whether real devices reject the feature, require an external fixture, or get a separate seeding path before exposing the capability.
`Capability.SELECT_PHOTOS = "selectPhotos"`(`bajutsu/common/drivers/base/capability.py`)は
`XcuitestDriver.CAPABILITIES`(ユニットテスト用に`FakeDriver.CAPABILITIES`にも)だけが宣言
します。`bajutsu/common/capability/capability_preflight.py`で`HANDLE_SYSTEM_ALERT`と同様に
ゲートします。Androidやwebのターゲットが`selectPhotos`を使うと、実行時の不透明なエラーでは
なく、プリフライトの時点で名指しのケーパビリティエラーになります。`playwright_driver.py`・
`adb_driver.py`・`xcuitest_live_driver.py`・`web_context_driver.py`は、それぞれ自身の
`select_photos`から`UnsupportedAction`を送出します。他のiOS専用アクションと同じ扱いです。
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos.md:10
- 🤖 Claude Code — issue (non-blocking): This is a new
BE-XXXXitem, but the roadmap workflow requires every new item to start withStatus: Proposal;Deferredis a later dashboard state. Leaving this asDeferredbypasses the proposal-first lifecycle, so change the metadata toProposaland defer it after the item is allocated.
| Status | **Deferred** |
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos.md:104
- 🤖 Claude Code — question (non-blocking): The reverse-order contract was measured with three separate
addmediainvocations, while the proposed builder accepts a sequence and emits one argv. Unless seeding explicitly invokes the builder once per file (or the batch ordering is measured), import timestamps can differ andindicescan select the wrong fixture; define the invocation granularity before making this ordering part of the DSL contract.
The picker sorts the library newest-first (measured: three fixtures added a few seconds apart, via
three separate `addmedia` invocations, appeared in reverse of their addition order — the
most-recently-added fixture at index 0), *ahead of* the Simulator's own pre-installed sample
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos.md:192
- 🤖 Claude Code — issue (non-blocking):
SELECT_PHOTOSis declared by the wholeXcuitestDriver, which also supports real devices, but Unit 1 only seeds through_prepare_simulator; real-device setup therefore ignoresseedPhotos. A scenario can pass capability preflight and then select ordinal positions from an uncontrolled library, defeating the deterministic fixture contract. Define whether real devices rejectseedPhotos/selectPhotos, require an external fixture, or receive a separate seeding path before exposing this capability.
`Capability.SELECT_PHOTOS = "selectPhotos"` (`bajutsu/common/drivers/base/capability.py`) is
declared only by `XcuitestDriver.CAPABILITIES` (and by `FakeDriver.CAPABILITIES` for unit tests),
gated through `bajutsu/common/capability/capability_preflight.py` the same way
`HANDLE_SYSTEM_ALERT` is — an Android or web target using `selectPhotos` fails preflight with a
named-capability error rather than an opaque runtime one. `playwright_driver.py`, `adb_driver.py`,
`xcuitest_live_driver.py`, and `web_context_driver.py` each raise `UnsupportedAction` from their own
`select_photos`, matching every other iOS-only action.
- Files reviewed: 2/2 changed files
- Comments generated: 10
- Review effort level: Lite
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Prototyped a coordinate press (XCUICoordinate.press(forDuration:)), the generalization of BE-0396's own frame-centre-tap fix, by extending tapPoint with an optional duration end to end (Swift + Python + DSL). It fails the same way the plain coordinate tap does: accepted, no cell marked selected. Reverted the prototype since it did not unblock the item, and recorded the result in Unit 3 as the closing of the most obvious remaining avenue. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Fix a factual error: `photos` is an ordinary simctl privacy TCC service (like camera/location); the gap is that granting it does not pick an item, not that no such service exists. - Move `seed_photos` from `Scenario` to `Preconditions`, beside `erase`/ `reinstall`, so it reaches `_prepare_simulator` with no new plumbing (previously `Scenario`-level fields need threading through `launch_driver` the way `permissions` is). - Require `erase: true` alongside a non-empty `seed_photos` via a loud, load-time validator, instead of a silent no-op that would leave `selectPhotos` addressing the Simulator's ambient library. - Seed one path per `addmedia` invocation (matching what was actually measured) rather than batching, since batch ordering is unverified. - Fix `contained_ref`'s description: paths resolve relative to the scenario file's own directory, with the suite root only as the containment boundary — matching `dataFile`'s existing resolution exactly. Note that `bajutsu run`'s own loader shares the same function. - Fix the confirm-button resolution to identify the picker's navigation bar by trait alone, not by its localized "Photos" title, so the rule stays locale-independent as advertised. - Record the exact presentation setup (selectionLimit, UIViewController- Representable) Unit 3's measurements used, for reproducibility. - Add the required `erase: true` precondition to the showcase demo scenario description. - ja: fix em-dash Unit headings to colons, replace the non-standard 「実演算経路」 wording, remove a duplicate/contradictory BE-0396 reference, and bring the log entry's register in line with the rest of the document. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Pull request was converted to draft
Summary
Investigates adding
selectPhotos, a step to pick images from a presentedPHPickerViewController's grid by ordinal position, plus aseedPhotosprecondition to seed the Simulator's photo library with known fixture images. On-device investigation found that every actuation technique tried against the picker's grid cells — a handle-based tap, a handle-based press at two durations, a raw coordinate tap, and a coordinate press (the generalization of BE-0396's own frame-centre-tap fix) — fails to reliably select a cell on an Apple silicon Simulator, matching independently reported limitations on Apple's own developer forums. Bajutsu retired its one alternative iOS actuator (idb) in BE-0290, leaving no existing fallback path around this.This PR records the proposal as Deferred rather than Implemented: the design for the buildable parts (seeding, the DSL action, capability plumbing) is kept as the starting point for whoever resumes the item, and the blocked actuation investigation is recorded in full, with sources, so resuming does not start from scratch.
What changed
roadmaps/BE-XXXX-phpicker-select-photos/(new) — the bilingual proposal (English + Japanese). Introduction/Motivation state the gap and the two facts (non-deterministic grid content by default, cells that cannot be actuated reliably) that decided the design. Detailed design covers Units 1 (photo seeding), 2 (theSelectPhotosDSL action), 3 (actuation — blocked, with the four attempts and results tabulated), and 4 (capability + showcase fixture). Alternatives, Progress, and References close it out.Scope
No product code in this PR. Every actuation technique tried failed on-device (Unit 3), so nothing is shippable yet — shipping the seeding/DSL/capability units alone would land a DSL surface that parses and then fails every run, which is worse than not shipping it. This PR is the investigation and proposal only.
Prime-directive compliance
Docs-only change; no runtime behavior is touched.
Verification
scripts/lint_roadmap.py: all item links resolve and authors are handle links.Files
roadmaps/BE-XXXX-phpicker-select-photos/BE-XXXX-phpicker-select-photos.md+ its-ja.mdmirror (bilingual pair)BE ID allocation
BE-XXXXis a placeholder — CI allocates the real id onmainafter merge. Don't hand-edit it.🤖 Generated with Claude Code