iOS App Development
Purpose
Take an iPhone app from local requirements to a verified internal TestFlight build. Treat implementation, signing, upload, Apple processing, tester assignment, and device installation as separate states with separate evidence.
Core Rules
- Read repository instructions, requirements, project configuration, and release artifacts before declaring a blocker.
- Inspect a known successful app from the same owner when one exists. Reuse its account, signing, and release pattern without copying app-specific identifiers, entitlements, permissions, dependencies, or deployment targets.
- Keep the product display name separate from stable internal target and scheme names when renaming would create needless release risk.
- Set
TARGETED_DEVICE_FAMILY: 1 for iPhone-only apps.
- Choose the minimum iOS version from required APIs and intended users. Do not copy another app's deployment target without evidence.
- Keep the app functional without an account unless account-backed behavior is an explicit requirement.
- Store secrets only through the repository's approved secret mechanism. Never print tokens, private keys, tester addresses, or account credentials.
- Do not claim TestFlight completion from a successful archive or upload alone.
- Do not commit or push unless the user has authorized it under the active repository instructions.
Start With Evidence
- Read the local specification and classify decisions as confirmed, provisional, or absent.
- Inspect the current project, Git state, installed Xcode, XcodeGen, schemes, signing settings, connected devices, and existing release artifacts.
- Inspect a successful sibling app when available. Record only the generalizable facts.
- Identify external choices that become durable, especially the Bundle ID and App Store Connect app record.
- Continue with reversible local work while durable choices remain open. Confirm final values immediately before registering them externally.
- Reconcile conflicting requirements into one named release contract. Record each conflict, chosen scope, and acceptance evidence instead of letting document order decide.
- Identify product claims that depend on unproven algorithms, models, datasets, or device behavior. Run a bounded feasibility spike with explicit pass and fail criteria before building production architecture around them.
For a new or regenerated project, read project-foundation.md.
Build In Vertical Slices
- Establish the app shell, persistence boundary, and the primary user workflow.
- Add one complete user-visible slice at a time, including its error, cancellation, empty, and recovery states.
- Keep framework adapters behind narrow interfaces so domain behavior can be tested without camera, network, StoreKit, or device hardware.
- Make file writes transactional. Persist metadata only after the corresponding files are durable, and clean up partial outputs after failure.
- Add permissions only when the implemented feature needs them. Include precise usage descriptions.
- Preserve user data across ordinary upgrades. Add migration or compatibility tests before changing stored formats.
- Prefer Apple frameworks and existing project dependencies. Add a third-party package only when it supplies material domain capability that would be unsafe or wasteful to recreate.
- For imaging features that alter document geometry or hidden content, separate deterministic transforms from inferred reconstruction. Never present generated text, symbols, or diagrams as recovered source content.
For precision camera, document, and image-restoration work, read precision-imaging.md.
Validate In Layers
Use the smallest useful check first, then broaden the evidence:
- Regenerate the Xcode project from its source configuration.
- Run an unsigned generic iOS build.
- Run focused unit tests.
- Run the full unit-test suite.
- Run UI tests for critical flows when they can be deterministic.
- Build with signing for a physical iPhone.
- Archive the exact Release configuration intended for upload.
- Inspect the archive metadata, embedded profile, entitlements, signature, version, build number, Bundle ID, architecture, and symbols.
- Install and exercise the signed or TestFlight build on a real device when user authorization and device access permit it.
Read quality-gates.md before declaring implementation or release readiness.
Release Through TestFlight
Read testflight-release.md before any App Store Connect mutation or upload.
The release state machine is:
- Unsigned local Release build passes.
- Durable product identifiers and App Store Connect metadata are confirmed.
- Explicit App ID exists.
- App Store Connect app record exists and matches the Bundle ID.
- Signed archive succeeds.
- Archive inspection passes.
- Upload succeeds.
- Apple processing reaches a valid state.
- The build is assigned to the intended internal tester group.
- The intended tester can see or install the build in TestFlight.
- The TestFlight build passes its primary workflow.
- A later distributed build preserves data from the previous build. Record this as not applicable for a first-ever build.
Do not collapse these states. Report the last confirmed state and the exact evidence for it.
Diagnose By Layer
Classify failures before changing code:
- Source or test failure
- Generated Xcode project failure
- package-resolution failure
- compiler or linker failure
- entitlement or permission failure
- certificate, profile, or Team mismatch
- archive metadata failure
- missing App ID or App Store Connect record
- upload transport failure
- Apple processing rejection
- tester-group assignment failure
- device installation or launch failure
- runtime crash or data migration failure
Do not treat a device support image issue, delayed Apple crash report, or App Store Connect processing delay as an app defect without supporting evidence.
For Swift 6 code crossing system callbacks, closures, delegates, audio or camera queues, or C APIs, test execution away from the main actor. Treat an actor-isolation crash as a release blocker even when simulator tests pass.
Improve This Skill During Real Work
After each material success or failure:
- Capture the observed symptom, confirmed layer, root cause, successful correction, and proof.
- Decide whether the lesson applies to more than one app.
- Add only reproducible, generalizable guidance to this skill or its references.
- Keep app names, Bundle IDs, Team IDs, App Store Connect IDs, tester identities, credentials, and one-off workarounds out of the skill.
- Re-run skill validation.
- Forward-test the changed skill against a realistic iPhone app request.
Remove guidance that is contradicted by a later verified workflow. Keep the skill compact and route detailed commands to references.
1---2name: ios-app-development3description: Build, repair, verify, and distribute native iPhone apps from requirements through internal TestFlight. Use for Swift or SwiftUI iOS projects, XcodeGen setup, signing, device validation, App Store Connect records, TestFlight uploads, tester assignment, release troubleshooting, and reusable development-process improvements.4---56# iOS App Development78## Purpose910Take an iPhone app from local requirements to a verified internal TestFlight build. Treat implementation, signing, upload, Apple processing, tester assignment, and device installation as separate states with separate evidence.1112## Core Rules1314- Read repository instructions, requirements, project configuration, and release artifacts before declaring a blocker.15- Inspect a known successful app from the same owner when one exists. Reuse its account, signing, and release pattern without copying app-specific identifiers, entitlements, permissions, dependencies, or deployment targets.16- Keep the product display name separate from stable internal target and scheme names when renaming would create needless release risk.17- Set `TARGETED_DEVICE_FAMILY: 1` for iPhone-only apps.18- Choose the minimum iOS version from required APIs and intended users. Do not copy another app's deployment target without evidence.19- Keep the app functional without an account unless account-backed behavior is an explicit requirement.20- Store secrets only through the repository's approved secret mechanism. Never print tokens, private keys, tester addresses, or account credentials.21- Do not claim TestFlight completion from a successful archive or upload alone.22- Do not commit or push unless the user has authorized it under the active repository instructions.2324## Start With Evidence25261. Read the local specification and classify decisions as confirmed, provisional, or absent.272. Inspect the current project, Git state, installed Xcode, XcodeGen, schemes, signing settings, connected devices, and existing release artifacts.283. Inspect a successful sibling app when available. Record only the generalizable facts.294. Identify external choices that become durable, especially the Bundle ID and App Store Connect app record.305. Continue with reversible local work while durable choices remain open. Confirm final values immediately before registering them externally.316. Reconcile conflicting requirements into one named release contract. Record each conflict, chosen scope, and acceptance evidence instead of letting document order decide.327. Identify product claims that depend on unproven algorithms, models, datasets, or device behavior. Run a bounded feasibility spike with explicit pass and fail criteria before building production architecture around them.3334For a new or regenerated project, read [project-foundation.md](references/project-foundation.md).3536## Build In Vertical Slices37381. Establish the app shell, persistence boundary, and the primary user workflow.392. Add one complete user-visible slice at a time, including its error, cancellation, empty, and recovery states.403. Keep framework adapters behind narrow interfaces so domain behavior can be tested without camera, network, StoreKit, or device hardware.414. Make file writes transactional. Persist metadata only after the corresponding files are durable, and clean up partial outputs after failure.425. Add permissions only when the implemented feature needs them. Include precise usage descriptions.436. Preserve user data across ordinary upgrades. Add migration or compatibility tests before changing stored formats.447. Prefer Apple frameworks and existing project dependencies. Add a third-party package only when it supplies material domain capability that would be unsafe or wasteful to recreate.458. For imaging features that alter document geometry or hidden content, separate deterministic transforms from inferred reconstruction. Never present generated text, symbols, or diagrams as recovered source content.4647For precision camera, document, and image-restoration work, read [precision-imaging.md](references/precision-imaging.md).4849## Validate In Layers5051Use the smallest useful check first, then broaden the evidence:52531. Regenerate the Xcode project from its source configuration.542. Run an unsigned generic iOS build.553. Run focused unit tests.564. Run the full unit-test suite.575. Run UI tests for critical flows when they can be deterministic.586. Build with signing for a physical iPhone.597. Archive the exact Release configuration intended for upload.608. Inspect the archive metadata, embedded profile, entitlements, signature, version, build number, Bundle ID, architecture, and symbols.619. Install and exercise the signed or TestFlight build on a real device when user authorization and device access permit it.6263Read [quality-gates.md](references/quality-gates.md) before declaring implementation or release readiness.6465## Release Through TestFlight6667Read [testflight-release.md](references/testflight-release.md) before any App Store Connect mutation or upload.6869The release state machine is:70711. Unsigned local Release build passes.722. Durable product identifiers and App Store Connect metadata are confirmed.733. Explicit App ID exists.744. App Store Connect app record exists and matches the Bundle ID.755. Signed archive succeeds.766. Archive inspection passes.777. Upload succeeds.788. Apple processing reaches a valid state.799. The build is assigned to the intended internal tester group.8010. The intended tester can see or install the build in TestFlight.8111. The TestFlight build passes its primary workflow.8212. A later distributed build preserves data from the previous build. Record this as not applicable for a first-ever build.8384Do not collapse these states. Report the last confirmed state and the exact evidence for it.8586## Diagnose By Layer8788Classify failures before changing code:8990- Source or test failure91- Generated Xcode project failure92- package-resolution failure93- compiler or linker failure94- entitlement or permission failure95- certificate, profile, or Team mismatch96- archive metadata failure97- missing App ID or App Store Connect record98- upload transport failure99- Apple processing rejection100- tester-group assignment failure101- device installation or launch failure102- runtime crash or data migration failure103104Do not treat a device support image issue, delayed Apple crash report, or App Store Connect processing delay as an app defect without supporting evidence.105106For Swift 6 code crossing system callbacks, closures, delegates, audio or camera queues, or C APIs, test execution away from the main actor. Treat an actor-isolation crash as a release blocker even when simulator tests pass.107108## Improve This Skill During Real Work109110After each material success or failure:1111121. Capture the observed symptom, confirmed layer, root cause, successful correction, and proof.1132. Decide whether the lesson applies to more than one app.1143. Add only reproducible, generalizable guidance to this skill or its references.1154. Keep app names, Bundle IDs, Team IDs, App Store Connect IDs, tester identities, credentials, and one-off workarounds out of the skill.1165. Re-run skill validation.1176. Forward-test the changed skill against a realistic iPhone app request.118119Remove guidance that is contradicted by a later verified workflow. Keep the skill compact and route detailed commands to references.