Ios ui testability contract
Skill Kofiloski/ios-ui-testability-contract-skill/skills/ios-ui-testability-contract
Fix XCUITest element lookup, identifier collision, wrong element type, and nondeterministic launch failures.
npx -y skills add Kofiloski/ios-ui-testability-contract-skill --skill ios-ui-testability-contractAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Fix XCUITest, AXe, and ios-ai-ui-check failures where a SwiftUI or UIKit element is reported as not found, resolves as the wrong XCUIElement type, inherits a container accessibilityIdentifier, or cannot be reached deterministically. Use to diagnose UI automation artifacts and patch app-side accessibility identifiers, element exposure, stable row IDs, launch routes, seeded state, scenario files, or planner context, then verify the exact path with a focused replay.
SKILL.md
8.0 KB, as published. Nobody here has run it
iOS UI Testability Contract
Use this skill to repair the app-side automation surface. Keep XCUITest, AXe, or ios-ai-ui-check as the detector; use this skill to make the UI expose stable, testable targets.
Non-Negotiable Rules
- Inspect the actual failure artifacts before changing prompts or scenarios.
- Patch the app-side contract first when the UI tree proves the app is exposing the wrong target.
- Put identifiers on the intended interactive control, not on broad containers, unless the container itself is the target.
- Keep identifiers stable and literal when possible.
- Do not turn a backend or network problem into a fake UI-accessibility fix.
- Verify with a focused replay of the exact failure path before calling the work done.
Start Here
- Inspect the failure before changing prompts.
- Classify the contract problem.
- Patch the smallest app-side surface that fixes it.
- Update checked-in scenarios or planner context if the contract changed.
- Verify with an inspect pass and one focused scenario.
Open these references as needed:
references/failure-patterns.mdUse when the failure mode is unclear or you need to classify it quickly.references/swiftui-contract-patterns.mdUse when patching SwiftUI or UIKit views and choosing where identifiers belong.references/artifact-contract.mdUse when deciding what evidence to gather and what outputs a completed fix should leave behind.references/verification-loop.mdUse when deciding how to reproduce, inspect, and verify the fix.
Optional helper:
Run these commands when the separately packaged ios-ui-testability CLI is installed. The repair workflow does not depend on the CLI; inspect the same evidence directly when it is unavailable.
If the CLI is missing, use this release-pinned ephemeral command only when network installation is authorized and uvx is available:
uvx --from ios-ui-testability-contract==0.4.1 ios-ui-testability --help
ios-ui-testability idsUse when you need a quick inventory of literal accessibility identifiers, duplicate literals, likely non-literal identifier assignments, or likely parent-container collisions in a repo. Dynamic row or cell identifiers are only treated as acceptable when they are backed by a stable model ID.ios-ui-testability launchUse when you need a quick inventory of launch arguments, automation environment keys, URL schemes, and likely routing hooks before blaming the UI tree.ios-ui-testability triageUse when you havesummary.md, a UI tree, a scenario file, and optionallyplanner-validation-error.txtand want a fast first-pass root-cause bucket before patching code. Both accessibility identifiers and explicit scenario labels are compared with the captured UI tree. Pass--report-mode patch-planor--report-mode fullwhen you want the helper to suggest the first contract edits instead of just classifying the failure.ios-ui-testability draft-contextUse when bootstrapping or tightening.github/ai-ui/planner-context.mdfrom the repo's discovered launch hooks and stable identifiers. Pass--outputwhen you want it to write the draft directly into a file. The helpers reject missing scan roots and missing or malformed artifacts instead of treating them as empty evidence. Recursive repository scans emit root-relative paths, skip symbolic links, and report the skipped paths; launch scans also report plist files they could not parse or read. Inspect those notes before treating an inventory as complete. Identifier inventory excludes commented code and code examples embedded in Swift raw or multiline strings.
Inspect First
Inspect in this order:
summary.mdor the failing test output- the decisive failure line in the UI test log
- failure screenshot or video
- captured UI tree, if available
- checked-in scenario JSON or failing UI test steps
- the source view and nearby launch-routing code
Do not start by tuning prompts. First prove whether the app is exposing the correct automation contract.
Classify The Failure
Map the issue to one of these buckets:
- Missing identifier The intended element exists visually but has no stable automation handle.
- Identifier collision A parent container identifier is swallowing child controls, or multiple elements share the same identifier.
- Wrong element type
The identifier resolves, but XCTest finds a static label or container when the test needs a
Button,TextField, or similar control. - Unstable identifier The identifier depends on generated text, dynamic layout, or incidental state.
- Unreachable screen The app has no deterministic launch route or seeded state to reach the screen reliably.
- False UI problem The test is really asserting a backend or network-dependent outcome instead of a deterministic UI contract.
Fix Rules
Apply these rules consistently:
- Put identifiers on the actual interactive target, not broad containers, unless the container itself is the intended target.
- Prefer literal stable identifiers in source when source discovery or planner context depends on them.
- Expose one stable root identifier per screen or flow, then stable identifiers for primary controls within it.
- Reserve dynamic identifiers for repeated rows or cells backed entirely by stable model IDs; every interpolated component must be stable across launches. Keep screen roots, primary CTAs, input fields, and asserted targets literal and stable.
- Prefer identifiers over labels for durable interaction targets. When an existing scenario intentionally uses a label, verify that exact label is exposed in the captured UI tree and is not localization-dependent.
- Add deterministic launch routes or automation state only when the screen cannot be reached reliably through normal setup.
- Keep the app generic. Do not make the UI contract depend on one specific testing tool.
- Narrow or remove backend-dependent assertions unless the repo documents deterministic mocks or seeded state.
Update The Contract Surface
When the app-side contract changes, update the nearby artifacts that consume it:
- checked-in scenario JSON used for smoke coverage
- planner context or repo automation docs
- UI test helper comments or fixtures, if the contract became more precise
Do not rename or broaden identifiers casually. Stable IDs become part of the repo's automation API.
Artifact Contract
Treat these as the preferred inputs:
- failing
summary.md, test output, or CI comment - UI test log with the decisive failure line
- failure screenshot or video
- captured UI tree, if available
- checked-in scenario JSON or repo-local runner input
- source view plus any nearby launch-routing or seeding code
Leave behind these outputs when possible:
- the smallest app-side contract patch that fixes the issue
- updated checked-in scenario or planner context if the contract changed
- one inspect artifact or UI tree proving the target now resolves correctly
- one focused replay proving the original path now passes
- a brief explanation of whether the root cause was app contract, scenario contract, launch determinism, or a non-UI dependency
Verification Standard
A fix is not complete until you have:
- verified the UI tree exposes the intended identifier on the correct element type
- rerun one focused scenario on the exact failure path
- checked diff hygiene with
git diff --check
If the repo includes app-local helpers from ios-ai-ui-check, prefer those helpers for inspect and replay. Otherwise use the smallest direct xcodebuild UI test that covers the failure.