@mmerterden/multi-agent-pipeline 20.36.0 → 20.37.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/docs/facts.json +2 -2
- package/docs/features.md +1 -1
- package/docs/recovery-guide.md +1 -1
- package/install/catalog-history.json +1 -1
- package/manifest.json +225 -148
- package/package.json +1 -1
- package/pipeline/commands/multi-agent/SKILL.md +33 -154
- package/pipeline/commands/multi-agent/analysis/SKILL.md +14 -68
- package/pipeline/commands/multi-agent/analysis-jira/SKILL.md +5 -8
- package/pipeline/commands/multi-agent/autopilot-on/SKILL.md +38 -109
- package/pipeline/commands/multi-agent/channels/SKILL.md +38 -167
- package/pipeline/commands/multi-agent/complaint-analysis/SKILL.md +37 -144
- package/pipeline/commands/multi-agent/design-check/SKILL.md +27 -131
- package/pipeline/commands/multi-agent/garbage-collect/SKILL.md +22 -48
- package/pipeline/commands/multi-agent/ios-coding-standard/SKILL.md +37 -180
- package/pipeline/commands/multi-agent/jira/SKILL.md +16 -46
- package/pipeline/commands/multi-agent/manual-test/SKILL.md +12 -7
- package/pipeline/commands/multi-agent/refactor/SKILL.md +23 -184
- package/pipeline/commands/multi-agent/resume/SKILL.md +30 -136
- package/pipeline/commands/multi-agent/review/SKILL.md +24 -199
- package/pipeline/commands/multi-agent/setup/SKILL.md +25 -181
- package/pipeline/commands/multi-agent/stack/SKILL.md +9 -53
- package/pipeline/commands/multi-agent/status/SKILL.md +13 -2
- package/pipeline/commands/multi-agent/store-ready/SKILL.md +27 -226
- package/pipeline/commands/multi-agent/sync/SKILL.md +35 -164
- package/pipeline/commands/multi-agent/test-gen/SKILL.md +2 -4
- package/pipeline/commands/multi-agent/update/SKILL.md +18 -60
- package/pipeline/contract/CHANGELOG.md +9 -0
- package/pipeline/contract/fixtures/error-invalid-request.json +1 -1
- package/pipeline/contract/fixtures/error-unauthorized.json +1 -1
- package/pipeline/contract/fixtures/error-unsigned.json +1 -1
- package/pipeline/contract/fixtures/runs-awaiting-question.json +1 -1
- package/pipeline/contract/fixtures/runs-empty.json +1 -1
- package/pipeline/contract/fixtures/runs-failed.json +1 -1
- package/pipeline/contract/fixtures/runs-pr-opened-redacted.json +1 -1
- package/pipeline/contract/fixtures/runs-pr-opened.json +1 -1
- package/pipeline/contract/fixtures/runs-running.json +1 -1
- package/pipeline/contract/manifest.json +5 -5
- package/pipeline/contract/types/index.d.ts +3 -2
- package/pipeline/multi-agent-refs/audit-guide.md +20 -0
- package/pipeline/multi-agent-refs/autopilot-on/details.md +148 -0
- package/pipeline/multi-agent-refs/channels/generator.md +14 -0
- package/pipeline/multi-agent-refs/channels/preview.md +13 -0
- package/pipeline/multi-agent-refs/channels/reference.md +46 -0
- package/pipeline/multi-agent-refs/complaint-analysis/phases.md +159 -0
- package/pipeline/multi-agent-refs/design-check/export.md +1 -0
- package/pipeline/multi-agent-refs/design-check/init-inventory.md +1 -1
- package/pipeline/multi-agent-refs/design-check/scope-and-ledger.md +64 -0
- package/pipeline/multi-agent-refs/features/analysis-command-notes.md +53 -0
- package/pipeline/multi-agent-refs/features/commit-multi-repo.md +63 -0
- package/pipeline/multi-agent-refs/features/dev-multi-repo.md +51 -0
- package/pipeline/multi-agent-refs/features/test-gap.md +40 -0
- package/pipeline/multi-agent-refs/features/worktree-finalize.md +1 -1
- package/pipeline/multi-agent-refs/garbage-collect/phases.md +60 -0
- package/pipeline/multi-agent-refs/ios-coding-standard/plan.md +71 -0
- package/pipeline/multi-agent-refs/ios-coding-standard/resolve-and-scan.md +135 -0
- package/pipeline/multi-agent-refs/jira/picker-detail.md +71 -0
- package/pipeline/multi-agent-refs/orchestrator/copilot-pipeline.md +88 -0
- package/pipeline/multi-agent-refs/orchestrator/dispatcher.md +96 -1
- package/pipeline/multi-agent-refs/orchestrator/phase-3-user-test.md +12 -9
- package/pipeline/multi-agent-refs/phases/phase-1-plan.md +4 -4
- package/pipeline/multi-agent-refs/phases/phase-2-dev.md +8 -47
- package/pipeline/multi-agent-refs/phases/phase-3-review.md +21 -65
- package/pipeline/multi-agent-refs/phases/phase-4-commit.md +9 -59
- package/pipeline/multi-agent-refs/phases/phase-5-report.md +0 -31
- package/pipeline/multi-agent-refs/refactor/sweep.md +190 -0
- package/pipeline/multi-agent-refs/resume/details.md +115 -2
- package/pipeline/multi-agent-refs/review/inputs.md +33 -1
- package/pipeline/multi-agent-refs/review/module-guides.md +9 -1
- package/pipeline/multi-agent-refs/review/panel.md +75 -0
- package/pipeline/multi-agent-refs/review/valven.md +5 -1
- package/pipeline/multi-agent-refs/rules.md +1 -1
- package/pipeline/multi-agent-refs/setup/hooks-and-plugins.md +4 -0
- package/pipeline/multi-agent-refs/setup/token-save-flow.md +13 -0
- package/pipeline/multi-agent-refs/stack/background.md +72 -0
- package/pipeline/multi-agent-refs/store-ready/gates.md +139 -0
- package/pipeline/multi-agent-refs/store-ready/report.md +40 -2
- package/pipeline/multi-agent-refs/sync/office.md +10 -0
- package/pipeline/multi-agent-refs/sync/overview.md +61 -0
- package/pipeline/multi-agent-refs/sync/repo.md +91 -0
- package/pipeline/multi-agent-refs/update/details.md +83 -0
- package/pipeline/office/index.html +6 -3
- package/pipeline/office/toolkit.json +1 -1
- package/pipeline/rules/figma-pipeline.md +6 -3
- package/pipeline/schemas/prefs.schema.json +1 -1
- package/pipeline/schemas/runs-index.schema.json +2 -1
- package/pipeline/scripts/_memory-policy.mjs +27 -5
- package/pipeline/scripts/checkpoint-fold.sh +59 -0
- package/pipeline/scripts/contract-server.mjs +1 -1
- package/pipeline/scripts/gate-ledger.mjs +1 -1
- package/pipeline/scripts/office-control.mjs +41 -15
- package/pipeline/scripts/offload-ref.sh +1 -1
- package/pipeline/scripts/rework-rulings.mjs +5 -3
- package/pipeline/scripts/runs-index.mjs +34 -7
- package/pipeline/scripts/scope-check-gate.mjs +15 -2
- package/pipeline/scripts/status-overview.mjs +401 -0
- package/pipeline/scripts/user-test-handoff.sh +203 -0
- package/pipeline/scripts/validate-planning.mjs +5 -3
- package/pipeline/scripts/validate-triage.mjs +2 -1
- package/pipeline/scripts/write-state.mjs +13 -4
- package/pipeline/skills/.skill-manifest.json +64 -64
- package/pipeline/skills/shared/core/apple-archive-compliance/SKILL.md +7 -70
- package/pipeline/skills/shared/core/apple-archive-compliance/references/examples.md +67 -0
- package/pipeline/skills/shared/core/apple-archive-compliance/references/version-history.md +8 -0
- package/pipeline/skills/shared/core/google-play-compliance/SKILL.md +10 -72
- package/pipeline/skills/shared/core/google-play-compliance/references/examples.md +69 -0
- package/pipeline/skills/shared/core/google-play-compliance/references/notes.md +7 -0
- package/pipeline/skills/shared/core/google-play-compliance/references/version-history.md +5 -0
- package/pipeline/skills/shared/core/multi-agent/SKILL.md +39 -262
- package/pipeline/skills/shared/core/multi-agent-autopilot-on/SKILL.md +35 -73
- package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +37 -337
- package/pipeline/skills/shared/core/multi-agent-design-check/SKILL.md +27 -122
- package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +8 -340
- package/pipeline/skills/shared/core/multi-agent-ios-coding-standard/SKILL.md +37 -180
- package/pipeline/skills/shared/core/multi-agent-manual-test/SKILL.md +12 -7
- package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +23 -184
- package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +14 -82
- package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +25 -277
- package/pipeline/skills/shared/core/multi-agent-status/SKILL.md +13 -2
- package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +73 -217
- package/pipeline/skills/shared/external/alarmkit/SKILL.md +11 -162
- package/pipeline/skills/shared/external/alarmkit/references/alarmkit-code.md +257 -0
- package/pipeline/skills/shared/external/android-architecture/SKILL.md +7 -58
- package/pipeline/skills/shared/external/android-architecture/references/code-examples.md +68 -0
- package/pipeline/skills/shared/external/app-intents/SKILL.md +3 -45
- package/pipeline/skills/shared/external/app-intents/references/code-examples.md +54 -0
- package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +5 -81
- package/pipeline/skills/shared/external/app-store-optimization/references/engagement-and-localization.md +96 -0
- package/pipeline/skills/shared/external/app-store-review/SKILL.md +6 -112
- package/pipeline/skills/shared/external/app-store-review/references/monetization-and-submission.md +138 -0
- package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +10 -117
- package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models-code.md +186 -0
- package/pipeline/skills/shared/external/authentication/SKILL.md +3 -50
- package/pipeline/skills/shared/external/authentication/references/code-examples.md +59 -0
- package/pipeline/skills/shared/external/callkit-voip/SKILL.md +3 -84
- package/pipeline/skills/shared/external/callkit-voip/references/code-examples.md +93 -0
- package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +7 -263
- package/pipeline/skills/shared/external/ci-cd-pipelines/references/pipeline-examples.md +281 -0
- package/pipeline/skills/shared/external/clean-code/SKILL.md +8 -41
- package/pipeline/skills/shared/external/clean-code/references/code-examples.md +56 -0
- package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +8 -146
- package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-code.md +214 -0
- package/pipeline/skills/shared/external/compose-components/SKILL.md +6 -80
- package/pipeline/skills/shared/external/compose-components/references/code-examples.md +89 -0
- package/pipeline/skills/shared/external/compose-navigation/SKILL.md +5 -64
- package/pipeline/skills/shared/external/compose-navigation/references/code-examples.md +70 -0
- package/pipeline/skills/shared/external/core-data/SKILL.md +9 -157
- package/pipeline/skills/shared/external/core-data/references/core-data-code.md +221 -0
- package/pipeline/skills/shared/external/core-nfc/SKILL.md +3 -89
- package/pipeline/skills/shared/external/core-nfc/references/code-examples.md +98 -0
- package/pipeline/skills/shared/external/coreml/SKILL.md +17 -133
- package/pipeline/skills/shared/external/coreml/references/coreml-code.md +208 -0
- package/pipeline/skills/shared/external/css-modern/SKILL.md +8 -131
- package/pipeline/skills/shared/external/css-modern/references/code-examples.md +142 -0
- package/pipeline/skills/shared/external/database-patterns/SKILL.md +6 -103
- package/pipeline/skills/shared/external/database-patterns/references/orm-examples.md +112 -0
- package/pipeline/skills/shared/external/html-semantic/SKILL.md +7 -48
- package/pipeline/skills/shared/external/html-semantic/references/code-examples.md +54 -0
- package/pipeline/skills/shared/external/humanizer/SKILL.md +6 -19
- package/pipeline/skills/shared/external/humanizer/references/voice.md +24 -0
- package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +13 -170
- package/pipeline/skills/shared/external/ios-accessibility/references/assistive-tech-review.md +224 -0
- package/pipeline/skills/shared/external/ios-localization/SKILL.md +2 -24
- package/pipeline/skills/shared/external/ios-localization/references/code-examples.md +30 -0
- package/pipeline/skills/shared/external/ios-networking/SKILL.md +3 -58
- package/pipeline/skills/shared/external/ios-networking/references/code-examples.md +67 -0
- package/pipeline/skills/shared/external/ios-security/SKILL.md +4 -64
- package/pipeline/skills/shared/external/ios-security/references/code-examples.md +74 -0
- package/pipeline/skills/shared/external/live-activities/SKILL.md +4 -90
- package/pipeline/skills/shared/external/live-activities/references/code-examples.md +108 -0
- package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +9 -23
- package/pipeline/skills/shared/external/localization-reuse-map/references/project-settings.md +22 -0
- package/pipeline/skills/shared/external/mapkit-location/SKILL.md +5 -95
- package/pipeline/skills/shared/external/mapkit-location/references/code-examples.md +117 -0
- package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +7 -106
- package/pipeline/skills/shared/external/nextjs-app-router/references/app-router-examples.md +124 -0
- package/pipeline/skills/shared/external/permissionkit/SKILL.md +2 -31
- package/pipeline/skills/shared/external/permissionkit/references/code-examples.md +37 -0
- package/pipeline/skills/shared/external/play-store-review/SKILL.md +6 -74
- package/pipeline/skills/shared/external/play-store-review/references/signing-and-policies.md +83 -0
- package/pipeline/skills/shared/external/push-notifications/SKILL.md +8 -125
- package/pipeline/skills/shared/external/push-notifications/references/notification-code.md +176 -0
- package/pipeline/skills/shared/external/python-patterns/SKILL.md +7 -158
- package/pipeline/skills/shared/external/python-patterns/references/python-examples.md +176 -0
- package/pipeline/skills/shared/external/rest-api-design/SKILL.md +7 -157
- package/pipeline/skills/shared/external/rest-api-design/references/api-examples.md +175 -0
- package/pipeline/skills/shared/external/swift-architecture/SKILL.md +11 -230
- package/pipeline/skills/shared/external/swift-architecture/references/pattern-examples.md +295 -0
- package/pipeline/skills/shared/external/swift-codable/SKILL.md +17 -149
- package/pipeline/skills/shared/external/swift-codable/references/codable-recipes.md +207 -0
- package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +12 -99
- package/pipeline/skills/shared/external/swift-concurrency/references/code-examples.md +100 -0
- package/pipeline/skills/shared/external/swift-concurrency/references/swift-6-2-additions.md +18 -0
- package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +9 -78
- package/pipeline/skills/shared/external/swift-formatstyle/references/formatstyle-examples.md +113 -0
- package/pipeline/skills/shared/external/swift-language/SKILL.md +3 -56
- package/pipeline/skills/shared/external/swift-language/references/code-examples.md +65 -0
- package/pipeline/skills/shared/external/swift-testing-pro/SKILL.md +1 -0
- package/pipeline/skills/shared/external/swiftdata/SKILL.md +6 -122
- package/pipeline/skills/shared/external/swiftdata/references/code-examples.md +140 -0
- package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +12 -139
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/interop-code.md +198 -0
- package/pipeline/skills/shared/external/tailwind-css/SKILL.md +9 -81
- package/pipeline/skills/shared/external/tailwind-css/references/code-examples.md +91 -0
- package/pipeline/skills/shared/external/testing-backend/SKILL.md +7 -207
- package/pipeline/skills/shared/external/testing-backend/references/testing-examples.md +225 -0
- package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +8 -89
- package/pipeline/skills/shared/external/typescript-patterns/references/code-examples.md +100 -0
- package/pipeline/skills/shared/external/vision-framework/SKILL.md +2 -20
- package/pipeline/skills/shared/external/vision-framework/references/code-examples.md +26 -0
- package/pipeline/skills/shared/external/vue-composition/SKILL.md +7 -169
- package/pipeline/skills/shared/external/vue-composition/references/vue-examples.md +187 -0
- package/pipeline/skills/shared/external/web-accessibility/SKILL.md +7 -174
- package/pipeline/skills/shared/external/web-accessibility/references/a11y-examples.md +192 -0
- package/pipeline/skills/shared/external/web-performance/SKILL.md +8 -66
- package/pipeline/skills/shared/external/web-performance/references/code-examples.md +77 -0
- package/pipeline/skills/shared/external/web-testing/SKILL.md +11 -186
- package/pipeline/skills/shared/external/web-testing/references/testing-examples.md +213 -0
- /package/pipeline/skills/shared/external/localization-reuse-map/{reference → references}/format-and-output.md +0 -0
- /package/pipeline/skills/shared/external/localization-reuse-map/{reference → references}/publish-and-snapshot.md +0 -0
- /package/pipeline/skills/shared/external/localization-reuse-map/{reference → references}/sources-and-recipes.md +0 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Reviews, events and localized metadata
|
|
2
|
+
|
|
3
|
+
In-app review prompts, In-App Events, ratings and review management, and localized metadata. SKILL.md keeps metadata fields, screenshots, custom pages, product page tests and the review checklist.
|
|
4
|
+
|
|
5
|
+
## Asking for reviews in the app
|
|
6
|
+
|
|
7
|
+
Use the SwiftUI environment value `RequestReviewAction` or, from UIKit,
|
|
8
|
+
`AppStore.requestReview(in:)`. The full StoreKit surface is covered in
|
|
9
|
+
`storekit`.
|
|
10
|
+
|
|
11
|
+
```swift
|
|
12
|
+
import StoreKit
|
|
13
|
+
import SwiftUI
|
|
14
|
+
|
|
15
|
+
struct TripSummaryView: View {
|
|
16
|
+
@Environment(\.requestReview) private var requestReview
|
|
17
|
+
let completedTrips: Int
|
|
18
|
+
|
|
19
|
+
var body: some View {
|
|
20
|
+
TripSummaryContent()
|
|
21
|
+
.onAppear {
|
|
22
|
+
if completedTrips == 5 { requestReview() }
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- The system shows the prompt at most three times in 365 days per device for
|
|
29
|
+
someone who has not rated the app.
|
|
30
|
+
- Calling the API is a request; StoreKit decides whether anything appears.
|
|
31
|
+
- Development builds always show it; TestFlight builds never do.
|
|
32
|
+
- Good moments: a meaningful task just finished, a milestone or streak, a
|
|
33
|
+
visible success, several active sessions.
|
|
34
|
+
- Bad moments: the very first launch, the onboarding flow, any error or crash,
|
|
35
|
+
a purchase that failed, or directly after a button tap.
|
|
36
|
+
- Do not put a "Do you like this app?" dialog in front of the system prompt.
|
|
37
|
+
Apple discourages intercepting it and may reject apps that do.
|
|
38
|
+
|
|
39
|
+
For a permanent "Write a review" row in settings, open
|
|
40
|
+
`https://apps.apple.com/app/id{APP_ID}?action=write-review`. It goes straight
|
|
41
|
+
to the review sheet and does not count against the three-per-year limit.
|
|
42
|
+
|
|
43
|
+
## In-App Events
|
|
44
|
+
|
|
45
|
+
Events are shown in search, on Today and in recommendations tailored to
|
|
46
|
+
each user. They raise visibility while they run and can bring lapsed
|
|
47
|
+
users back.
|
|
48
|
+
|
|
49
|
+
- Badges (seven): Challenge, Competition, Live Event, Major Update, New
|
|
50
|
+
Season, Premiere, Special Event. Pick the one that matches what actually happens in
|
|
51
|
+
the app, and never create an event without real time-bound content.
|
|
52
|
+
- Text limits in characters: 30 for the name, 50 for the short description,
|
|
53
|
+
120 for the long one.
|
|
54
|
+
- Media: an event card image or video at 16:9 (1920 x 1080) and an event
|
|
55
|
+
details page image or video at 9:16 (1080 x 1920).
|
|
56
|
+
- Time them with feature releases, seasonal moments and content drops.
|
|
57
|
+
- Write the name and short description for someone scanning search results;
|
|
58
|
+
they appear on the event cards in Search and Today.
|
|
59
|
+
- The card is shown on the product page as well, and a well-timed card lifts
|
|
60
|
+
tap-through.
|
|
61
|
+
- Line events up so a new one starts as the previous one ends, keeping a card
|
|
62
|
+
in search at all times.
|
|
63
|
+
|
|
64
|
+
## Ratings and reviews
|
|
65
|
+
|
|
66
|
+
Star ratings and written reviews are visible on the product page and in
|
|
67
|
+
search, and they move both ranking and conversion.
|
|
68
|
+
|
|
69
|
+
- Earn more recent positive reviews: prompt after successes and answer
|
|
70
|
+
complaints constructively.
|
|
71
|
+
- Answer critical reviews from App Store Connect. A calm, specific reply
|
|
72
|
+
improves how the app looks even when the rating does not change: acknowledge
|
|
73
|
+
the problem, say what is fixed or in progress, keep the tone neutral.
|
|
74
|
+
- Read reviews as research into what users want, what frustrates them and the
|
|
75
|
+
words they use, then feed that into metadata and captions.
|
|
76
|
+
- Submitting a new version offers the option of resetting the summary rating. Do it only
|
|
77
|
+
when the shown rating is far below current quality after major fixes. Keep a
|
|
78
|
+
good rating that reflects the app fairly, skip the reset for routine fixes, and after
|
|
79
|
+
a risky redesign wait until it has settled.
|
|
80
|
+
|
|
81
|
+
## Localized Metadata Optimization
|
|
82
|
+
|
|
83
|
+
A localized listing is a separate job from translating the app's screens.
|
|
84
|
+
Keywords, descriptions and captions are researched and written per market.
|
|
85
|
+
|
|
86
|
+
- Research keywords in each market. The term people use to find a photo editor
|
|
87
|
+
in Japanese is not a word-for-word translation of the English one.
|
|
88
|
+
- Rewrite the description per locale, adapting opening lines, features, proof
|
|
89
|
+
and close to local expectations.
|
|
90
|
+
- Localize every surface (description, keywords, previews, screenshots), and do
|
|
91
|
+
not count on literal translations or on one locale's keywords being indexed
|
|
92
|
+
elsewhere.
|
|
93
|
+
- Caption screenshots in the market's language; native captions convert better
|
|
94
|
+
than English ones.
|
|
95
|
+
- Localizing strings inside the app (String Catalogs, `FormatStyle`,
|
|
96
|
+
right-to-left layout) is covered by `ios-localization`.
|
|
@@ -177,42 +177,7 @@ Codes, plist layout and SDK rules: [privacy manifest reference](references/priva
|
|
|
177
177
|
|
|
178
178
|
## 3.1.1 Paying for digital things
|
|
179
179
|
|
|
180
|
-
|
|
181
|
-
service, the sale normally runs through Apple IAP, unless a guideline exception, a regional rule or
|
|
182
|
-
an approved entitlement says otherwise.
|
|
183
|
-
|
|
184
|
-
| Needs IAP | Does not need IAP |
|
|
185
|
-
|---|---|
|
|
186
|
-
| Unlocking premium features | Physical goods |
|
|
187
|
-
| Subscriptions to app functionality | Real-world services such as rides or food delivery |
|
|
188
|
-
| Virtual currency | Person-to-person services, for example a live tutor or consultant |
|
|
189
|
-
| Removing ads | Business apps for organizations, distributed as custom apps via Apple Business Manager |
|
|
190
|
-
| Digital tips to creators | Donations to approved nonprofits (see 3.2.1 and 3.2.2) |
|
|
191
|
-
|
|
192
|
-
Rules around the purchase:
|
|
193
|
-
|
|
194
|
-
- Before a subscription is bought, the paywall states what it costs, how long a
|
|
195
|
-
period lasts and that it renews on its own.
|
|
196
|
-
- For a free trial, show the trial length, the price after it, how often billing
|
|
197
|
-
happens, that it renews automatically, and how to cancel, all before purchase.
|
|
198
|
-
- Strip any route to an outside checkout for digital goods, whether a link, a
|
|
199
|
-
button or a nudge in copy, unless the storefront's current rule or a granted
|
|
200
|
-
entitlement permits it. A StoreKit External Purchase Link entitlement or,
|
|
201
|
-
where permitted, a Music Streaming Services entitlement allows a link to a
|
|
202
|
-
permitted destination; the US storefront needs no entitlement. These rules differ by region and have changed recently; read the
|
|
203
|
-
current 3.1.1(a) and 3.1.3 text for the target storefront.
|
|
204
|
-
- Reader apps may link out to account sign-up with the matching entitlement, but
|
|
205
|
-
may not offer a way around IAP for in-app purchases.
|
|
206
|
-
|
|
207
|
-
StoreKit checks:
|
|
208
|
-
|
|
209
|
-
- Products are typed correctly in App Store Connect (consumable, non-consumable,
|
|
210
|
-
subscription).
|
|
211
|
-
- A Restore Purchases control exists and works.
|
|
212
|
-
- Entitlements are verified with StoreKit 2 `Transaction.currentEntitlements` or
|
|
213
|
-
on the server.
|
|
214
|
-
- A purchase that is interrupted, or deferred while a parent approves it through
|
|
215
|
-
Ask to Buy, leaves the UI in a sane state.
|
|
180
|
+
Unlocking digital content, features, subscriptions, virtual currency or ad removal goes through IAP unless a guideline exception, regional rule or entitlement says otherwise; physical goods and real-world services do not. The paywall must disclose price, period, renewal and trial terms before purchase, and outside checkout links need a storefront rule or entitlement. Tables, StoreKit checks and regional notes: [Monetization, submission, metadata and appeals](references/monetization-and-submission.md).
|
|
216
181
|
|
|
217
182
|
## HIG items App Review looks at
|
|
218
183
|
|
|
@@ -272,91 +237,19 @@ behind another system permission alert.
|
|
|
272
237
|
|
|
273
238
|
## Entitlements and usage strings
|
|
274
239
|
|
|
275
|
-
Every entitlement needs a reason
|
|
276
|
-
|
|
277
|
-
| Capability | What review expects |
|
|
278
|
-
|---|---|
|
|
279
|
-
| Camera | a clear `NSCameraUsageDescription` |
|
|
280
|
-
| Location (Always) | a visible reason the user benefits from background location |
|
|
281
|
-
| Push notifications | no marketing pushes without the user's opt-in |
|
|
282
|
-
| HealthKit | health data used in a meaningful feature |
|
|
283
|
-
| Background Modes | every declared mode (audio, location, VoIP, fetch) has a feature that uses it |
|
|
284
|
-
| App Groups | the shared data is explained |
|
|
285
|
-
| Associated Domains | universal links resolve and open the app |
|
|
286
|
-
|
|
287
|
-
A usage string names the data and the user-facing reason:
|
|
288
|
-
|
|
289
|
-
| Verdict | String |
|
|
290
|
-
|---|---|
|
|
291
|
-
| Approved | "We use where you are to place the closest charging stations on the map." |
|
|
292
|
-
| Approved | "The camera scans a book's barcode so you can add it to your shelf." |
|
|
293
|
-
| Rejected | "This app requires camera access." |
|
|
294
|
-
| Rejected | "We use your photo library to improve your experience." |
|
|
295
|
-
| Fixed | "Pick a photo from your library to use as your profile picture. Only the photo you choose is uploaded." |
|
|
296
|
-
|
|
297
|
-
The second rejected string names a data type but gives no concrete purpose;
|
|
298
|
-
"improve your experience" is the phrase review flags. The fixed version says
|
|
299
|
-
which feature uses the data and what leaves the device.
|
|
240
|
+
Every entitlement needs a reason review can see in the product, and every usage string names the data and the user-facing reason ("improve your experience" is rejected). Capability table and approved versus rejected strings: [Monetization, submission, metadata and appeals](references/monetization-and-submission.md).
|
|
300
241
|
|
|
301
242
|
## Submission workflow
|
|
302
243
|
|
|
303
|
-
|
|
304
|
-
Release build. Aim for zero warnings; it is good hygiene, not a review rule.
|
|
305
|
-
2. Upload: in Organizer choose Distribute App, then App Store Connect; or run
|
|
306
|
-
`xcodebuild -exportArchive`. `altool` and Transporter also work.
|
|
307
|
-
3. Internal TestFlight: internal testers see the build minutes after processing.
|
|
308
|
-
Try every flow on two or more screen sizes.
|
|
309
|
-
4. External TestFlight: the first build sent to an external group goes through
|
|
310
|
-
Beta App Review.
|
|
311
|
-
5. Submit: pick the build, complete metadata, attach screenshots, press Submit
|
|
312
|
-
for Review. Review time varies, so keep slack before a deadline.
|
|
313
|
-
|
|
314
|
-
Expedited review is for a critical fix for existing users, a date-bound event
|
|
315
|
-
(a holiday launch, a legal deadline) or a security patch. Ask through Contact
|
|
316
|
-
Us > App Review > Expedite Request with a specific, factual reason. It is not for
|
|
317
|
-
first launches or new features.
|
|
318
|
-
|
|
319
|
-
Phased release for automatic updates: day 1 1%, day 2 2%, day 3 5%, day 4 10%,
|
|
320
|
-
day 5 20%, day 6 50%, day 7 100%. Users who check for updates by hand get the
|
|
321
|
-
build immediately. The rollout can be paused, resumed or finished early at any
|
|
322
|
-
time.
|
|
244
|
+
Archive a clean Release build, upload, test on internal then external TestFlight, then submit. Expedited review is only for critical fixes, date-bound events or security patches. Steps and the phased-release schedule: [Monetization, submission, metadata and appeals](references/monetization-and-submission.md).
|
|
323
245
|
|
|
324
246
|
## Metadata rules
|
|
325
247
|
|
|
326
|
-
|
|
327
|
-
A bare category word such as "Photo Editor" is likely rejected; so are
|
|
328
|
-
competitor or trademarked terms and prices. The name must be unique.
|
|
329
|
-
- Screenshots: 1 to 10 per required platform and localization. The
|
|
330
|
-
6.9-inch iPhone set is the primary one; the 6.5-inch set is required only
|
|
331
|
-
when there is no 6.9-inch set, and smaller iPhones get scaled images. Apps that
|
|
332
|
-
run on iPad need 13-inch iPad screenshots; smaller iPads are scaled.
|
|
333
|
-
- Screenshot content: the real UI; never show a feature the build lacks. Captions and
|
|
334
|
-
frames are fine if they neither hide nor misstate the UI. Localized sets show
|
|
335
|
-
the localized UI.
|
|
336
|
-
- Keywords: 100 characters, comma-separated with no spaces. Words already in the
|
|
337
|
-
name or subtitle are indexed, so do not repeat them. Use singular or plural,
|
|
338
|
-
not both. No competitor, trademark or unrelated terms.
|
|
339
|
-
- App previews: up to 30 seconds, up to 3 per localization, captured from the app
|
|
340
|
-
on a device with the app's own audio (narration or music optional). No
|
|
341
|
-
misleading framing and no footage of hands holding a device. The first frame
|
|
342
|
-
is the poster frame.
|
|
248
|
+
Name and subtitle 30 characters each, keywords 100 characters, screenshots and previews show the real UI. Screenshot sets, keyword and preview limits: [Monetization, submission, metadata and appeals](references/monetization-and-submission.md).
|
|
343
249
|
|
|
344
250
|
## Rejections and appeals
|
|
345
251
|
|
|
346
|
-
|
|
347
|
-
- Reply in that thread with facts. If you fixed the issue, say what changed and
|
|
348
|
-
upload a new binary. If you disagree, show how the app complies, quoting the
|
|
349
|
-
guideline.
|
|
350
|
-
- Keep it professional, specific and short. Attach demo credentials, screenshots
|
|
351
|
-
or a screen recording. No emotional language, no threats.
|
|
352
|
-
- For a formal appeal, go to the App Review Board through the Resolution Center or
|
|
353
|
-
Contact Us > App Review > Appeal. A separate team reads the whole history. The
|
|
354
|
-
ruling is final for that build; a changed build can still be submitted.
|
|
355
|
-
|
|
356
|
-
What tends to work: a video walkthrough of the flagged feature, a point-by-point
|
|
357
|
-
answer against the guideline text, fresh demo credentials (the usual 2.1 cause),
|
|
358
|
-
a polite reference to comparable approved behaviour, and offering an alternative
|
|
359
|
-
implementation.
|
|
252
|
+
Reply in the Resolution Center thread with facts: what changed, or how the app complies with the quoted guideline, plus demo credentials or a recording. Formal appeals go to the App Review Board. Full steps and what tends to work: [Monetization, submission, metadata and appeals](references/monetization-and-submission.md).
|
|
360
253
|
|
|
361
254
|
## Common mistakes
|
|
362
255
|
|
|
@@ -396,6 +289,7 @@ Full lists: [review checklists](references/review-checklists.md).
|
|
|
396
289
|
|
|
397
290
|
## References
|
|
398
291
|
|
|
292
|
+
- [Monetization, submission, metadata and appeals](references/monetization-and-submission.md): IAP versus external purchase rules, entitlement and usage-string expectations, the archive-to-release workflow (expedited review, phased release), and name, screenshot, keyword and preview limits. Also replying to a rejection and filing an appeal.
|
|
399
293
|
- Guidelines text: https://developer.apple.com/app-store/review/guidelines/
|
|
400
294
|
- SDK and Xcode deadlines: https://developer.apple.com/news/upcoming-requirements/
|
|
401
295
|
- Screenshot sizes: https://developer.apple.com/help/app-store-connect/reference/screenshot-specifications/
|
package/pipeline/skills/shared/external/app-store-review/references/monetization-and-submission.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Monetization, submission, metadata and appeals
|
|
2
|
+
|
|
3
|
+
<!-- toc -->
|
|
4
|
+
- [3.1.1 Paying for digital things](#311-paying-for-digital-things)
|
|
5
|
+
- [Entitlements and usage strings](#entitlements-and-usage-strings)
|
|
6
|
+
- [Submission workflow](#submission-workflow)
|
|
7
|
+
- [Metadata rules](#metadata-rules)
|
|
8
|
+
- [Rejections and appeals](#rejections-and-appeals)
|
|
9
|
+
<!-- /toc -->
|
|
10
|
+
|
|
11
|
+
The 3.1.1 purchase rules, entitlement and usage-string expectations, the submission workflow, metadata limits, and handling rejections and appeals. SKILL.md keeps triage, the guidelines that cause most rejections and the review checklist.
|
|
12
|
+
|
|
13
|
+
## 3.1.1 Paying for digital things
|
|
14
|
+
|
|
15
|
+
When the app unlocks digital content, a feature, a subscription or a digital
|
|
16
|
+
service, the sale normally runs through Apple IAP, unless a guideline exception, a regional rule or
|
|
17
|
+
an approved entitlement says otherwise.
|
|
18
|
+
|
|
19
|
+
| Needs IAP | Does not need IAP |
|
|
20
|
+
|---|---|
|
|
21
|
+
| Unlocking premium features | Physical goods |
|
|
22
|
+
| Subscriptions to app functionality | Real-world services such as rides or food delivery |
|
|
23
|
+
| Virtual currency | Person-to-person services, for example a live tutor or consultant |
|
|
24
|
+
| Removing ads | Business apps for organizations, distributed as custom apps via Apple Business Manager |
|
|
25
|
+
| Digital tips to creators | Donations to approved nonprofits (see 3.2.1 and 3.2.2) |
|
|
26
|
+
|
|
27
|
+
Rules around the purchase:
|
|
28
|
+
|
|
29
|
+
- Before a subscription is bought, the paywall states what it costs, how long a
|
|
30
|
+
period lasts and that it renews on its own.
|
|
31
|
+
- For a free trial, show the trial length, the price after it, how often billing
|
|
32
|
+
happens, that it renews automatically, and how to cancel, all before purchase.
|
|
33
|
+
- Strip any route to an outside checkout for digital goods, whether a link, a
|
|
34
|
+
button or a nudge in copy, unless the storefront's current rule or a granted
|
|
35
|
+
entitlement permits it. A StoreKit External Purchase Link entitlement or,
|
|
36
|
+
where permitted, a Music Streaming Services entitlement allows a link to a
|
|
37
|
+
permitted destination; the US storefront needs no entitlement. These rules differ by region and have changed recently; read the
|
|
38
|
+
current 3.1.1(a) and 3.1.3 text for the target storefront.
|
|
39
|
+
- Reader apps may link out to account sign-up with the matching entitlement, but
|
|
40
|
+
may not offer a way around IAP for in-app purchases.
|
|
41
|
+
|
|
42
|
+
StoreKit checks:
|
|
43
|
+
|
|
44
|
+
- Products are typed correctly in App Store Connect (consumable, non-consumable,
|
|
45
|
+
subscription).
|
|
46
|
+
- A Restore Purchases control exists and works.
|
|
47
|
+
- Entitlements are verified with StoreKit 2 `Transaction.currentEntitlements` or
|
|
48
|
+
on the server.
|
|
49
|
+
- A purchase that is interrupted, or deferred while a parent approves it through
|
|
50
|
+
Ask to Buy, leaves the UI in a sane state.
|
|
51
|
+
|
|
52
|
+
## Entitlements and usage strings
|
|
53
|
+
|
|
54
|
+
Every entitlement needs a reason App Review can see in the product.
|
|
55
|
+
|
|
56
|
+
| Capability | What review expects |
|
|
57
|
+
|---|---|
|
|
58
|
+
| Camera | a clear `NSCameraUsageDescription` |
|
|
59
|
+
| Location (Always) | a visible reason the user benefits from background location |
|
|
60
|
+
| Push notifications | no marketing pushes without the user's opt-in |
|
|
61
|
+
| HealthKit | health data used in a meaningful feature |
|
|
62
|
+
| Background Modes | every declared mode (audio, location, VoIP, fetch) has a feature that uses it |
|
|
63
|
+
| App Groups | the shared data is explained |
|
|
64
|
+
| Associated Domains | universal links resolve and open the app |
|
|
65
|
+
|
|
66
|
+
A usage string names the data and the user-facing reason:
|
|
67
|
+
|
|
68
|
+
| Verdict | String |
|
|
69
|
+
|---|---|
|
|
70
|
+
| Approved | "We use where you are to place the closest charging stations on the map." |
|
|
71
|
+
| Approved | "The camera scans a book's barcode so you can add it to your shelf." |
|
|
72
|
+
| Rejected | "This app requires camera access." |
|
|
73
|
+
| Rejected | "We use your photo library to improve your experience." |
|
|
74
|
+
| Fixed | "Pick a photo from your library to use as your profile picture. Only the photo you choose is uploaded." |
|
|
75
|
+
|
|
76
|
+
The second rejected string names a data type but gives no concrete purpose;
|
|
77
|
+
"improve your experience" is the phrase review flags. The fixed version says
|
|
78
|
+
which feature uses the data and what leaves the device.
|
|
79
|
+
|
|
80
|
+
## Submission workflow
|
|
81
|
+
|
|
82
|
+
1. Archive: Product > Archive with a Distribution signing identity, from a clean
|
|
83
|
+
Release build. Aim for zero warnings; it is good hygiene, not a review rule.
|
|
84
|
+
2. Upload: in Organizer choose Distribute App, then App Store Connect; or run
|
|
85
|
+
`xcodebuild -exportArchive`. `altool` and Transporter also work.
|
|
86
|
+
3. Internal TestFlight: internal testers see the build minutes after processing.
|
|
87
|
+
Try every flow on two or more screen sizes.
|
|
88
|
+
4. External TestFlight: the first build sent to an external group goes through
|
|
89
|
+
Beta App Review.
|
|
90
|
+
5. Submit: pick the build, complete metadata, attach screenshots, press Submit
|
|
91
|
+
for Review. Review time varies, so keep slack before a deadline.
|
|
92
|
+
|
|
93
|
+
Expedited review is for a critical fix for existing users, a date-bound event
|
|
94
|
+
(a holiday launch, a legal deadline) or a security patch. Ask through Contact
|
|
95
|
+
Us > App Review > Expedite Request with a specific, factual reason. It is not for
|
|
96
|
+
first launches or new features.
|
|
97
|
+
|
|
98
|
+
Phased release for automatic updates: day 1 1%, day 2 2%, day 3 5%, day 4 10%,
|
|
99
|
+
day 5 20%, day 6 50%, day 7 100%. Users who check for updates by hand get the
|
|
100
|
+
build immediately. The rollout can be paused, resumed or finished early at any
|
|
101
|
+
time.
|
|
102
|
+
|
|
103
|
+
## Metadata rules
|
|
104
|
+
|
|
105
|
+
- Name and subtitle: 30 characters each. The subtitle is a short value statement.
|
|
106
|
+
A bare category word such as "Photo Editor" is likely rejected; so are
|
|
107
|
+
competitor or trademarked terms and prices. The name must be unique.
|
|
108
|
+
- Screenshots: 1 to 10 per required platform and localization. The
|
|
109
|
+
6.9-inch iPhone set is the primary one; the 6.5-inch set is required only
|
|
110
|
+
when there is no 6.9-inch set, and smaller iPhones get scaled images. Apps that
|
|
111
|
+
run on iPad need 13-inch iPad screenshots; smaller iPads are scaled.
|
|
112
|
+
- Screenshot content: the real UI; never show a feature the build lacks. Captions and
|
|
113
|
+
frames are fine if they neither hide nor misstate the UI. Localized sets show
|
|
114
|
+
the localized UI.
|
|
115
|
+
- Keywords: 100 characters, comma-separated with no spaces. Words already in the
|
|
116
|
+
name or subtitle are indexed, so do not repeat them. Use singular or plural,
|
|
117
|
+
not both. No competitor, trademark or unrelated terms.
|
|
118
|
+
- App previews: up to 30 seconds, up to 3 per localization, captured from the app
|
|
119
|
+
on a device with the app's own audio (narration or music optional). No
|
|
120
|
+
misleading framing and no footage of hands holding a device. The first frame
|
|
121
|
+
is the poster frame.
|
|
122
|
+
|
|
123
|
+
## Rejections and appeals
|
|
124
|
+
|
|
125
|
+
- A rejection arrives in the Resolution Center with the guideline number.
|
|
126
|
+
- Reply in that thread with facts. If you fixed the issue, say what changed and
|
|
127
|
+
upload a new binary. If you disagree, show how the app complies, quoting the
|
|
128
|
+
guideline.
|
|
129
|
+
- Keep it professional, specific and short. Attach demo credentials, screenshots
|
|
130
|
+
or a screen recording. No emotional language, no threats.
|
|
131
|
+
- For a formal appeal, go to the App Review Board through the Resolution Center or
|
|
132
|
+
Contact Us > App Review > Appeal. A separate team reads the whole history. The
|
|
133
|
+
ruling is final for that build; a changed build can still be submitted.
|
|
134
|
+
|
|
135
|
+
What tends to work: a video walkthrough of the flagged feature, a point-by-point
|
|
136
|
+
answer against the guideline text, fresh demo credentials (the usual 2.1 cause),
|
|
137
|
+
a polite reference to comparable approved behaviour, and offering an alternative
|
|
138
|
+
implementation.
|
|
@@ -89,32 +89,7 @@ Facts that shape every design:
|
|
|
89
89
|
|
|
90
90
|
Every entry point checks availability and falls back without crashing.
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
import Foundation
|
|
94
|
-
import FoundationModels
|
|
95
|
-
import os
|
|
96
|
-
|
|
97
|
-
private let aiLog = Logger(subsystem: "StudyApp", category: "AI")
|
|
98
|
-
|
|
99
|
-
enum SummaryState { case ready, openSettings, downloading, unsupported }
|
|
100
|
-
|
|
101
|
-
func summaryState() -> SummaryState {
|
|
102
|
-
let model = SystemLanguageModel.default
|
|
103
|
-
switch model.availability {
|
|
104
|
-
case .available:
|
|
105
|
-
return model.supportsLocale(Locale.current) ? .ready : .unsupported
|
|
106
|
-
case .unavailable(.appleIntelligenceNotEnabled):
|
|
107
|
-
return .openSettings // point the user to Settings
|
|
108
|
-
case .unavailable(.modelNotReady):
|
|
109
|
-
return .downloading // assets still arriving; show progress
|
|
110
|
-
case .unavailable(.deviceNotEligible):
|
|
111
|
-
return .unsupported // hardware cannot run it; use a fallback
|
|
112
|
-
case .unavailable(let other):
|
|
113
|
-
aiLog.notice("Model unavailable: \(String(describing: other))")
|
|
114
|
-
return .unsupported
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
```
|
|
92
|
+
Code for this section: [Foundation Models and multi-backend code](references/foundation-models-code.md).
|
|
118
93
|
|
|
119
94
|
### Sessions
|
|
120
95
|
|
|
@@ -144,22 +119,6 @@ let resumed = LanguageModelSession(model: .default, tools: [], transcript: saved
|
|
|
144
119
|
`@Generable` builds the output schema at compile time, and the response comes
|
|
145
120
|
back as your type.
|
|
146
121
|
|
|
147
|
-
```swift
|
|
148
|
-
@Generable
|
|
149
|
-
struct StudyCard {
|
|
150
|
-
@Guide(description: "The term being studied, two to four words")
|
|
151
|
-
var term: String
|
|
152
|
-
@Guide(description: "Plain-language definitions", .count(2))
|
|
153
|
-
var definitions: [String]
|
|
154
|
-
@Guide(.range(1...5))
|
|
155
|
-
var difficulty: Int
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
let reply = try await tutor.respond(to: "Make a card for osmosis",
|
|
159
|
-
generating: StudyCard.self)
|
|
160
|
-
let card = reply.content
|
|
161
|
-
```
|
|
162
|
-
|
|
163
122
|
`@Guide` options:
|
|
164
123
|
|
|
165
124
|
| Guide | Effect |
|
|
@@ -178,38 +137,12 @@ Fields are generated in declaration order. Put the fields that others depend on
|
|
|
178
137
|
first.
|
|
179
138
|
|
|
180
139
|
Streaming gives partial values as they form; each property of
|
|
181
|
-
`StudyCard.PartiallyGenerated` is optional
|
|
140
|
+
`StudyCard.PartiallyGenerated` is optional.
|
|
182
141
|
|
|
183
|
-
|
|
184
|
-
let cardStream = tutor.streamResponse(to: "Card for diffusion", generating: StudyCard.self)
|
|
185
|
-
for try await partial in cardStream {
|
|
186
|
-
draft.term = partial.content.term ?? draft.term
|
|
187
|
-
draft.definitions = partial.content.definitions ?? draft.definitions
|
|
188
|
-
}
|
|
189
|
-
```
|
|
142
|
+
Code for this section: [Foundation Models and multi-backend code](references/foundation-models-code.md).
|
|
190
143
|
|
|
191
144
|
### Tools
|
|
192
145
|
|
|
193
|
-
```swift
|
|
194
|
-
struct GlossaryTool: Tool {
|
|
195
|
-
let name = "lookUpTerm"
|
|
196
|
-
let description = "Returns the course glossary entry for a biology term."
|
|
197
|
-
|
|
198
|
-
@Generable
|
|
199
|
-
struct Arguments {
|
|
200
|
-
@Guide(description: "Singular form of the term to look up")
|
|
201
|
-
var term: String
|
|
202
|
-
@Guide(.range(1...3))
|
|
203
|
-
var gradeLevel: Int
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
func call(arguments: Arguments) async throws -> String {
|
|
207
|
-
await Glossary.shared.entry(for: arguments.term, level: arguments.gradeLevel)
|
|
208
|
-
?? "No entry found."
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
```
|
|
212
|
-
|
|
213
146
|
- Register tools when creating the session, and only the ones the task needs.
|
|
214
147
|
- `Tool` is `Sendable`; captured state must be safe to share.
|
|
215
148
|
- Tool names, descriptions and argument schemas, like `@Generable` schemas,
|
|
@@ -218,27 +151,11 @@ struct GlossaryTool: Tool {
|
|
|
218
151
|
should be fetched beforehand and put in the prompt; keep tools for lookups
|
|
219
152
|
that depend on the conversation.
|
|
220
153
|
|
|
154
|
+
Code for this section: [Foundation Models and multi-backend code](references/foundation-models-code.md).
|
|
155
|
+
|
|
221
156
|
### Errors
|
|
222
157
|
|
|
223
|
-
|
|
224
|
-
do {
|
|
225
|
-
let answer = try await tutor.respond(to: question)
|
|
226
|
-
show(answer.content)
|
|
227
|
-
} catch let failure as LanguageModelSession.GenerationError {
|
|
228
|
-
switch failure {
|
|
229
|
-
case .exceededContextWindowSize: restartWithSummary() // too many tokens
|
|
230
|
-
case .guardrailViolation: showRephraseHint() // safety filter hit
|
|
231
|
-
case .concurrentRequests: queueUntilIdle() // session already busy
|
|
232
|
-
case .unsupportedLanguageOrLocale: showLanguageNotice()
|
|
233
|
-
case .unsupportedGuide: logSchemaProblem() // a @Guide the model cannot honour
|
|
234
|
-
case .assetsUnavailable: showDownloadingState()
|
|
235
|
-
case .refusal(let refusal, _): explain(refusal) // stream refusal.explanation
|
|
236
|
-
case .rateLimited: retryLater() // back off
|
|
237
|
-
case .decodingFailure: logSchemaProblem() // output did not fit the type
|
|
238
|
-
default: showGenericFailure()
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
```
|
|
158
|
+
Code for this section: [Foundation Models and multi-backend code](references/foundation-models-code.md).
|
|
242
159
|
|
|
243
160
|
### Generation options
|
|
244
161
|
|
|
@@ -374,46 +291,21 @@ MLX lifecycle, llama.cpp and GGUF: [the MLX and llama.cpp guide](references/mlx-
|
|
|
374
291
|
## Running several backends
|
|
375
292
|
|
|
376
293
|
Try the system model first, then a local open model, and fail clearly when
|
|
377
|
-
neither is there
|
|
378
|
-
|
|
379
|
-
```swift
|
|
380
|
-
func pickBackend() async throws -> Backend {
|
|
381
|
-
let systemModel = SystemLanguageModel.default
|
|
382
|
-
if systemModel.isAvailable { return .foundationModels }
|
|
383
|
-
if await mlxModelCanLoad() { return .mlx }
|
|
384
|
-
throw AIError.noBackendAvailable
|
|
385
|
-
}
|
|
386
|
-
```
|
|
294
|
+
neither is there.
|
|
387
295
|
|
|
388
296
|
Send every model call through one actor so requests never compete for the same
|
|
389
297
|
hardware. Actors are reentrant: a method that awaits lets the next caller in,
|
|
390
298
|
so an actor that only forwards the call does not serialise anything. Chain the
|
|
391
299
|
work instead:
|
|
392
300
|
|
|
393
|
-
```swift
|
|
394
|
-
actor InferenceGate {
|
|
395
|
-
private var last: Task<Void, Never>?
|
|
396
|
-
|
|
397
|
-
func exclusive<Value: Sendable>(
|
|
398
|
-
_ work: @escaping @Sendable () async throws -> Value
|
|
399
|
-
) async throws -> Value {
|
|
400
|
-
let previous = last
|
|
401
|
-
let current = Task { () async throws -> Value in
|
|
402
|
-
await previous?.value
|
|
403
|
-
return try await work()
|
|
404
|
-
}
|
|
405
|
-
last = Task { _ = try? await current.value }
|
|
406
|
-
return try await current.value
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
```
|
|
410
|
-
|
|
411
301
|
- For a custom Core ML model, this skill stops at conversion and
|
|
412
302
|
optimisation. Swift integration, loading, Vision hookup and running
|
|
413
303
|
predictions are for `coreml`.
|
|
414
304
|
- Private material such as journals or health notes stays on the device unless
|
|
415
305
|
the product has deliberately chosen a non-local fallback.
|
|
416
306
|
|
|
307
|
+
Code for this section: [Foundation Models and multi-backend code](references/foundation-models-code.md).
|
|
308
|
+
|
|
417
309
|
## Performance habits
|
|
418
310
|
|
|
419
311
|
1. Benchmark without the debugger: in the scheme's Run action (Cmd-Opt-R),
|
|
@@ -457,6 +349,7 @@ actor InferenceGate {
|
|
|
457
349
|
|
|
458
350
|
## Reference files
|
|
459
351
|
|
|
352
|
+
- [Foundation Models and multi-backend code](references/foundation-models-code.md): open for the code behind availability checks, `@Generable` output, tools, error handling and backend routing.
|
|
460
353
|
- [Foundation Models reference](references/foundation-models.md): the full API,
|
|
461
354
|
long conversations, feedback.
|
|
462
355
|
- [Conversion guide](references/coreml-conversion.md): coremltools from each
|