@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,500 +1,329 @@
1
1
  ---
2
2
  name: shareplay-activities
3
- description: "Build shared real-time experiences using GroupActivities and SharePlay. Use when implementing shared media playback, collaborative app features, synchronized game state, or any FaceTime, Messages, AirDrop, or nearby visionOS group activity on iOS, macOS, tvOS, or visionOS."
3
+ description: "GroupActivities and SharePlay on iOS, macOS, tvOS and visionOS: GroupActivity, GroupSession lifecycle, messengers, playback sync, file transfer, late joiners. Use for shared media, collaboration or synced game state over FaceTime, Messages, AirDrop or nearby sharing."
4
4
  metadata:
5
- source: "dpearson2699/swift-ios-skills (PolyForm Perimeter 1.0.0)"
5
+ source: multi-agent-pipeline
6
6
  ---
7
- # GroupActivities / SharePlay
8
- Build shared real-time experiences using the GroupActivities framework. SharePlay
9
- connects people over FaceTime, Messages, AirDrop, and nearby visionOS sharing,
10
- synchronizing media playback, app state, or custom data. Targets Swift 6.3 / iOS 26+.
11
-
12
- ## Contents
13
-
14
- - [Setup](#setup)
15
- - [Defining a GroupActivity](#defining-a-groupactivity)
16
- - [Session Lifecycle](#session-lifecycle)
17
- - [Sending and Receiving Messages](#sending-and-receiving-messages)
18
- - [Coordinated Media Playback](#coordinated-media-playback)
19
- - [Starting SharePlay from Your App](#starting-shareplay-from-your-app)
20
- - [GroupSessionJournal: File Transfer](#groupsessionjournal-file-transfer)
21
- - [Common Mistakes](#common-mistakes)
22
- - [Review Checklist](#review-checklist)
23
- - [References](#references)
7
+
8
+ # SharePlay and Group Activities
9
+
10
+ SharePlay joins people in a FaceTime call, a Messages conversation, an AirDrop
11
+ exchange or, on visionOS, a room of nearby headsets, and keeps media, app state
12
+ or custom data in step between them. Code here is written for Swift 6.3 on
13
+ iOS 26 and newer.
24
14
 
25
15
  ## Setup
26
16
 
27
17
  ### Capability
28
18
 
29
- Add the **Group Activities** capability to the app target in Xcode. Xcode adds
30
- the required entitlement and updates the provisioning profile:
19
+ Add **Group Activities** to the app target under Signing & Capabilities. Xcode
20
+ then sets `com.apple.developer.group-session` to `true` in the entitlements
21
+ file and refreshes provisioning.
31
22
 
32
- ```xml
33
- <key>com.apple.developer.group-session</key>
34
- <true/>
35
- ```
23
+ Only app targets get it. Group Activities does not run in widgets, other
24
+ extensions or App Clips.
36
25
 
37
- Configure this only for app targets. Group Activities are not available in
38
- widgets, extensions, or App Clips.
26
+ ### Eligibility
39
27
 
40
- ### Checking Eligibility
28
+ `GroupStateObserver` reports whether a FaceTime call, or a Messages chat, is
29
+ currently able to host an activity. Use it to decide whether a
30
+ SharePlay button appears.
41
31
 
42
32
  ```swift
43
33
  import GroupActivities
44
34
 
45
- let observer = GroupStateObserver()
46
-
47
- // Check if a FaceTime call or Messages conversation is active
48
- if observer.isEligibleForGroupSession {
49
- showSharePlayButton()
50
- }
51
- ```
52
-
53
- Observe changes reactively:
54
-
55
- ```swift
56
- for await isEligible in observer.$isEligibleForGroupSession.values {
57
- showSharePlayButton(isEligible)
35
+ @MainActor
36
+ func watchEligibility(update: @escaping @MainActor (Bool) -> Void) async {
37
+ let observer = GroupStateObserver()
38
+ update(observer.isEligibleForGroupSession)
39
+ for await eligible in observer.$isEligibleForGroupSession.values {
40
+ update(eligible)
41
+ }
58
42
  }
59
43
  ```
60
44
 
61
- ## Defining a GroupActivity
62
-
63
- Conform to `GroupActivity` and provide metadata:
45
+ ## Defining an activity
64
46
 
65
47
  ```swift
66
- import GroupActivities
67
-
68
- struct WatchTogetherActivity: GroupActivity {
69
- let movieID: String
70
- let movieTitle: String
48
+ struct CookAlong: GroupActivity {
49
+ let recipeID: String
71
50
 
72
51
  var metadata: GroupActivityMetadata {
73
- var meta = GroupActivityMetadata()
74
- meta.title = movieTitle
75
- meta.type = .watchTogether
76
- meta.fallbackURL = URL(string: "https://example.com/movie/\(movieID)")
77
- return meta
52
+ var info = GroupActivityMetadata()
53
+ info.title = "Cook together"
54
+ info.type = .exploreTogether
55
+ info.fallbackURL = URL(string: "https://recipes.example/r/\(recipeID)")
56
+ return info
78
57
  }
79
58
  }
80
59
  ```
81
60
 
82
- ### Activity Types
61
+ ### Activity types
83
62
 
84
- | Type | Use Case |
85
- |---|---|
86
- | `.generic` | Default for custom activities |
87
- | `.watchTogether` | Video playback |
88
- | `.listenTogether` | Audio playback |
89
- | `.createTogether` | Collaborative creation (drawing, editing) |
90
- | `.exploreTogether` | Shared browsing, planning, or exploration |
91
- | `.learnTogether` | Shared learning or studying |
92
- | `.readTogether` | Shared reading |
93
- | `.shopTogether` | Shared shopping |
94
- | `.workoutTogether` | Shared fitness sessions |
63
+ | Type | Fits |
64
+ | --- | --- |
65
+ | `.generic` | The default for anything custom |
66
+ | `.watchTogether` | Video |
67
+ | `.listenTogether` | Audio |
68
+ | `.createTogether` | Drawing, editing, building something together |
69
+ | `.exploreTogether` | Browsing, planning, exploring |
70
+ | `.learnTogether` | Study sessions |
71
+ | `.readTogether` | Reading |
72
+ | `.shopTogether` | Shopping |
73
+ | `.workoutTogether` | Fitness |
95
74
 
96
- `GroupActivity` is `Codable`; stored activity data must be codable. Add
97
- `Transferable` only for SwiftUI `ShareLink`, SharePlay over AirDrop, or
98
- AppKit/UIKit share sheets. Keep payloads minimal: use identifiers or URLs
99
- instead of large data.
75
+ `GroupActivity` inherits `Codable`, so every stored property must be codable.
76
+ Keep the payload tiny: an identifier or a URL, never the content itself. Add
77
+ `Transferable` only when the activity is offered through a SwiftUI `ShareLink`,
78
+ an AirDrop hand-off, or a UIKit or AppKit share sheet.
100
79
 
101
- ## Session Lifecycle
80
+ ## Session lifecycle
102
81
 
103
- ### Listening for Sessions
82
+ ### Receiving sessions
104
83
 
105
- Set up a long-lived task to receive sessions when another participant starts
106
- the activity:
84
+ Sessions started by anyone arrive through `Activity.sessions()`. Iterate it in
85
+ a task owned by a long-lived object.
107
86
 
108
87
  ```swift
109
- @Observable
110
- @MainActor
111
- final class SharePlayManager {
112
- private var session: GroupSession<WatchTogetherActivity>?
88
+ import GroupActivities
89
+ import Observation
90
+
91
+ @MainActor @Observable
92
+ final class KitchenSession {
93
+ private(set) var people: Set<Participant> = []
94
+ private(set) var session: GroupSession<CookAlong>?
95
+ private var jobs: [Task<Void, Never>] = []
113
96
  private var messenger: GroupSessionMessenger?
114
- private var sessionTasks: [Task<Void, Never>] = []
115
97
 
116
- func observeSessions() {
117
- Task {
118
- for await session in WatchTogetherActivity.sessions() {
119
- self.configureSession(session)
120
- }
98
+ init() {
99
+ Task { @MainActor [weak self] in
100
+ for await incoming in CookAlong.sessions() { self?.attach(incoming) }
121
101
  }
122
102
  }
123
103
 
124
- private func configureSession(
125
- _ session: GroupSession<WatchTogetherActivity>
126
- ) {
127
- self.session = session
128
- self.messenger = GroupSessionMessenger(session: session)
129
-
130
- // Observe session state changes
131
- let stateTask = Task {
132
- for await state in session.$state.values {
133
- handleState(state)
134
- }
135
- }
136
- sessionTasks.append(stateTask)
104
+ private func attach(_ incoming: GroupSession<CookAlong>) {
105
+ session = incoming
106
+ messenger = GroupSessionMessenger(session: incoming)
107
+ let states = incoming.$state.values
108
+ let rosters = incoming.$activeParticipants.values
109
+ jobs.append(Task { @MainActor [weak self] in
110
+ for await phase in states { self?.handle(phase) }
111
+ })
112
+ jobs.append(Task { @MainActor [weak self] in
113
+ for await roster in rosters { self?.people = roster }
114
+ })
115
+ incoming.join()
116
+ }
137
117
 
138
- // Observe participant changes
139
- let participantTask = Task {
140
- for await participants in session.$activeParticipants.values {
141
- handleParticipants(participants)
142
- }
118
+ private func handle(_ state: GroupSession<CookAlong>.State) {
119
+ switch state {
120
+ case .waiting:
121
+ break
122
+ case .joined:
123
+ if let recipe = session?.activity.recipeID { RecipeStore.shared.open(recipe) }
124
+ case .invalidated:
125
+ teardown()
126
+ @unknown default:
127
+ break
143
128
  }
144
- sessionTasks.append(participantTask)
145
-
146
- // Join the session
147
- session.join()
148
129
  }
149
130
 
150
- private func cleanUp() {
151
- sessionTasks.forEach { $0.cancel() }
152
- sessionTasks.removeAll()
131
+ func teardown() {
132
+ for job in jobs { job.cancel() }
133
+ jobs = []
153
134
  session = nil
154
135
  messenger = nil
155
136
  }
156
137
  }
157
138
  ```
158
139
 
159
- ### Session States
160
-
161
- | State | Description |
162
- |---|---|
163
- | `.waiting` | Session exists but local participant has not joined |
164
- | `.joined` | Local participant is actively in the session |
165
- | `.invalidated(reason:)` | Session ended (check reason for details) |
166
-
167
- ### Handling State Changes
168
-
169
- ```swift
170
- private func handleState(_ state: GroupSession<WatchTogetherActivity>.State) {
171
- switch state {
172
- case .waiting:
173
- print("Waiting to join")
174
- case .joined:
175
- print("Joined session")
176
- loadActivity(session?.activity)
177
- case .invalidated(let reason):
178
- print("Session ended: \(reason)")
179
- cleanUp()
180
- @unknown default:
181
- break
182
- }
183
- }
184
-
185
- private func handleParticipants(_ participants: Set<Participant>) {
186
- print("Active participants: \(participants.count)")
187
- }
188
- ```
189
-
190
- ### Leaving and Ending
140
+ ### States
191
141
 
192
- ```swift
193
- // Leave the session (other participants continue)
194
- session?.leave()
142
+ | State | Meaning |
143
+ | --- | --- |
144
+ | `.waiting` | The session exists; the local person has not joined |
145
+ | `.joined` | The local person is in the session |
146
+ | `.invalidated(reason:)` | The session is over; the reason says why |
195
147
 
196
- // End the session for all participants
197
- session?.end()
198
- ```
148
+ Participants come as a `Set<Participant>`.
199
149
 
200
- ## Sending and Receiving Messages
150
+ ### Leaving and ending
201
151
 
202
- Use `GroupSessionMessenger` to sync small, time-sensitive app state between
203
- participants.
152
+ - `session?.leave()`: only this device leaves; everyone else carries on.
153
+ - `session?.end()`: the session ends for all participants.
204
154
 
205
- ### Defining Messages
155
+ ## Messages
206
156
 
207
- Messages must be `Codable`; keep each message under 256 KB.
157
+ `GroupSessionMessenger` carries small, time-sensitive app state. Each message
158
+ is `Codable` and must stay under 256 KB.
208
159
 
209
160
  ```swift
210
- struct SyncMessage: Codable {
211
- let action: String
212
- let timestamp: Date
213
- let data: [String: String]
161
+ struct StepChanged: Codable, Sendable {
162
+ let stepIndex: Int
214
163
  }
215
- ```
216
-
217
- ### Sending
218
-
219
- ```swift
220
- func sendSync(_ message: SyncMessage) async throws {
221
- guard let messenger else { return }
222
164
 
223
- try await messenger.send(message, to: .all)
165
+ func announce(step: Int, via messenger: GroupSessionMessenger) async throws {
166
+ try await messenger.send(StepChanged(stepIndex: step), to: .all)
224
167
  }
225
168
 
226
- // Send to specific participants
227
- try await messenger.send(message, to: .only(participant))
228
- ```
229
-
230
- ### Receiving
231
-
232
- ```swift
233
- func observeMessages() {
234
- guard let messenger else { return }
235
-
236
- Task {
237
- for await (message, context) in messenger.messages(of: SyncMessage.self) {
238
- let sender = context.source
239
- handleReceivedMessage(message, from: sender)
240
- }
169
+ func listen(on messenger: GroupSessionMessenger) async {
170
+ for await (change, context) in messenger.messages(of: StepChanged.self) {
171
+ RecipeStore.shared.show(step: change.stepIndex, from: context.source)
241
172
  }
242
173
  }
243
174
  ```
244
175
 
245
- ### Delivery Modes
176
+ Send to one person with `to: .only(participant)`; the sender of a received
177
+ message is `context.source`.
246
178
 
247
- ```swift
248
- // Reliable (default) -- checked and retried for crucial state
249
- let reliableMessenger = GroupSessionMessenger(
250
- session: session,
251
- deliveryMode: .reliable
252
- )
253
-
254
- // Unreliable -- lower latency, no delivery guarantee
255
- let unreliableMessenger = GroupSessionMessenger(
256
- session: session,
257
- deliveryMode: .unreliable
258
- )
259
- ```
179
+ Pick a delivery mode with `GroupSessionMessenger(session:deliveryMode:)`:
260
180
 
261
- Use `.reliable` for state-changing actions such as selections or turns. Use
262
- `.unreliable` for high-frequency ephemeral data such as cursor positions,
263
- drawing strokes, and reactions.
181
+ | Mode | Behaviour | Use for |
182
+ | --- | --- | --- |
183
+ | `.reliable` (default) | Delivery checked and retried | State changes: selections, turns |
184
+ | `.unreliable` | Lower latency, may drop | Frequent throwaway data: cursors, strokes, reactions |
264
185
 
265
- ## Coordinated Media Playback
186
+ ## Coordinated media playback
266
187
 
267
- For video/audio, use `AVPlaybackCoordinator` with `AVPlayer`:
188
+ For `AVPlayer` content, hand the session to the player's coordinator:
268
189
 
269
190
  ```swift
270
191
  import AVFoundation
271
- import GroupActivities
272
192
 
273
- func configurePlayback(
274
- session: GroupSession<WatchTogetherActivity>,
275
- player: AVPlayer
276
- ) {
277
- // Connect the player's coordinator to the session
278
- let coordinator = player.playbackCoordinator
279
- coordinator.coordinateWithSession(session)
193
+ func syncPlayback(_ player: AVPlayer, with session: GroupSession<MovieNight>) {
194
+ player.playbackCoordinator.coordinateWithSession(session)
280
195
  }
281
196
  ```
282
197
 
283
- Once connected, AVFoundation synchronizes play/pause, seeking, rate, playback speed,
284
- and time. Do not put AVPlayer transport fields in messenger messages or snapshots,
285
- including late-joiner snapshots; use custom messages only for state outside playback.
198
+ `AVPlaybackCoordinator` then keeps play, pause, seeks, rate and position in
199
+ step for everyone. Play state, position and rate never belong in your own
200
+ messages or state snapshots, late-joiner snapshots included. Custom messages are
201
+ for state that playback does not cover.
286
202
 
287
- ## Starting SharePlay from Your App
288
-
289
- ### Using GroupActivitySharingController (UIKit)
203
+ ## Starting SharePlay from the app
290
204
 
291
205
  ```swift
292
- import GroupActivities
293
- import UIKit
294
-
295
- func startSharePlay() async throws {
296
- let activity = WatchTogetherActivity(
297
- movieID: "123",
298
- movieTitle: "Great Movie"
299
- )
300
-
301
- switch await activity.prepareForActivation() {
302
- case .activationPreferred:
303
- // A conversation is active and the user chose to share.
304
- _ = try await activity.activate()
305
-
206
+ func startCooking(_ activity: CookAlong) async {
207
+ let choice = await activity.prepareForActivation()
208
+ switch choice {
306
209
  case .activationDisabled:
307
- // The user chose local playback, or sharing is unavailable.
308
- startLocalExperience()
309
-
210
+ RecipeStore.shared.open(activity.recipeID)
211
+ case .activationPreferred:
212
+ do { _ = try await activity.activate() } catch { Log.share.error("\(error)") }
310
213
  case .cancelled:
311
- break
312
-
214
+ return
313
215
  @unknown default:
314
- break
216
+ return
315
217
  }
316
218
  }
317
219
  ```
318
220
 
319
- When no conversation is active (i.e., `isEligibleForGroupSession` is false),
320
- use `GroupActivitySharingController` to let the user pick contacts first:
321
-
322
- ```swift
323
- let controller = try GroupActivitySharingController(activity)
324
- present(controller, animated: true)
325
- ```
326
-
327
- Use the `shareplay` SF Symbol for custom controls. Treat `GroupActivityMetadata`
328
- as discovery copy: concise title, subtitle, image, and type aligned with the
329
- entry point. Keep sibling domains out: GameKit owns auth, matchmaking,
330
- leaderboards, achievements, and voice/chat; TabletopKit owns seats, board
331
- equipment, spatial placement, turns, rules, and authoritative tabletop state;
332
- AVKit owns playback UI. SharePlay owns invitations, lifecycle, participants, and
333
- coordination handoffs. See [references/shareplay-patterns.md](references/shareplay-patterns.md) for SwiftUI `ShareLink`, AirDrop, and direct activation patterns.
334
-
335
- ## GroupSessionJournal: File Transfer
336
-
337
- For larger, non-time-sensitive attachments, use `GroupSessionJournal` instead
338
- of `GroupSessionMessenger`. Journal items must conform to `Transferable`, are
339
- available to late joiners, and are limited to 100 MB. It requires iOS/iPadOS/tvOS
340
- 17+, macOS 14+, or visionOS 1+. For larger/protected assets, share a pointer or manifest and use server storage or app-managed file transfer.
341
-
342
- ```swift
343
- import GroupActivities
344
-
345
- let journal = GroupSessionJournal(session: session)
346
-
347
- // Upload a Transferable file or data item
348
- let attachment = try await journal.add(sharedImageItem)
349
-
350
- // Observe incoming attachments
351
- Task {
352
- for await attachments in journal.attachments {
353
- for attachment in attachments {
354
- let data = try await attachment.load(Data.self)
355
- handleReceivedFile(data)
356
- }
357
- }
358
- }
359
- ```
360
-
361
- ## Common Mistakes
362
-
363
- ### DON'T: Forget to call session.join()
364
-
365
- ```swift
366
- // WRONG -- session is received but never joined
367
- for await session in MyActivity.sessions() {
368
- self.session = session
369
- // Session stays in .waiting state forever
370
- }
371
-
372
- // CORRECT -- join after configuring
373
- for await session in MyActivity.sessions() {
374
- self.session = session
375
- self.messenger = GroupSessionMessenger(session: session)
376
- session.join()
377
- }
378
- ```
379
-
380
- ### DON'T: Forget to leave or end sessions
221
+ - `.activationPreferred`: there is a live conversation and sharing was
222
+ chosen; call `activate()`.
223
+ - `.activationDisabled`: they chose to stay local, or sharing is not possible;
224
+ start the local experience.
225
+ - `.cancelled`: do nothing.
381
226
 
382
- ```swift
383
- // WRONG -- session stays alive after the user navigates away
384
- func viewDidDisappear() {
385
- // Nothing -- session leaks
386
- }
387
-
388
- // CORRECT -- leave when the view is dismissed
389
- func viewDidDisappear() {
390
- session?.leave()
391
- session = nil
392
- messenger = nil
393
- }
394
- ```
395
-
396
- ### DON'T: Assume all participants have the same state
227
+ With no conversation in progress (`isEligibleForGroupSession == false`),
228
+ present `GroupActivitySharingController` in UIKit so the person can pick
229
+ contacts:
397
230
 
398
231
  ```swift
399
- // WRONG -- broadcasting state without handling late joiners
400
- func onJoin() {
401
- // New participant has no idea what the current state is
402
- }
403
-
404
- // CORRECT -- send full state to new participants
405
- func handleParticipants(_ participants: Set<Participant>) {
406
- let newParticipants = participants.subtracting(knownParticipants)
407
- for participant in newParticipants {
408
- Task {
409
- try await messenger?.send(currentState, to: .only(participant))
410
- }
411
- }
412
- knownParticipants = participants
413
- }
232
+ let picker = try GroupActivitySharingController(CookAlong(recipeID: recipe.id))
233
+ hostViewController.present(picker, animated: true)
414
234
  ```
415
235
 
416
- ### DON'T: Use SharePlay transports for large/protected assets
417
-
418
- ```swift
419
- // WRONG -- messenger is small/time-sensitive; journal is Transferable and <=100 MB
420
- let imageData = try Data(contentsOf: imageURL) // 300 KB
421
- try await messenger.send(imageData, to: .all) // Too large
422
- // CORRECT -- journal attachments up to 100 MB; otherwise share a pointer/manifest
423
- let journal = GroupSessionJournal(session: session)
424
- try await journal.add(sharedImageItem)
425
- // Larger/protected assets: server storage or app-managed file transfer
426
- ```
236
+ Custom controls use the `shareplay` SF Symbol. Write
237
+ `GroupActivityMetadata` as discovery copy: a short title, a subtitle and image
238
+ where the surface shows them, and a type that matches where the activity was
239
+ started. SwiftUI buttons, `ShareLink` and AirDrop are covered in
240
+ [the patterns file](references/shareplay-patterns.md).
427
241
 
428
- ### DON'T: Send redundant messages for media playback
242
+ Boundaries with neighbouring frameworks:
429
243
 
430
- ```swift
431
- // WRONG -- manually syncing play/pause when using AVPlayer
432
- func play() {
433
- player.play()
434
- try await messenger.send(PlayMessage(), to: .all)
435
- }
244
+ - GameKit: sign-in, matchmaking, leaderboards, achievements, voice chat.
245
+ - TabletopKit: seating, pieces on the board, where things sit in space, turn
246
+ order, game rules, and which device holds the true table state.
247
+ - AVKit: playback UI.
248
+ - SharePlay (this skill): invitations, session lifecycle, participants and the
249
+ hand-off points to the others.
436
250
 
437
- // CORRECT -- let AVPlaybackCoordinator handle it
438
- player.playbackCoordinator.coordinateWithSession(session)
439
- player.play() // Automatically synced to all participants
440
- ```
251
+ ## GroupSessionJournal: sharing files
441
252
 
442
- ### DON'T: Observe sessions in a view that gets recreated
253
+ For bigger attachments that are not time-critical, use `GroupSessionJournal`
254
+ instead of the messenger. Items must be `Transferable`, attachments stay
255
+ available to people who join later, and each attachment may be up to 100 MB.
256
+ Available on iOS, iPadOS and tvOS 17+, macOS 14+ and visionOS 1+.
443
257
 
444
258
  ```swift
445
- // WRONG -- each time the view appears, a new listener is created
446
- struct MyView: View {
447
- var body: some View {
448
- Text("Hello")
449
- .task {
450
- for await session in MyActivity.sessions() { }
451
- }
452
- }
259
+ func sharePhoto(_ photo: DishPhoto, in session: GroupSession<CookAlong>) async throws {
260
+ let shelf = GroupSessionJournal(session: session)
261
+ _ = try await shelf.add(photo)
453
262
  }
454
263
 
455
- // CORRECT -- observe sessions in a long-lived manager
456
- @Observable
457
- final class ActivityManager {
458
- init() {
459
- Task {
460
- for await session in MyActivity.sessions() {
461
- configureSession(session)
462
- }
264
+ func collectPhotos(from shelf: GroupSessionJournal) async {
265
+ for await batch in shelf.attachments {
266
+ for item in batch {
267
+ guard let bytes = try? await item.load(Data.self) else { continue }
268
+ Gallery.shared.insert(bytes, id: item.id)
463
269
  }
464
270
  }
465
271
  }
466
272
  ```
467
273
 
468
- ## Review Checklist
469
-
470
- - [ ] Group Activities capability added to the app target only
471
- - [ ] `GroupActivity` struct is `Codable` with meaningful metadata
472
- - [ ] `Transferable` conformance added when using `ShareLink`, AirDrop, or share sheets
473
- - [ ] `sessions()` observed in a long-lived object (not a SwiftUI view body)
474
- - [ ] `session.join()` called after receiving and configuring the session
475
- - [ ] `session.leave()` called when the user navigates away or dismisses
476
- - [ ] `GroupSessionMessenger` messages stay under 256 KB with appropriate `deliveryMode`
477
- - [ ] Late-joining participants receive current state on connection
478
- - [ ] `$state` and `$activeParticipants` publishers observed for lifecycle changes
479
- - [ ] `GroupSessionJournal` used for non-time-sensitive `Transferable` attachments
480
- - [ ] `AVPlaybackCoordinator` used for media sync (not manual messages)
481
- - [ ] `GroupStateObserver.isEligibleForGroupSession` checked before showing SharePlay UI
482
- - [ ] `GroupActivitySharingController` used when no conversation is active
483
- - [ ] Session invalidation handled with cleanup of messenger, journal, and tasks
274
+ Anything larger, or anything that needs access control, goes to server storage
275
+ or an app-managed transfer; share only a pointer or manifest through SharePlay.
276
+
277
+ ## Common mistakes
278
+
279
+ - **No `join()`.** The session sits in `.waiting` forever. Join once the
280
+ messenger and observers are set up.
281
+ - **Never leaving.** Navigating away without `session?.leave()` leaks the
282
+ session. Leave on disappear and drop the session and messenger.
283
+ - **Assuming everyone has the same state.** A late joiner knows nothing.
284
+ Compare `activeParticipants` with the set you already know and send the full
285
+ state `to: .only(participant)` to each newcomer.
286
+ - **Pushing big payloads through the messenger.** A 300 KB `Data` blob already
287
+ exceeds its limit. Use the journal up to 100 MB, and server storage or your
288
+ own transfer beyond that.
289
+ - **Duplicating playback commands.** With `AVPlaybackCoordinator` in charge,
290
+ `player.play()` is already shared; extra play or pause messages fight it.
291
+ - **Listening to `sessions()` in a view's `.task`.** Each appearance starts
292
+ another listener. Observe from a long-lived manager, for example from its
293
+ `init`.
294
+
295
+ ## Review checklist
296
+
297
+ - [ ] Only the app target carries the capability
298
+ - [ ] `GroupActivity` is `Codable` and its metadata is meaningful
299
+ - [ ] `Transferable` added where `ShareLink`, AirDrop or share sheets are used
300
+ - [ ] A long-lived object, never a view body, iterates `sessions()`
301
+ - [ ] `join()` called after the session is received and configured
302
+ - [ ] `leave()` called when the person navigates away or dismisses
303
+ - [ ] Messenger payloads under 256 KB, with a suitable `deliveryMode`
304
+ - [ ] Late joiners receive the current state
305
+ - [ ] Both `$state` and `$activeParticipants` are observed
306
+ - [ ] Journal used for `Transferable` attachments that are not time-sensitive
307
+ - [ ] `AVPlaybackCoordinator` handles media sync
308
+ - [ ] `isEligibleForGroupSession` checked before SharePlay UI is shown
309
+ - [ ] `GroupActivitySharingController` offered when no conversation is active
310
+ - [ ] Invalidation tears down messenger, journal and tasks
484
311
 
485
312
  ## References
486
313
 
487
- - Extended patterns (SwiftUI sharing, collaborative canvas, spatial Personas): [references/shareplay-patterns.md](references/shareplay-patterns.md)
488
- - [Configuring Group Activities](https://sosumi.ai/documentation/xcode/configuring-group-activities)
489
- - [GroupActivities framework](https://sosumi.ai/documentation/groupactivities)
490
- - [GroupActivity protocol](https://sosumi.ai/documentation/groupactivities/groupactivity)
491
- - [GroupSession](https://sosumi.ai/documentation/groupactivities/groupsession)
492
- - [GroupSessionMessenger](https://sosumi.ai/documentation/groupactivities/groupsessionmessenger)
493
- - [GroupSessionJournal](https://sosumi.ai/documentation/groupactivities/groupsessionjournal)
494
- - [GroupStateObserver](https://sosumi.ai/documentation/groupactivities/groupstateobserver)
495
- - [GroupActivitySharingController](https://sosumi.ai/documentation/groupactivities/groupactivitysharingcontroller-ybcy)
496
- - [Defining your app's SharePlay activities](https://sosumi.ai/documentation/groupactivities/defining-your-apps-shareplay-activities)
497
- - [Presenting SharePlay activities from your app's UI](https://sosumi.ai/documentation/groupactivities/promoting-shareplay-activities-from-your-apps-ui)
498
- - [Synchronizing data during a SharePlay activity](https://sosumi.ai/documentation/groupactivities/synchronizing-data-during-a-shareplay-activity)
499
- - [Supporting coordinated media playback](https://sosumi.ai/documentation/avfoundation/supporting-coordinated-media-playback)
500
- - [SharePlay HIG](https://sosumi.ai/design/human-interface-guidelines/shareplay)
314
+ - [Pattern catalogue](references/shareplay-patterns.md): shared canvas,
315
+ generic manager, SwiftUI buttons and ShareLink, state sync for late joiners,
316
+ participant tracking, visionOS nearby
317
+ - Capability setup: [Group Activities in Xcode](https://developer.apple.com/documentation/xcode/configuring-group-activities)
318
+ - [GroupActivities](https://developer.apple.com/documentation/groupactivities)
319
+ - [GroupActivity](https://developer.apple.com/documentation/groupactivities/groupactivity)
320
+ - [GroupSession](https://developer.apple.com/documentation/groupactivities/groupsession)
321
+ - [GroupSessionMessenger](https://developer.apple.com/documentation/groupactivities/groupsessionmessenger)
322
+ - [GroupSessionJournal](https://developer.apple.com/documentation/groupactivities/groupsessionjournal)
323
+ - [GroupStateObserver](https://developer.apple.com/documentation/groupactivities/groupstateobserver)
324
+ - [GroupActivitySharingController](https://developer.apple.com/documentation/groupactivities/groupactivitysharingcontroller-ybcy)
325
+ - Article, activity definitions: [link](https://developer.apple.com/documentation/groupactivities/defining-your-apps-shareplay-activities)
326
+ - Article, starting activities from app UI: [link](https://developer.apple.com/documentation/groupactivities/promoting-shareplay-activities-from-your-apps-ui)
327
+ - Article, keeping data in sync: [link](https://developer.apple.com/documentation/groupactivities/synchronizing-data-during-a-shareplay-activity)
328
+ - Article, coordinated playback: [link](https://developer.apple.com/documentation/avfoundation/supporting-coordinated-media-playback)
329
+ - Design guidance: [SharePlay HIG page](https://developer.apple.com/design/human-interface-guidelines/shareplay)