@mmerterden/multi-agent-pipeline 20.7.0 → 20.8.0

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.
Files changed (264) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +0 -10
  3. package/docs/facts.json +1 -1
  4. package/manifest.json +266 -267
  5. package/package.json +2 -2
  6. package/pipeline/scripts/_notices.mjs +1 -1
  7. package/pipeline/skills/.skill-manifest.json +68 -68
  8. package/pipeline/skills/shared/README.md +70 -70
  9. package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
  10. package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
  11. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
  12. package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
  13. package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
  14. package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
  15. package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
  16. package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
  17. package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
  18. package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
  19. package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
  20. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
  21. package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
  22. package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
  23. package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
  24. package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
  25. package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
  26. package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
  27. package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
  28. package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
  29. package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
  30. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
  31. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
  32. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
  33. package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
  34. package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
  35. package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
  36. package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
  37. package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
  38. package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
  39. package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
  40. package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
  41. package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
  42. package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
  43. package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
  44. package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
  45. package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
  46. package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
  47. package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
  48. package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
  49. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
  50. package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
  51. package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
  52. package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
  53. package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
  54. package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
  55. package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
  56. package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
  57. package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
  58. package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
  59. package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
  60. package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
  61. package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
  62. package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
  63. package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
  64. package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
  65. package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
  66. package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
  67. package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
  68. package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
  69. package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
  70. package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
  71. package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
  72. package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
  73. package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
  74. package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
  75. package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
  76. package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
  77. package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
  78. package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
  79. package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
  80. package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
  81. package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
  82. package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
  83. package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
  84. package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
  85. package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
  86. package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
  87. package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
  88. package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
  89. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
  90. package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
  91. package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
  92. package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
  93. package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
  94. package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
  95. package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
  96. package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
  97. package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
  98. package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
  99. package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
  100. package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
  101. package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
  102. package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
  103. package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
  104. package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
  105. package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
  106. package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
  107. package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
  108. package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
  109. package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
  110. package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
  111. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
  112. package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
  113. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
  114. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
  115. package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
  116. package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
  117. package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
  118. package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
  119. package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
  120. package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
  121. package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
  122. package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
  123. package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
  124. package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
  125. package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
  126. package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
  127. package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
  128. package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
  129. package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
  130. package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
  131. package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
  132. package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
  133. package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
  134. package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
  135. package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
  136. package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
  137. package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
  138. package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
  139. package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
  140. package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
  141. package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
  142. package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
  143. package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
  144. package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
  145. package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
  146. package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
  147. package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
  148. package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
  149. package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
  150. package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
  151. package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
  152. package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
  153. package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
  154. package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
  155. package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
  156. package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
  157. package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
  158. package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
  159. package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
  160. package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
  161. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
  162. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
  163. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
  164. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
  165. package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
  166. package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
  167. package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
  168. package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
  169. package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
  170. package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
  171. package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
  172. package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
  173. package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
  174. package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
  175. package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
  176. package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
  177. package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
  178. package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
  179. package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
  180. package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
  181. package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
  182. package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
  183. package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
  184. package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
  185. package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
  186. package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
  187. package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
  188. package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
  189. package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
  190. package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
  191. package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
  192. package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
  193. package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
  194. package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
  195. package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
  196. package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
  197. package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
  198. package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
  199. package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
  200. package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
  201. package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
  202. package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
  203. package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
  204. package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
  205. package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
  206. package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
  207. package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
  208. package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
  209. package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
  210. package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
  211. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
  212. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
  213. package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
  214. package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
  215. package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
  216. package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
  217. package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
  218. package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
  219. package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
  220. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
  221. package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
  222. package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
  223. package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
  224. package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
  225. package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
  226. package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
  227. package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
  228. package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
  229. package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
  230. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
  231. package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
  232. package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
  233. package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
  234. package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
  235. package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
  236. package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
  237. package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
  238. package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
  239. package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
  240. package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
  241. package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
  242. package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
  243. package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
  244. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
  245. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
  246. package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
  247. package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
  248. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
  249. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
  250. package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
  251. package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
  252. package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
  253. package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
  254. package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
  255. package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
  256. package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
  257. package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
  258. package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
  259. package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
  260. package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
  261. package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
  262. package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
  263. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
  264. package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
@@ -1,42 +1,34 @@
1
1
  ---
2
2
  name: tipkit
