@mmerterden/multi-agent-pipeline 20.6.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 (326) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/LICENSE +0 -10
  3. package/docs/facts.json +1 -1
  4. package/manifest.json +328 -329
  5. package/package.json +2 -2
  6. package/pipeline/multi-agent-refs/features/design-conformance.md +62 -64
  7. package/pipeline/scripts/_notices.mjs +12 -1
  8. package/pipeline/scripts/gen-skills-index.mjs +1 -1
  9. package/pipeline/skills/.skill-manifest.json +106 -106
  10. package/pipeline/skills/shared/README.md +71 -71
  11. package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +1 -0
  12. package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
  13. package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
  14. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
  15. package/pipeline/skills/shared/external/android-architecture/SKILL.md +2 -0
  16. package/pipeline/skills/shared/external/android-performance/SKILL.md +2 -0
  17. package/pipeline/skills/shared/external/android-security/SKILL.md +2 -0
  18. package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
  19. package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
  20. package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
  21. package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
  22. package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
  23. package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
  24. package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
  25. package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
  26. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
  27. package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
  28. package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
  29. package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
  30. package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
  31. package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
  32. package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
  33. package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
  34. package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
  35. package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
  36. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
  37. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
  38. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
  39. package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
  40. package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
  41. package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
  42. package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
  43. package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
  44. package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
  45. package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
  46. package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
  47. package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
  48. package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
  49. package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
  50. package/pipeline/skills/shared/external/backlog/BACKLOG.md +1 -1
  51. package/pipeline/skills/shared/external/backlog/SKILL.md +56 -33
  52. package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
  53. package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
  54. package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
  55. package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +1 -0
  56. package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
  57. package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
  58. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
  59. package/pipeline/skills/shared/external/compose-components/SKILL.md +2 -0
  60. package/pipeline/skills/shared/external/compose-navigation/SKILL.md +3 -2
  61. package/pipeline/skills/shared/external/compose-testing/SKILL.md +2 -0
  62. package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
  63. package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
  64. package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
  65. package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
  66. package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
  67. package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
  68. package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
  69. package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
  70. package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
  71. package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
  72. package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
  73. package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
  74. package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
  75. package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
  76. package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
  77. package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
  78. package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
  79. package/pipeline/skills/shared/external/council/SKILL.md +1 -0
  80. package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
  81. package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
  82. package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
  83. package/pipeline/skills/shared/external/css-modern/SKILL.md +1 -0
  84. package/pipeline/skills/shared/external/database-patterns/SKILL.md +1 -0
  85. package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
  86. package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
  87. package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
  88. package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
  89. package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
  90. package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
  91. package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
  92. package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
  93. package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
  94. package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
  95. package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
  96. package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
  97. package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
  98. package/pipeline/skills/shared/external/evidence-github/SKILL.md +2 -0
  99. package/pipeline/skills/shared/external/evidence-registry/SKILL.md +2 -0
  100. package/pipeline/skills/shared/external/gradle-kotlin-dsl/SKILL.md +2 -0
  101. package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
  102. package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
  103. package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
  104. package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
  105. package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
  106. package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
  107. package/pipeline/skills/shared/external/html-semantic/SKILL.md +1 -0
  108. package/pipeline/skills/shared/external/humanizer/SKILL.md +1 -0
  109. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
  110. package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
  111. package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
  112. package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
  113. package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
  114. package/pipeline/skills/shared/external/ios-coding-standard/SKILL.md +1 -0
  115. package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
  116. package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
  117. package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
  118. package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
  119. package/pipeline/skills/shared/external/ios-module-structure/SKILL.md +1 -0
  120. package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
  121. package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
  122. package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
  123. package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
  124. package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
  125. package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
  126. package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
  127. package/pipeline/skills/shared/external/ios-security/SKILL.md +2 -0
  128. package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
  129. package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
  130. package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
  131. package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
  132. package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
  133. package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
  134. package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +91 -283
  135. package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +119 -151
  136. package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +60 -90
  137. package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +119 -156
  138. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +726 -787
  139. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +253 -288
  140. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +243 -304
  141. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +88 -104
  142. package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +181 -235
  143. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-key-shots.py +198 -263
  144. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +461 -466
  145. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +145 -151
  146. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +123 -141
  147. package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +146 -157
  148. package/pipeline/skills/shared/external/localization-reuse-map/scripts/snapshot-resources.sh +22 -19
  149. package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +156 -140
  150. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
  151. package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
  152. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
  153. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
  154. package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
  155. package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
  156. package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
  157. package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
  158. package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
  159. package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
  160. package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
  161. package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
  162. package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
  163. package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +1 -0
  164. package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
  165. package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
  166. package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
  167. package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
  168. package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
  169. package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
  170. package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
  171. package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
  172. package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
  173. package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
  174. package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
  175. package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
  176. package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
  177. package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
  178. package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
  179. package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
  180. package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
  181. package/pipeline/skills/shared/external/play-store-review/SKILL.md +2 -0
  182. package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
  183. package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
  184. package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
  185. package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
  186. package/pipeline/skills/shared/external/python-patterns/SKILL.md +1 -0
  187. package/pipeline/skills/shared/external/react-best-practices/SKILL.md +1 -0
  188. package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
  189. package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
  190. package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
  191. package/pipeline/skills/shared/external/rest-api-design/SKILL.md +1 -0
  192. package/pipeline/skills/shared/external/retrofit-networking/SKILL.md +2 -0
  193. package/pipeline/skills/shared/external/room-database/SKILL.md +2 -0
  194. package/pipeline/skills/shared/external/search-first/SKILL.md +1 -0
  195. package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
  196. package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
  197. package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
  198. package/pipeline/skills/shared/external/signal-community/SKILL.md +2 -0
  199. package/pipeline/skills/shared/external/skill-creator/SKILL.md +80 -41
  200. package/pipeline/skills/shared/external/skill-creator/audit.md +63 -59
  201. package/pipeline/skills/shared/external/skill-creator/checklist.md +28 -20
  202. package/pipeline/skills/shared/external/skill-creator/examples.md +40 -40
  203. package/pipeline/skills/shared/external/skill-creator/label-check.md +48 -36
  204. package/pipeline/skills/shared/external/skill-creator/scripts/audit-panel.js +91 -100
  205. package/pipeline/skills/shared/external/skill-creator/template.md +51 -39
  206. package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
  207. package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
  208. package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
  209. package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
  210. package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
  211. package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
  212. package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
  213. package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
  214. package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
  215. package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
  216. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
  217. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
  218. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
  219. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
  220. package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
  221. package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
  222. package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
  223. package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
  224. package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
  225. package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
  226. package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
  227. package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
  228. package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
  229. package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
  230. package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
  231. package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
  232. package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
  233. package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
  234. package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
  235. package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
  236. package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
  237. package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
  238. package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
  239. package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
  240. package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
  241. package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
  242. package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
  243. package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
  244. package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
  245. package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
  246. package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
  247. package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
  248. package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
  249. package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
  250. package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
  251. package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
  252. package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
  253. package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
  254. package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
  255. package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
  256. package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
  257. package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
  258. package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
  259. package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
  260. package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
  261. package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
  262. package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
  263. package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
  264. package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
  265. package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
  266. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
  267. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
  268. package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
  269. package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
  270. package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
  271. package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
  272. package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
  273. package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
  274. package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
  275. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
  276. package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
  277. package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
  278. package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
  279. package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
  280. package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
  281. package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
  282. package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
  283. package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
  284. package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
  285. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
  286. package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
  287. package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
  288. package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
  289. package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
  290. package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
  291. package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
  292. package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
  293. package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
  294. package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
  295. package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
  296. package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
  297. package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
  298. package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
  299. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
  300. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
  301. package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
  302. package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
  303. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
  304. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
  305. package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
  306. package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
  307. package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
  308. package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
  309. package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
  310. package/pipeline/skills/shared/external/tailwind-css/SKILL.md +1 -0
  311. package/pipeline/skills/shared/external/testing-backend/SKILL.md +1 -0
  312. package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
  313. package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
  314. package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +1 -0
  315. package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
  316. package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
  317. package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
  318. package/pipeline/skills/shared/external/vue-composition/SKILL.md +1 -0
  319. package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
  320. package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
  321. package/pipeline/skills/shared/external/web-accessibility/SKILL.md +1 -0
  322. package/pipeline/skills/shared/external/web-performance/SKILL.md +1 -0
  323. package/pipeline/skills/shared/external/web-testing/SKILL.md +1 -0
  324. package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
  325. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
  326. 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.