Consolidate tap-family flags into shared OptionGroups and a typed executor entry point#49
Merged
Merged
Conversation
Plan record for issue #42: shared TapTargetingOptions/TapTimingOptions, a fail-closed reflection guardrail for the remaining construct-and-assign forwarders, and a performTap-style executor entry point for the tap family (adopting the review suggestion, mirroring the Android precedent). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: onevcat <onevcat@gmail.com>
…teness (#42) Every construct-and-assign forwarder site (14 sites across 13 verbs) now builds its iOS backend command in a testable makeIOSSubcommand(). New ForwarderInitializationGuardTests Mirror-audits the result: any property left in ArgumentParser wrapper-definition state fails the test instead of trapping at runtime on first read (the #41 failure class). The audit fails closed — unrecognized wrapper internals or a walk that finds zero wrappers is a failure, so an ArgumentParser upgrade can break the guard loudly but never silently blind it. Paste.clientPreflight previously copied only the three fields it read; it now reuses the full copy so it can never trap if it grows another field read. Step 1 of docs/ai/xxxx-tap-optiongroup-consolidation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: onevcat <onevcat@gmail.com>
TapTargetingOptions (coords, five selectors, --element-type, --frame) and TapTimingOptions (--pre-delay/--post-delay/--wait-timeout/ --poll-interval) now live in SimUseCore/Options/, declared once and consumed by Tap, LongPress, and IOSSimTapCommand. The forwarders transfer whole parsed groups, so a field added inside a group appears on every surface and forwards with zero forwarder edits. The positional alias and --duration deliberately stay per-command (verb-specific help / default). Validation moves onto the groups (TapTargetingOptions.validate(alias:), TapTimingOptions.validate() + validateDuration), replacing the 15-param IOSSimTapCommand.validateOptions static. ArgumentParser does not auto-validate nested groups, so each surface's explicit calls are load-bearing — the new TapValidationParityTests pins that the same invalid argv fails with the same message on all three surfaces, which is exactly the regression a dropped call would cause. Behavior notes (pinned by a before/after --help diff): flag names, defaults, validation messages, and --json envelopes are byte-identical; help wording unifies to verb-neutral phrasing and the timing flags render as one block — both deltas recorded in CHANGELOG and the plan doc. Step 2 of docs/ai/xxxx-tap-optiongroup-consolidation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: onevcat <onevcat@gmail.com>
IOSSimTapCommand.performTap(alias:targeting:timing:duration:multiTouch: device:json:) is now the single execution entry for the tap family — the iOS mirror of AndroidTapCommand.performTap. `sim-use ios tap` delegates from execute(), and the top-level `tap` / `long-press` forwarders call it directly with their parsed groups: no backend command instance is hand-built anymore, so the wrapper-definition trap (#41's failure class) is impossible on this path by construction, not by guardrail. The two tap-family guard tests retire together with the copy code they pinned; the guard suite keeps covering the 11 verbs still on the construct-and-assign pattern. setup(logger:) body moves to a free performEssentialSetup(logger:) — it never touched the command instance — so static entry points can run the same Xcode/framework preflight. Step 3 of docs/ai/xxxx-tap-optiongroup-consolidation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: onevcat <onevcat@gmail.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: onevcat <onevcat@gmail.com>
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 #42.
What this does
Three steps, one commit each (plus the plan doc in
docs/ai/xxxx-tap-optiongroup-consolidation/):93dd606) — every construct-and-assign forwarder site (14 sites, 13 verbs) extracts its copy block into a testablemakeIOSSubcommand(), andForwarderInitializationGuardTestsMirror-audits the result: a property left in ArgumentParser wrapper-definition state fails in CI instead of trapping at runtime (the Fixandroid tapcrashing on ArgumentParser direct-init trap #41 failure class). The audit fails closed — unrecognized wrapper internals are a test failure, so an ArgumentParser upgrade can break the guard loudly but never silently blind it. Bonus:Paste.clientPreflightwas a deliberately partial three-field copy; it now reuses the full copy.4622a52) —TapTargetingOptions(coords, five selectors,--element-type,--frame) andTapTimingOptions(--pre-delay/--post-delay/--wait-timeout/--poll-interval) live inSimUseCore/Options/, declared once and consumed bytap,long-press, andios tap. Validation moves onto the groups; ArgumentParser does not auto-validate nested groups, so the newTapValidationParityTestspins that the same invalid argv fails with the same message on all three surfaces — exactly the regression a dropped validator call would cause. The positional alias and--durationdeliberately stay per-command (verb-specific help / default).17f434a) —IOSSimTapCommand.performTap(alias:targeting:timing:duration:multiTouch:device:json:), the iOS mirror ofAndroidTapCommand.performTap, adopting @hiSandog's review suggestion on the issue. Thetap/long-pressforwarders pass their parsed groups by value; no backend instance is hand-built, so the wrapper-definition trap is impossible on this path by construction. The two tap-family guard tests retire with the copy code they pinned.Behavior contract
Flag names, defaults, validation messages, and
--jsonenvelopes are byte-identical (pinned by a before/after--helpgolden diff and the parity tests). The only user-visible deltas, both recorded in CHANGELOG:--duration.Verification
--helpgolden diff on all three surfaces: only the two documented deltas.describe-ui,tap --point(exact-coordinate hit),tap @N(alias cache path),long-press --label-contains --element-type, and both--jsonenvelope paths (success + no-match error with hint).Follow-ups (out of scope)
AndroidTapCommandshares the targeting group (Int pixel coords + Android-only--value-contains/--value-regex).🤖 Generated with Claude Code