3
- description: "Implement, review, or improve in-app tips and onboarding using Apple's TipKit framework. Use when adding feature discovery tooltips, onboarding flows, contextual tips, first-run experiences, coach marks, or working with Tip protocol, TipView, popoverTip, tip rules, tip events, or feature education UI."
3
+ description: "TipKit in-app tips (iOS 17+): Tip protocol, TipView, popoverTip, rules, events, TipGroup, styles, CloudKit sync. Use when building or reviewing feature-discovery tooltips, onboarding flows, first-run experiences, coach marks, contextual tips or other feature-education UI."
4
4
  metadata:
5
- source: "dpearson2699/swift-ios-skills (PolyForm Perimeter 1.0.0)"
5
+ source: multi-agent-pipeline
6
6
  ---
7
7
 
8
8
  # TipKit
9
9
 
10
- Add feature discovery tips, contextual hints, and onboarding coach marks to
11
- iOS 17+ apps using Apple's TipKit framework. TipKit manages display frequency,
12
- eligibility rules, and persistence so tips appear at the right time and
13
- disappear once the user has learned the feature.
10
+ TipKit (iOS 17 and later) shows short hints that teach a feature at the
11
+ moment it matters. The framework owns the hard parts: it decides when a tip
12
+ is eligible, throttles how often tips appear, and remembers which tips a
13
+ person has already learned so they stop appearing.
14
14
 
15
- ## Contents
16
-
17
- - [Setup](#setup)
18
- - [Defining Tips](#defining-tips)
19
- - [Displaying Tips](#displaying-tips)
20
- - [Tip Rules](#tip-rules)
21
- - [Tip Actions](#tip-actions)
22
- - [Tip Groups](#tip-groups)
23
- - [Programmatic Control](#programmatic-control)
24
- - [Common Mistakes](#common-mistakes)
25
- - [Review Checklist](#review-checklist)
26
- - [References](#references)
15
+ Tips are for discovery and progressive disclosure. They can be dismissed and
16
+ do not come back, so anything critical or safety related goes in an alert or
17
+ an inline warning instead.
27
18
 
28
19
  ## Setup
29
20
 
30
- Call `Tips.configure()` once in `App.init`, before any views render. This
31
- initializes the tips datastore and begins rule evaluation. Calling it later
32
- risks a race where tip views attempt to display before the datastore is ready.
21
+ Configure TipKit once, in the `App` initializer, before the first view is
22
+ built. `Tips.configure` opens the tips datastore and starts evaluating rules;
23
+ if it runs later (in `onAppear` or `.task`), tip views can render against a
24
+ store that is not ready yet.
33
25
 
34
26
  ```swift
35
27
  import SwiftUI
36
28
  import TipKit
37
29
 
38
30
  @main
39
- struct MyApp: App {
31
+ struct GardenJournalApp: App {
40
32
  init() {
41
33
  try? Tips.configure([
42
34
  .datastoreLocation(.applicationDefault)
@@ -44,99 +36,117 @@ struct MyApp: App {
44
36
  }
45
37
 
46
38
  var body: some Scene {
47
- WindowGroup { ContentView() }
39
+ WindowGroup {
40
+ JournalHomeView()
41
+ }
48
42
  }
49
43
  }
50
44
  ```
51
45
 
52
- ### DatastoreLocation Options
46
+ ### Where the datastore lives
53
47
 
54
- | Option | Use Case |
55
- |---|---|
56
- | `.applicationDefault` | Default location, app sandbox (most apps) |
57
- | `.groupContainer(identifier:)` | Share tips state across app and extensions |
58
- | `.url(_:)` | Custom file URL for full control over storage location |
48
+ | Option | When to pick it |
49
+ | --- | --- |
50
+ | `.applicationDefault` | The app sandbox default. Correct for most apps. |
51
+ | `.groupContainer(identifier:)` | Tip state shared between the app and its extensions. |
52
+ | `.url(_:)` | A file URL you choose, when you need full control. |
59
53
 
60
- ### CloudKit Sync
54
+ ### Syncing tip state with CloudKit
61
55
 
62
- Sync tip state across a user's devices so they do not see the same tip on
63
- every device. Add the CloudKit container option alongside the datastore
64
- location.
56
+ When the app runs on several devices, sync tip state so a person who learned
57
+ a feature on their iPhone is not taught it again on their iPad. Add a CloudKit
58
+ container next to the datastore option (`cloudKitContainer` needs iOS 18):
65
59
 
66
60
  ```swift
67
61
  try? Tips.configure([
68
62
  .datastoreLocation(.applicationDefault),
69
- .cloudKitContainer(.named("iCloud.com.example.app"))
63
+ .cloudKitContainer(.named("iCloud.com.example.gardenjournal"))
70
64
  ])
71
65
  ```
72
66
 
73
- ## Defining Tips
67
+ ## Defining a tip
74
68
 
75
- Conform a struct to the `Tip` protocol. Provide a `title` at minimum.
76
- Add `message` for supporting detail and `image` for a leading icon. Keep
77
- titles short and action-oriented because the tip appears as a compact callout.
69
+ A tip is a struct that conforms to `Tip`. Only `title` (a `Text`) is
70
+ required. `message` (`Text?`) adds a line of context and `image` (`Image?`)
71
+ adds a leading icon. The callout is small, so write the title as a short
72
+ instruction.
78
73
 
79
74
  ```swift
80
- import TipKit
75
+ struct PinPlantTip: Tip {
76
+ var title: Text {
77
+ Text("Pin a plant")
78
+ }
79
+
80
+ var message: Text? {
81
+ Text("Pinned plants stay at the top of your journal.")
82
+ }
81
83
 
82
- struct FavoriteTip: Tip {
83
- var title: Text { Text("Pin Your Favorites") }
84
- var message: Text? { Text("Tap the heart icon to save items for quick access.") }
85
- var image: Image? { Image(systemName: "heart") }
84
+ var image: Image? {
85
+ Image(systemName: "pin")
86
+ }
86
87
  }
87
88
  ```
88
89
 
89
- **Properties**: `title` (required), `message` (optional detail), `image` (optional leading icon), `actions` (optional buttons), `rules` (optional eligibility conditions), `options` (display frequency, max count).
90
+ Optional members:
91
+
92
+ - `actions`: buttons shown inside the tip.
93
+ - `rules`: conditions that must hold before the tip can appear.
94
+ - `options`: per-tip display settings such as a maximum count.
90
95
 
91
- **Lifecycle**: Pending (rules unsatisfied) -> Eligible (all rules pass) -> Invalidated (dismissed, actioned, or programmatically removed). Once invalidated, a tip does not reappear unless the datastore is reset.
96
+ A tip moves through three states. It is pending while its rules are not yet
97
+ satisfied, eligible once every rule passes, and invalidated when it is
98
+ dismissed, acted on, or invalidated in code. An invalidated tip stays hidden
99
+ for good unless the datastore is reset.
92
100
 
93
- ## Displaying Tips
101
+ ## Showing a tip
94
102
 
95
- ### Inline Tips with TipView
103
+ ### Inline with TipView
96
104
 
97
- Embed a `TipView` directly in your layout. It renders as a rounded card that
98
- appears and disappears with animation. Use for tips within scrollable content.
105
+ `TipView(tip)` places the tip in the layout as a rounded card that animates
106
+ in and out. Use it for tips that sit among scrolling content.
99
107
 
100
108
  ```swift
101
- let favoriteTip = FavoriteTip()
102
- var body: some View {
103
- VStack {
104
- TipView(favoriteTip)
105
- ItemListView()
109
+ struct JournalHomeView: View {
110
+ let pinTip = PinPlantTip()
111
+
112
+ var body: some View {
113
+ VStack {
114
+ TipView(pinTip)
115
+ PlantListView()
116
+ }
106
117
  }
107
118
  }
108
119
  ```
109
120
 
110
- ### Popover Tips with .popoverTip()
121
+ ### As a popover
111
122
 
112
- Attach a tip as a popover anchored to any view. The framework draws an arrow
113
- from the popover to the anchor. Use for tips pointing to a specific control.
123
+ `.popoverTip(tip)` attaches the tip to a view and draws an arrow to it. Use it
124
+ when the tip explains one particular control. Pass `arrowEdge:` to choose the
125
+ arrow direction, or leave it out and let the system decide.
114
126
 
115
127
  ```swift
116
- Button { toggleFavorite() } label: { Image(systemName: "heart") }
117
- .popoverTip(favoriteTip)
118
-
119
- // Control arrow direction (omit to let system choose)
120
- .popoverTip(favoriteTip, arrowEdge: .bottom)
128
+ Button("Water", systemImage: "drop") {
129
+ logWatering()
130
+ }
131
+ .popoverTip(waterTip, arrowEdge: .bottom)
121
132
  ```
122
133
 
123
- ### Custom TipViewStyle
134
+ ### A custom look with TipViewStyle
124
135
 
125
- Create a custom style to control tip appearance across the app. Conform
126
- to `TipViewStyle` and implement `makeBody(configuration:)`.
136
+ To restyle tips across the app, adopt `TipViewStyle` and implement
137
+ `makeBody(configuration:)`. The configuration carries `title` plus optional
138
+ `image` and `message`.
127
139
 
128
140
  ```swift
129
- struct CustomTipStyle: TipViewStyle {
141
+ struct LeafTipStyle: TipViewStyle {
130
142
  func makeBody(configuration: Configuration) -> some View {
131
- HStack {
132
- configuration.image?
133
- .font(.title2)
134
- .foregroundStyle(.tint)
135
-
136
- VStack(alignment: .leading) {
143
+ HStack(alignment: .top, spacing: 10) {
144
+ configuration.image
145
+ .foregroundStyle(.green)
146
+ VStack(alignment: .leading, spacing: 4) {
137
147
  configuration.title
138
148
  .font(.headline)
139
- configuration.message?
149
+ configuration.message
140
150
  .font(.subheadline)
141
151
  .foregroundStyle(.secondary)
142
152
  }
@@ -144,353 +154,228 @@ struct CustomTipStyle: TipViewStyle {
144
154
  .padding()
145
155
  }
146
156
  }
147
-
148
- // Apply globally or per view
149
- TipView(favoriteTip)
150
- .tipViewStyle(CustomTipStyle())
151
157
  ```
152
158
 
153
- ## Tip Rules
159
+ Apply it with `.tipViewStyle(LeafTipStyle())` on a single tip view or on a
160
+ container to cover everything below it.
161
+
162
+ ## Rules
154
163
 
155
- Rules control when a tip becomes eligible. All rules in the `rules` array
156
- must pass before the tip displays. TipKit supports two rule types:
157
- parameter-based and event-based.
164
+ Rules decide eligibility. Every rule in `rules` has to pass before the tip is
165
+ shown. There are two kinds.
158
166
 
159
- ### Parameter-Based Rules
167
+ ### Parameter rules (app state)
160
168
 
161
- Use `@Parameter` to track app state. The tip becomes eligible when the
162
- parameter value satisfies the rule condition.
169
+ Declare a `@Parameter` static on the tip, write a rule against its projected
170
+ value, and assign the static when the state changes.
163
171
 
164
172
  ```swift
165
- struct FavoriteTip: Tip {
173
+ struct SortPlantsTip: Tip {
166
174
  @Parameter
167
- static var hasSeenList: Bool = false
175
+ static var hasOpenedList: Bool = false
168
176
 
169
- var title: Text { Text("Pin Your Favorites") }
177
+ var title: Text { Text("Sort by watering date") }
170
178
 
171
179
  var rules: [Rule] {
172
- #Rule(Self.$hasSeenList) { $0 == true }
180
+ #Rule(Self.$hasOpenedList) { $0 == true }
173
181
  }
174
182
  }
175
183
 
176
- // Set the parameter when the user reaches the list
177
- FavoriteTip.hasSeenList = true
184
+ SortPlantsTip.hasOpenedList = true
178
185
  ```
179
186
 
180
- ### Event-Based Rules
187
+ ### Event rules (user actions)
181
188
 
182
- Use `Tips.Event` to track user actions. Donate to the event each time the
183
- action occurs. The rule fires when the donation count or timing condition
184
- is met. This is ideal for tips that should appear after the user has
185
- performed an action several times without discovering a related feature.
189
+ Declare a `Tips.Event`, donate to it every time the action happens, and write
190
+ a rule on the donations. A rule can look at how many donations there are or
191
+ when they happened.
186
192
 
187
193
  ```swift
188
- struct ShortcutTip: Tip {
189
- static let appOpenedEvent = Tips.Event(id: "appOpened")
194
+ struct QuickLogTip: Tip {
195
+ static let entryAdded = Tips.Event(id: "entryAdded")
190
196
 
191
- var title: Text { Text("Try the Quick Action") }
197
+ var title: Text { Text("Log faster with a long press") }
192
198
 
193
199
  var rules: [Rule] {
194
- #Rule(Self.appOpenedEvent) { $0.donations.count >= 3 }
200
+ #Rule(Self.entryAdded) { $0.donations.count >= 3 }
195
201
  }
196
202
  }
197
203
 
198
- // Donate each time the app opens
199
- ShortcutTip.appOpenedEvent.donate()
204
+ Task { await QuickLogTip.entryAdded.donate() }
200
205
  ```
201
206
 
202
- ### Combining Multiple Rules
207
+ Event rules fit tips that should appear only after someone has repeated a
208
+ task several times without finding the shortcut that would help.
203
209
 
204
- Place multiple rules in the array. All must pass (logical AND).
210
+ ### Several rules together
205
211
 
206
- ```swift
207
- struct AdvancedTip: Tip {
208
- @Parameter
209
- static var isLoggedIn: Bool = false
210
-
211
- static let featureUsedEvent = Tips.Event(id: "featureUsed")
212
-
213
- var title: Text { Text("Unlock Advanced Mode") }
212
+ List more than one `#Rule` and all of them must pass (logical AND):
214
213
 
215
- var rules: [Rule] {
216
- #Rule(Self.$isLoggedIn) { $0 == true }
217
- #Rule(Self.featureUsedEvent) { $0.donations.count >= 5 }
218
- }
214
+ ```swift
215
+ var rules: [Rule] {
216
+ #Rule(Self.$isSignedIn) { $0 == true }
217
+ #Rule(Self.entryAdded) { $0.donations.count >= 5 }
219
218
  }
220
219
  ```
221
220
 
222
- ### Display Frequency Options
221
+ ### How often tips appear
223
222
 
224
- Control how often tips appear using the `options` property.
223
+ Per tip, `options` adjusts display behavior:
225
224
 
226
225
  ```swift
227
- struct DailyTip: Tip {
228
- var title: Text { Text("Daily Reminder") }
229
-
230
- var options: [TipOption] {
231
- MaxDisplayCount(3) // Show at most 3 times total
232
- IgnoresDisplayFrequency(true) // Bypass global frequency limit
233
- }
226
+ var options: [TipOption] {
227
+ Tips.MaxDisplayCount(3)
228
+ Tips.IgnoresDisplayFrequency(true)
234
229
  }
235
230
  ```
236
231
 
237
- Global display frequency is set at configuration time:
232
+ - `MaxDisplayCount(3)` stops the tip after three showings in total.
233
+ - `IgnoresDisplayFrequency(true)` lets this tip bypass the global limit.
234
+
235
+ The global limit is set at configuration time with
236
+ `.displayFrequency(...)`, taking `.immediate`, `.hourly`, `.daily`, `.weekly`
237
+ or `.monthly`. With `.daily`, the whole app shows at most one tip per day,
238
+ except for tips that opt out with `IgnoresDisplayFrequency(true)`.
238
239
 
239
240
  ```swift
240
- try? Tips.configure([
241
- .displayFrequency(.daily) // .immediate, .hourly, .daily, .weekly, .monthly
242
- ])
241
+ try? Tips.configure([.displayFrequency(.daily)])
243
242
  ```
244
243
 
245
- With `.daily`, the system shows at most one tip per day across the entire
246
- app, unless a specific tip sets `IgnoresDisplayFrequency(true)`.
244
+ ## Actions
247
245
 
248
- ## Tip Actions
249
-
250
- Add action buttons to a tip for direct interaction. Each action has an `id`
251
- and a label. Handle the action in the tip view's action handler.
246
+ `actions` adds buttons to a tip. Each `Action(id:title:)` gets an identifier
247
+ and a label. Handle taps in the closure passed to `TipView`, switching on the
248
+ identifier.
252
249
 
253
250
  ```swift
254
- struct FeatureTip: Tip {
255
- var title: Text { Text("Try the New Editor") }
256
- var message: Text? { Text("We added a powerful new editing mode.") }
251
+ struct ReminderTip: Tip {
252
+ var title: Text { Text("Never miss a watering") }
257
253
 
258
254
  var actions: [Action] {
259
- Action(id: "open-editor", title: "Open Editor")
260
- Action(id: "learn-more", title: "Learn More")
255
+ Action(id: "set-reminder", title: "Set Reminder")
256
+ Action(id: "show-guide", title: "How It Works")
261
257
  }
262
258
  }
263
- ```
264
-
265
- Handle actions in the view:
266
259
 
267
- ```swift
268
- TipView(featureTip) { action in
260
+ TipView(reminderTip) { action in
269
261
  switch action.id {
270
- case "open-editor":
271
- navigateToEditor()
272
- featureTip.invalidate(reason: .actionPerformed)
273
- case "learn-more":
274
- showHelpSheet = true
262
+ case "set-reminder":
263
+ reminderTip.invalidate(reason: .actionPerformed)
264
+ openReminderEditor()
265
+ case "show-guide":
266
+ isGuidePresented = true
275
267
  default:
276
268
  break
277
269
  }
278
270
  }
279
271
  ```
280
272
 
281
- ## Tip Groups
273
+ ## Tip groups
282
274
 
283
- Use `TipGroup` to coordinate multiple tips within a single view.
284
- `TipGroup` ensures only one tip from the group displays at a time,
285
- preventing tip overload. Tips display in priority order.
275
+ When one screen has several tips, put them in a `TipGroup` (iOS 18 and
276
+ later) so only one is visible at a time. The `.ordered` priority shows them in
277
+ the order listed. Render `currentTip` when it is not nil; invalidating it
278
+ makes the next eligible tip current.
286
279
 
287
280
  ```swift
288
- struct OnboardingView: View {
289
- let tipGroup = TipGroup(.ordered) {
290
- WelcomeTip()
291
- NavigationTip()
292
- ProfileTip()
281
+ struct PlantDetailView: View {
282
+ @State private var tips = TipGroup(.ordered) {
283
+ PinPlantTip()
284
+ SortPlantsTip()
285
+ QuickLogTip()
293
286
  }
294
287
 
295
288
  var body: some View {
296
289
  VStack {
297
- if let currentTip = tipGroup.currentTip {
298
- TipView(currentTip)
290
+ if let tip = tips.currentTip {
291
+ TipView(tip)
299
292
  }
300
-
301
- Button("Next") {
302
- tipGroup.currentTip?.invalidate(reason: .actionPerformed)
293
+ Button("Next hint") {
294
+ tips.currentTip?.invalidate(reason: .actionPerformed)
303
295
  }
304
296
  }
305
297
  }
306
298
  }
307
299
  ```
308
300
 
309
- ### Priority Options
310
-
311
- | Initializer | Behavior |
312
- |---|---|
313
- | `.ordered` | Tips display in the order they are listed |
314
-
315
- When the current tip is invalidated, the next eligible tip in the group
316
- becomes `currentTip`.
317
-
318
- ## Programmatic Control
319
-
320
- ### Invalidating Tips
321
-
322
- Call `invalidate(reason:)` when the user performs the discovered action or
323
- when the tip is no longer relevant.
324
-
325
- ```swift
326
- let tip = FavoriteTip()
327
- tip.invalidate(reason: .actionPerformed)
328
- ```
329
-
330
- | Reason | When to Use |
331
- |---|---|
332
- | `.actionPerformed` | User performed the action the tip describes |
333
- | `.displayCountExceeded` | Tip hit its maximum display count |
334
- | `.tipClosed` | User explicitly dismissed the tip |
335
-
336
- ### Testing Utilities
337
-
338
- TipKit provides static methods to control tip visibility during development
339
- and testing. Gate these behind `#if DEBUG` or `ProcessInfo` checks so they
340
- never run in production builds.
301
+ ## Controlling tips from code
341
302
 
342
- ```swift
343
- #if DEBUG
344
- // Show all tips regardless of rules (useful during development)
345
- Tips.showAllTipsForTesting()
346
-
347
- // Show only specific tips
348
- Tips.showTipsForTesting([FavoriteTip.self, ShortcutTip.self])
349
-
350
- // Hide all tips (useful for UI tests that do not involve tips)
351
- Tips.hideAllTipsForTesting()
303
+ ### Invalidation
352
304
 
353
- // Reset the datastore (clears all tip state, invalidations, and events)
354
- try? Tips.resetDatastore()
355
- #endif
356
- ```
357
-
358
- ### Using ProcessInfo for Test Schemes
305
+ Call `tip.invalidate(reason:)` once the person performs the action the tip
306
+ describes, or when the tip no longer applies.
359
307
 
360
- ```swift
361
- if ProcessInfo.processInfo.arguments.contains("--show-all-tips") {
362
- Tips.showAllTipsForTesting()
363
- }
364
- ```
308
+ | Reason | Meaning |
309
+ | --- | --- |
310
+ | `.actionPerformed` | The person did what the tip suggests. |
311
+ | `.displayCountExceeded` | The tip hit its maximum display count. |
312
+ | `.tipClosed` | The person closed the tip. |
365
313
 
366
- Pass `--show-all-tips` as a launch argument in the Xcode scheme for
367
- development builds.
314
+ ### Testing helpers
368
315
 
369
- ## Common Mistakes
316
+ | Call | Effect |
317
+ | --- | --- |
318
+ | `Tips.showAllTipsForTesting()` | Shows every tip and ignores rules. |
319
+ | `Tips.showTipsForTesting([PinPlantTip.self, QuickLogTip.self])` | Shows only the listed tip types. |
320
+ | `Tips.hideAllTipsForTesting()` | Hides all tips, for UI tests that are not about tips. |
321
+ | `try? Tips.resetDatastore()` | Clears tip state, invalidations and event donations. |
370
322
 
371
- ### DON'T: Call Tips.configure() anywhere except App.init
323
+ None of these may run in production. Put them behind `#if DEBUG` or a
324
+ launch-argument check.
372
325
 
373
- Calling `Tips.configure()` in a view's `onAppear` or `task` modifier
374
- creates a race condition where tip views try to render before the
375
- datastore is ready, causing missing or flickering tips.
326
+ ### Launch arguments for development schemes
376
327
 
377
328
  ```swift
378
- // WRONG
379
- struct ContentView: View {
380
- var body: some View {
381
- Text("Hello")
382
- .task { try? Tips.configure() } // Too late, views already rendered
329
+ init() {
330
+ #if DEBUG
331
+ if ProcessInfo.processInfo.arguments.contains("--show-all-tips") {
332
+ Tips.showAllTipsForTesting()
383
333
  }
384
- }
385
-
386
- // CORRECT
387
- @main struct MyApp: App {
388
- init() { try? Tips.configure() }
389
- var body: some Scene { WindowGroup { ContentView() } }
334
+ #endif
335
+ try? Tips.configure()
390
336
  }
391
337
  ```
392
338
 
393
- ### DON'T: Show too many tips at once
394
-
395
- Displaying multiple tips simultaneously overwhelms users and dilutes the
396
- impact of each tip. Users learn to ignore them.
397
-
398
- ```swift
399
- // WRONG: Three tips visible at the same time
400
- VStack {
401
- TipView(tipA)
402
- TipView(tipB)
403
- TipView(tipC)
404
- }
405
-
406
- // CORRECT: Use TipGroup to sequence them
407
- let group = TipGroup(.ordered) { TipA(); TipB(); TipC() }
408
- if let currentTip = group.currentTip {
409
- TipView(currentTip)
410
- }
411
- ```
412
-
413
- ### DON'T: Forget to invalidate tips after the user performs the action
414
-
415
- If a tip says "Tap the star to favorite" and the user taps the star but
416
- the tip remains, it erodes trust in the UI.
417
-
418
- ```swift
419
- // WRONG: Tip stays visible after user acts
420
- Button("Favorite") { toggleFavorite() }
421
- .popoverTip(favoriteTip)
422
-
423
- // CORRECT: Invalidate on action
424
- Button("Favorite") {
425
- toggleFavorite()
426
- favoriteTip.invalidate(reason: .actionPerformed)
427
- }
428
- .popoverTip(favoriteTip)
429
- ```
430
-
431
- ### DON'T: Leave testing tips enabled in production
432
-
433
- `Tips.showAllTipsForTesting()` bypasses all rules and frequency limits.
434
- Shipping this in production means every user sees every tip immediately.
435
-
436
- ```swift
437
- // WRONG: Always active
438
- Tips.showAllTipsForTesting()
439
-
440
- // CORRECT: Gated behind DEBUG
441
- #if DEBUG
442
- Tips.showAllTipsForTesting()
443
- #endif
444
- ```
445
-
446
- ### DON'T: Make tip titles too long
447
-
448
- Long titles get truncated or wrap awkwardly in the compact tip callout.
449
- Put the key action in the title and supporting context in the message.
450
-
451
- ```swift
452
- // WRONG
453
- var title: Text { Text("You can tap the heart button to save this item to your favorites list") }
454
-
455
- // CORRECT
456
- var title: Text { Text("Save to Favorites") }
457
- var message: Text? { Text("Tap the heart icon to keep items for quick access.") }
458
- ```
459
-
460
- ### DON'T: Use tips for critical information
461
-
462
- Users can dismiss tips at any time and they do not reappear. Never put
463
- essential instructions or safety information in a tip.
464
-
465
- ```swift
466
- // WRONG: Critical info in a dismissible tip
467
- struct DataLossTip: Tip {
468
- var title: Text { Text("Unsaved changes will be lost") }
469
- }
470
-
471
- // CORRECT: Use an alert or inline warning for critical information
472
- // Reserve tips for feature discovery and progressive disclosure
473
- ```
474
-
475
- ## Review Checklist
476
-
477
- - [ ] `Tips.configure()` called in `App.init`, before any views render
478
- - [ ] Each tip has a clear, concise title (action-oriented, under ~40 characters)
479
- - [ ] Tips invalidated when the user performs the discovered action
480
- - [ ] Rules set so tips appear at the right time (not immediately on first launch for all tips)
481
- - [ ] `TipGroup` used when multiple tips exist in one view
482
- - [ ] Testing utilities (`showAllTipsForTesting`, `resetDatastore`) gated behind `#if DEBUG`
483
- - [ ] CloudKit sync configured if the app supports multiple devices
484
- - [ ] Display frequency set appropriately (`.daily` or `.weekly` for most apps)
485
- - [ ] Tips used for feature discovery only, not for critical information
486
- - [ ] Custom `TipViewStyle` applied consistently if the default style does not match the app design
487
- - [ ] Tip actions handled and tip invalidated in the action handler
488
- - [ ] Event donations placed at the correct user action points
489
- - [ ] Ensure custom Tip types are Sendable; configure Tips on @MainActor
339
+ Add `--show-all-tips` under Arguments Passed On Launch in a development
340
+ scheme.
341
+
342
+ ## Pitfalls
343
+
344
+ - Configuring in `onAppear` or `.task`. The race leaves tips missing or
345
+ flickering. Configure in `App.init`.
346
+ - Several `TipView`s on screen at once. People feel swamped and start
347
+ ignoring tips. Sequence them with `TipGroup(.ordered)` and `currentTip`.
348
+ - Leaving a tip up after the person already did the thing. A stale hint costs
349
+ trust. Call `invalidate(reason: .actionPerformed)` in the action of the
350
+ control that carries the `.popoverTip`.
351
+ - Shipping `showAllTipsForTesting()` without a guard. It skips rules and
352
+ frequency limits, so every user sees every tip at once. Wrap it in
353
+ `#if DEBUG`.
354
+ - Long titles. They truncate or wrap awkwardly. Keep the action in the title
355
+ and the explanation in the message.
356
+ - Using a tip for critical or safety information. Tips can be dismissed and
357
+ never return. Use an alert or an inline warning.
358
+
359
+ ## Review checklist
360
+
361
+ - [ ] `Tips.configure()` runs in `App.init`, before any view renders.
362
+ - [ ] Titles are short, clear and action oriented, roughly 40 characters or
363
+ fewer.
364
+ - [ ] Each tip is invalidated when its action is performed.
365
+ - [ ] Rules keep tips from all firing on first launch.
366
+ - [ ] Screens with more than one tip use `TipGroup`.
367
+ - [ ] `showAllTipsForTesting` and `resetDatastore` sit behind `#if DEBUG`.
368
+ - [ ] CloudKit sync is configured when the app runs on more than one device.
369
+ - [ ] Display frequency suits the app; `.daily` or `.weekly` fits most.
370
+ - [ ] Tips are used for feature discovery only, never for critical information.
371
+ - [ ] A custom `TipViewStyle` is applied consistently where the default look
372
+ clashes with the design.
373
+ - [ ] Tip actions are handled and the tip is invalidated in the handler.
374
+ - [ ] Event donations happen at the right user-action points.
375
+ - [ ] Tip types are `Sendable`, and TipKit is configured on the `@MainActor`.
490
376
 
491
377
  ## References
492
378
 
493
- - See [references/tipkit-patterns.md](references/tipkit-patterns.md) for complete implementation patterns
494
- including custom styles, event-based rules, tip groups, testing strategies,
495
- onboarding flows, and SwiftUI preview configuration.
496
-
379
+ - [references/tipkit-patterns.md](references/tipkit-patterns.md): complete
380
+ tips with rules and events, placement, donation values, custom styles, tip
381
+ group sequencing, previews and tests, onboarding and a full app example.