@mmerterden/multi-agent-pipeline 20.7.0 → 20.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +0 -10
  3. package/docs/facts.json +1 -1
  4. package/manifest.json +266 -267
  5. package/package.json +2 -2
  6. package/pipeline/scripts/_notices.mjs +1 -1
  7. package/pipeline/skills/.skill-manifest.json +68 -68
  8. package/pipeline/skills/shared/README.md +70 -70
  9. package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
  10. package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
  11. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
  12. package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
  13. package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
  14. package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
  15. package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
  16. package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
  17. package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
  18. package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
  19. package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
  20. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
  21. package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
  22. package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
  23. package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
  24. package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
  25. package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
  26. package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
  27. package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
  28. package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
  29. package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
  30. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
  31. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
  32. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
  33. package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
  34. package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
  35. package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
  36. package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
  37. package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
  38. package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
  39. package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
  40. package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
  41. package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
  42. package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
  43. package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
  44. package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
  45. package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
  46. package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
  47. package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
  48. package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
  49. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
  50. package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
  51. package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
  52. package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
  53. package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
  54. package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
  55. package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
  56. package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
  57. package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
  58. package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
  59. package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
  60. package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
  61. package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
  62. package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
  63. package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
  64. package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
  65. package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
  66. package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
  67. package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
  68. package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
  69. package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
  70. package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
  71. package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
  72. package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
  73. package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
  74. package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
  75. package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
  76. package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
  77. package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
  78. package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
  79. package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
  80. package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
  81. package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
  82. package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
  83. package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
  84. package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
  85. package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
  86. package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
  87. package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
  88. package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
  89. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
  90. package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
  91. package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
  92. package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
  93. package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
  94. package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
  95. package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
  96. package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
  97. package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
  98. package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
  99. package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
  100. package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
  101. package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
  102. package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
  103. package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
  104. package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
  105. package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
  106. package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
  107. package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
  108. package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
  109. package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
  110. package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
  111. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
  112. package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
  113. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
  114. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
  115. package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
  116. package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
  117. package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
  118. package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
  119. package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
  120. package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
  121. package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
  122. package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
  123. package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
  124. package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
  125. package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
  126. package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
  127. package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
  128. package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
  129. package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
  130. package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
  131. package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
  132. package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
  133. package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
  134. package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
  135. package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
  136. package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
  137. package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
  138. package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
  139. package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
  140. package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
  141. package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
  142. package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
  143. package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
  144. package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
  145. package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
  146. package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
  147. package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
  148. package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
  149. package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
  150. package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
  151. package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
  152. package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
  153. package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
  154. package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
  155. package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
  156. package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
  157. package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
  158. package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
  159. package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
  160. package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
  161. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
  162. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
  163. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
  164. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
  165. package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
  166. package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
  167. package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
  168. package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
  169. package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
  170. package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
  171. package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
  172. package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
  173. package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
  174. package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
  175. package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
  176. package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
  177. package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
  178. package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
  179. package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
  180. package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
  181. package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
  182. package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
  183. package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
  184. package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
  185. package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
  186. package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
  187. package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
  188. package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
  189. package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
  190. package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
  191. package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
  192. package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
  193. package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
  194. package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
  195. package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
  196. package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
  197. package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
  198. package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
  199. package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
  200. package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
  201. package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
  202. package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
  203. package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
  204. package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
  205. package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
  206. package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
  207. package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
  208. package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
  209. package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
  210. package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
  211. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
  212. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
  213. package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
  214. package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
  215. package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
  216. package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
  217. package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
  218. package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
  219. package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
  220. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
  221. package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
  222. package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
  223. package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
  224. package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
  225. package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
  226. package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
  227. package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
  228. package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
  229. package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
  230. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
  231. package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
  232. package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
  233. package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
  234. package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
  235. package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
  236. package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
  237. package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
  238. package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
  239. package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
  240. package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
  241. package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
  242. package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
  243. package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
  244. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
  245. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
  246. package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
  247. package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
  248. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
  249. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
  250. package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
  251. package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
  252. package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
  253. package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
  254. package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
  255. package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
  256. package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
  257. package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
  258. package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
  259. package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
  260. package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
  261. package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
  262. package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
  263. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
  264. package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
@@ -1,430 +1,382 @@
1
1
  ---
2
2
  name: swift-concurrency
3
- description: "Swift concurrency language reference and migration: Sendable and actor-isolation diagnostics, approachable concurrency (SE-0466 default MainActor, @concurrent, nonisolated(nonsending), Task.immediate), actors, TaskGroup and the Swift 6 strict-mode migration. Use when fixing strict-concurrency errors or migrating; for the smallest fix to one diagnostic use swift-concurrency-expert, for a file-by-file review swift-concurrency-pro."
3
+ description: "Swift 6.2+ concurrency: actor isolation, Sendable, sending, approachable concurrency (SE-0466 default MainActor, @concurrent, nonisolated(nonsending), Task.immediate), TaskGroup, cancellation, AsyncStream, bridging callbacks and GCD, Swift 6 migration. Use when answering concurrency questions, reading Sendable or isolation diagnostics, or repairing strict-concurrency errors. Not for single-diagnostic fixes or per-file reviews."
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
  # Swift Concurrency
9
9
 
10
- Review, fix, and write concurrent Swift code targeting Swift 6.3+. Apply actor
11
- isolation, Sendable safety, and modern concurrency patterns with minimal
12
- behavior changes.
10
+ Baseline: Swift 6.3 compilers and later. The aim of every change made with this
11
+ skill is data-race safety through isolation and `Sendable`, reached with the
12
+ smallest possible change in behavior. Features newer than Swift 6.0 name the
13
+ release or proposal that introduced them.
14
+
15
+ Not for the smallest fix to a single diagnostic (use `swift-concurrency-expert`)
16
+ or a file-by-file review pass (use `swift-concurrency-pro`).
13
17
 
14
18
  ## Contents
15
19
 
16
- - [Triage Workflow](#triage-workflow)
17
- - [Swift 6.2 Language Changes](#swift-62-language-changes)
18
- - [Actor Isolation Rules](#actor-isolation-rules)
19
- - [Sendable Rules](#sendable-rules)
20
- - [Structured Concurrency Patterns](#structured-concurrency-patterns)
21
- - [Task Cancellation](#task-cancellation)
22
- - [Actor Reentrancy](#actor-reentrancy)
23
- - [AsyncSequence and AsyncStream](#asyncsequence-and-asyncstream)
24
- - [`@Observable and Concurrency`](#observable-and-concurrency)
25
- - [Synchronization Primitives](#synchronization-primitives)
26
- - [Common Mistakes](#common-mistakes)
27
- - [Review Checklist](#review-checklist)
20
+ - [Triage workflow](#triage-workflow)
21
+ - [Approachable concurrency in Swift 6.2](#approachable-concurrency-in-swift-62)
22
+ - [Isolation rules](#isolation-rules)
23
+ - [Sendable rules](#sendable-rules)
24
+ - [Tasks and structured concurrency](#tasks-and-structured-concurrency)
25
+ - [Cancellation](#cancellation)
26
+ - [Actor reentrancy](#actor-reentrancy)
27
+ - [Streams and continuations](#streams-and-continuations)
28
+ - [Observable models](#observable-models)
29
+ - [Locks and atomics](#locks-and-atomics)
30
+ - [Choosing how code moves between contexts](#choosing-how-code-moves-between-contexts)
31
+ - [Mistakes to catch](#mistakes-to-catch)
32
+ - [Review checklist](#review-checklist)
28
33
  - [References](#references)
29
34
 
30
- ## Triage Workflow
31
-
32
- When diagnosing a concurrency issue, follow this sequence:
33
-
34
- ### Step 1: Capture context
35
+ ## Triage workflow
35
36
 
36
- - Copy the exact compiler diagnostic(s) and the offending symbol(s).
37
- - Identify the project's concurrency settings:
38
- - Swift language version (must be 6.2+).
39
- - Whether Approachable Concurrency is enabled.
40
- - Whether Default Actor Isolation is set to `MainActor`.
41
- - Swift 6 strict concurrency status: complete/errors in Swift 6 language mode;
42
- Complete / Targeted / Minimal only when auditing Swift 5 migration settings.
43
- - Determine the current actor context of the code (`@MainActor`, custom `actor`,
44
- `nonisolated`) and whether a default isolation mode is active.
45
- - Confirm whether the code is UI-bound or intended to run off the main actor.
37
+ **1. Collect the facts before editing.**
46
38
 
47
- ### Step 2: Apply the smallest safe fix
39
+ - Copy the compiler message word for word and note every symbol it names.
40
+ - Find the Swift language version. This workflow assumes 6.2 or newer.
41
+ - Check two build settings separately: is Approachable Concurrency on, and is
42
+ Default Actor Isolation set to `MainActor`?
43
+ - In Swift 6 language mode strict checking is always complete and every
44
+ data-race diagnostic is an error. The Minimal, Targeted and Complete levels
45
+ only matter when you audit a target still in Swift 5 mode.
46
+ - Work out where the failing code is isolated today: `@MainActor`, a custom
47
+ `actor`, or `nonisolated`, and whether a module-wide default applies.
48
+ - Decide whether the code belongs to the UI or is meant to run away from the
49
+ main actor.
48
50
 
49
- Prefer edits that preserve existing behavior while satisfying data-race safety.
51
+ **2. Make the smallest change that is still safe.** Keep behavior as it is.
50
52
 
51
- | Situation | Recommended fix |
53
+ | Situation | Change |
52
54
  |---|---|
53
- | UI-bound type | Annotate the type or relevant members with `@MainActor`. |
54
- | Protocol conformance on MainActor type | Use an isolated conformance: `extension Foo: @MainActor Proto`. |
55
- | Global / static state | Protect with `@MainActor` or move into an actor. |
56
- | Background work needed | Use a `@concurrent` async function on a `nonisolated` type. |
57
- | Sendable error | Prefer immutable value types. Add `Sendable` only when correct. |
58
- | Cross-isolation callback | Use `sending` parameters (SE-0430) for finer control. |
59
-
60
- ### Step 3: Verify
61
-
62
- - Rebuild and confirm the diagnostic is resolved.
63
- - Check for new warnings introduced by the fix.
64
- - Ensure no unnecessary `@unchecked Sendable` or `nonisolated(unsafe)` was added.
65
-
66
- ## Swift 6.2 Language Changes
67
-
68
- Swift 6.2 introduces "approachable concurrency" -- a set of language changes
69
- that make concurrent code safer by default while reducing annotation burden.
70
- In Xcode, Approachable Concurrency and Default Actor Isolation are separate
71
- build settings: use Approachable Concurrency for the bundled upcoming-feature
72
- flags, and set Default Actor Isolation to `MainActor` when you want unannotated
73
- code inferred as `@MainActor`.
74
-
75
- ### SE-0466: Default MainActor Isolation
76
-
77
- With the `-default-isolation MainActor` compiler flag, SwiftPM
78
- `.defaultIsolation(MainActor.self)`, or Xcode's `Default Actor Isolation`
79
- setting set to `MainActor`, unannotated declarations in the module are inferred
80
- as `@MainActor` unless explicitly opted out.
81
-
82
- **Effect:** Eliminates most data-race safety errors for UI-bound code and
83
- global/static state without writing `@MainActor` everywhere.
55
+ | Type drives UI | `@MainActor` on the type or on the members that need it |
56
+ | Main-actor type must satisfy a protocol | Isolated conformance: `extension Foo: @MainActor Proto` |
57
+ | Global or `static` mutable state | Put it on `@MainActor` or inside an actor |
58
+ | Work must leave the caller's actor | `@concurrent` async function on a `nonisolated` type |
59
+ | Type fails a `Sendable` check | Prefer an immutable value type; declare `Sendable` only when it is true |
60
+ | Value handed to another isolation once | A `sending` parameter or result (SE-0430) |
61
+
62
+ **3. Confirm.** Rebuild and check the diagnostic is gone, no new warnings
63
+ appeared, and no `@unchecked Sendable` or `nonisolated(unsafe)` slipped in
64
+ without a proven reason.
65
+
66
+ ## Approachable concurrency in Swift 6.2
67
+
68
+ Swift 6.2 changed defaults so that ordinary code needs fewer annotations and is
69
+ safe without them. Xcode exposes two independent settings, and mixing them up
70
+ is the most common planning error:
71
+
72
+ - **Approachable Concurrency** switches on a group of upcoming features,
73
+ including `NonisolatedNonsendingByDefault` and isolated-conformance
74
+ inference. It does not make the module main-actor isolated.
75
+ - **Default Actor Isolation = `MainActor`** (SE-0466) is the setting that makes
76
+ unannotated declarations infer `@MainActor`.
77
+
78
+ Default isolation can be turned on three ways: the compiler flag
79
+ `-default-isolation MainActor`, `.defaultIsolation(MainActor.self)` in a
80
+ SwiftPM `swiftSettings` array, or the Xcode build setting. Use it for app
81
+ targets, scripts and other executables where most code serves the UI. Leave
82
+ library targets without it so they stay usable from any isolation.
84
83
 
85
84
  ```swift
86
- // With default MainActor isolation enabled, these are implicitly @MainActor:
87
- final class StickerLibrary {
88
- static let shared = StickerLibrary() // safe -- on MainActor
89
- var stickers: [Sticker] = []
85
+ // Target built with Default Actor Isolation = MainActor: no annotations needed.
86
+ final class PlaybackQueue {
87
+ static let current = PlaybackQueue() // main-actor protected
88
+ var upcoming: [Episode] = [] // main-actor protected
90
89
  }
91
90
 
92
- final class StickerModel {
93
- let photoProcessor = PhotoProcessor()
94
- var selection: [PhotosPickerItem] = []
91
+ final class EpisodeLibrary {
92
+ let renderer = WaveformRenderer()
93
+ var pinned: [Episode.ID] = []
95
94
  }
96
95
 
97
- // Conformances are also implicitly isolated:
98
- extension StickerModel: Exportable {
99
- func export() {
100
- photoProcessor.exportAsPNG()
101
- }
96
+ extension EpisodeLibrary: Archivable { // conformance is main-actor isolated too
97
+ func archive() -> Data { Data() }
102
98
  }
103
99
  ```
104
100
 
105
- **When to use:** Recommended for apps, scripts, and other executable targets
106
- where most code is UI-bound. Not recommended for library targets that should
107
- remain actor-agnostic.
108
-
109
- ### SE-0461: nonisolated(nonsending)
110
-
111
- Nonisolated async functions now stay on the caller's actor by default instead
112
- of hopping to the global concurrent executor. This is the
113
- `nonisolated(nonsending)` behavior.
101
+ **Async functions stay where they are called (SE-0461).** With
102
+ `NonisolatedNonsendingByDefault` on, a `nonisolated` async function runs on the
103
+ caller's actor instead of jumping to the global concurrent executor. That
104
+ behavior is spelled `nonisolated(nonsending)`. Without the feature, Swift 6.0
105
+ and 6.1 semantics still apply and the function leaves the caller's actor.
114
106
 
115
107
  ```swift
116
- class PhotoProcessor {
117
- func extractSticker(data: Data, with id: String?) async -> Sticker? {
118
- // In Swift 6.2+, this runs on the caller's actor (e.g., MainActor)
119
- // instead of hopping to a background thread.
120
- // ...
121
- }
108
+ final class WaveformRenderer {
109
+ func render(_ audio: Data) async -> Waveform { Waveform(samples: []) }
122
110
  }
123
111
 
124
112
  @MainActor
125
- final class StickerModel {
126
- let photoProcessor = PhotoProcessor()
127
-
128
- func extractSticker(_ item: PhotosPickerItem) async throws -> Sticker? {
129
- guard let data = try await item.loadTransferable(type: Data.self) else {
130
- return nil
131
- }
132
- // No data race -- photoProcessor stays on MainActor
133
- return await photoProcessor.extractSticker(data: data, with: item.itemIdentifier)
134
- }
135
- }
136
- ```
137
-
138
- Use `@concurrent` to explicitly request background execution when needed.
113
+ final class EpisodeDetailModel {
114
+ let renderer = WaveformRenderer()
115
+ var waveform: Waveform?
139
116
 
140
- ### `@concurrent` Attribute
141
-
142
- `@concurrent` ensures a function always runs on the concurrent thread pool,
143
- freeing the calling actor to run other tasks.
144
-
145
- ```swift
146
- class PhotoProcessor {
147
- var cachedStickers: [String: Sticker] = [:]
148
-
149
- func extractSticker(data: Data, with id: String) async -> Sticker {
150
- if let sticker = cachedStickers[id] { return sticker }
151
-
152
- let sticker = await Self.extractSubject(from: data)
153
- cachedStickers[id] = sticker
154
- return sticker
155
- }
156
-
157
- @concurrent
158
- static func extractSubject(from data: Data) async -> Sticker {
159
- // Expensive image processing -- runs on background thread pool
160
- // ...
117
+ func open(_ url: URL) async throws {
118
+ let (audio, _) = try await URLSession.shared.data(from: url)
119
+ waveform = await renderer.render(audio) // stays on the main actor: no race reported
161
120
  }
162
121
  }
163
122
  ```
164
123
 
165
- To move a function to a background thread:
166
- 1. Ensure the containing type is `nonisolated` (or the function itself is).
167
- 2. Add `@concurrent` to the function.
168
- 3. Add `async` if not already asynchronous.
169
- 4. Add `await` at call sites.
124
+ **`@concurrent` asks for the thread pool on purpose.** A `@concurrent` function
125
+ always runs on the concurrent pool, which frees the calling actor. To move a
126
+ piece of work off the caller:
127
+
128
+ 1. Make the type, or just the function, `nonisolated`.
129
+ 2. Add `@concurrent`.
130
+ 3. Make the function `async` if it is not already.
131
+ 4. Put `await` at each call site.
170
132
 
171
133
  ```swift
172
- nonisolated struct PhotoProcessor {
134
+ nonisolated struct TranscriptBuilder {
173
135
  @concurrent
174
- func process(data: Data) async -> ProcessedPhoto? { /* ... */ }
136
+ func build(from audio: Data) async -> Transcript? { Transcript(lines: []) }
175
137
  }
176
138
 
177
- // Caller:
178
- processedPhotos[item.id] = await PhotoProcessor().process(data: data)
139
+ // On the main actor:
140
+ transcripts[episode.id] = await builder.build(from: audio)
179
141
  ```
180
142
 
181
- ### SE-0472: Task.immediate
182
-
183
- `Task.immediate` starts executing synchronously on the current actor before
184
- any suspension point, rather than being enqueued.
143
+ **Other 6.2 additions**, each covered in
144
+ [concurrency-patterns.md](references/concurrency-patterns.md):
145
+
146
+ - `Task.immediate` (SE-0472) runs synchronously on the current actor until its
147
+ first suspension instead of being enqueued; `Task.immediateDetached` adds
148
+ detached semantics. Use it where the enqueue delay is visible to the user,
149
+ for example `Task.immediate { await search.apply(query) }`.
150
+ - `Observations { }` (SE-0475) turns reads of `@Observable` properties into an
151
+ `AsyncSequence` with transactional updates:
152
+ `for await elapsed in Observations({ player.elapsed }) { scrubber.move(to: elapsed) }`.
153
+ - Isolated conformances let a main-actor type conform to a protocol whose
154
+ requirements it can only meet on the main actor. The compiler allows the
155
+ conformance only where that isolation holds.
156
+ - SE-0473 adds `.epoch` to `ContinuousClock` and `SuspendingClock`, but the
157
+ iOS 26.4 SDK does not ship it yet ("value of type 'ContinuousClock' has no
158
+ member 'epoch'"); check your SDK before relying on it.
159
+
160
+ ## Isolation rules
161
+
162
+ - Shared mutable state needs one owner: an actor, a global actor, or a
163
+ `Sendable` synchronization primitive such as `Mutex` or `Atomic`. Unowned
164
+ shared state is a race.
165
+ - Code that reads or writes UI state is `@MainActor`. SwiftUI closures that the
166
+ framework documents as running off the main thread are the exception, and
167
+ they receive copies, not UI state (see
168
+ [swiftui-concurrency.md](references/swiftui-concurrency.md)).
169
+ - `nonisolated` suits members that only read immutable `let` storage or do pure
170
+ computation.
171
+ - `@concurrent` is the explicit way to leave the caller's actor.
172
+ - `nonisolated(unsafe)` is for state whose synchronization you have proven by
173
+ other means, after every checked option has been ruled out.
174
+ - An actor already serializes access. Adding `NSLock` or `DispatchSemaphore`
175
+ inside it buys nothing and can deadlock.
176
+
177
+ ## Sendable rules
178
+
179
+ - A struct or enum is implicitly `Sendable` when all its stored properties are.
180
+ - Actors are `Sendable`. So are classes isolated to a global actor, such as a
181
+ `@MainActor` class; writing `Sendable` on them again is noise.
182
+ - Any other class qualifies only if it is `final` and every stored property is
183
+ a `let` of a `Sendable` type (a `let` holding a `Mutex` counts).
184
+ - `@unchecked Sendable` is the final option, and the declaration must carry a
185
+ note saying which lock or invariant the compiler cannot see.
186
+ - `sending` parameters and results (SE-0430) move a non-`Sendable` value into
187
+ another isolation region once, without making the type `Sendable`.
188
+ - `@preconcurrency import` is for third-party modules you cannot change. Record
189
+ a plan to remove it.
190
+
191
+ ## Tasks and structured concurrency
192
+
193
+ | Tool | What it inherits | Use for |
194
+ |---|---|---|
195
+ | `async let` | Everything; child task | A fixed number of concurrent calls |
196
+ | `withTaskGroup` / `withThrowingTaskGroup` | Everything; child tasks | A number of calls known only at run time |
197
+ | `Task { }` | Actor, priority, task-locals | Starting async work from synchronous code |
198
+ | `Task.immediate { }` | Same as `Task`, starts at once | Latency-sensitive starts (OS 26 runtime) |
199
+ | `Task.detached { }` | Nothing | Deliberately breaking inheritance; see the rule below |
185
200
 
186
201
  ```swift
187
- Task.immediate { await handleUserInput() }
188
- ```
189
-
190
- Use for latency-sensitive work that should begin without delay. There is also
191
- `Task.immediateDetached` which combines immediate start with detached semantics.
192
-
193
- ### SE-0475: Transactional Observation (Observations)
194
-
195
- `Observations { }` provides async observation of `@Observable` types via
196
- `AsyncSequence`, enabling transactional change tracking.
202
+ async let profile = api.profile(for: userID)
203
+ async let badges = api.badges(for: userID)
204
+ let (loadedProfile, loadedBadges) = try await (profile, badges)
197
205
 
198
- ```swift
199
- for await _ in Observations { model.count } {
200
- print("Count changed to \(model.count)")
206
+ let episodes = try await withThrowingTaskGroup(of: Episode.self) { group in
207
+ for id in episodeIDs {
208
+ group.addTask { try await api.episode(id) }
209
+ }
210
+ var collected: [Episode] = []
211
+ for try await episode in group { collected.append(episode) }
212
+ return collected
201
213
  }
202
214
  ```
203
215
 
204
- ### Isolated Conformances
205
-
206
- A conformance that needs MainActor state is called an *isolated conformance*.
207
- The compiler ensures it is only used in a matching isolation context.
216
+ SE-0493 lets a `defer` body `await`, but the Swift 6.3.1 compiler in Xcode
217
+ 26.4 still rejects it with "'async' call cannot occur in a defer body". Until
218
+ your toolchain accepts it, run async cleanup on every exit path yourself:
208
219
 
209
220
  ```swift
210
- protocol Exportable {
211
- func export()
212
- }
213
-
214
- // Isolated conformance: only usable on MainActor
215
- extension StickerModel: @MainActor Exportable {
216
- func export() {
217
- photoProcessor.exportAsPNG()
221
+ func exportSession() async throws -> Int {
222
+ let file = try await LogFile.open(named: "session")
223
+ do {
224
+ let written = try await file.write(pendingEntries)
225
+ await file.close()
226
+ return written
227
+ } catch {
228
+ await file.close()
229
+ throw error
218
230
  }
219
231
  }
220
-
221
- @MainActor
222
- struct ImageExporter {
223
- var items: [any Exportable]
224
-
225
- mutating func add(_ item: StickerModel) {
226
- items.append(item) // OK -- ImageExporter is on MainActor
227
- }
228
- }
229
- ```
230
-
231
- If `ImageExporter` were `nonisolated`, adding a `StickerModel` would fail:
232
- "Main actor-isolated conformance of 'StickerModel' to 'Exportable' cannot be
233
- used in nonisolated context."
234
-
235
- ### Clock Epochs
236
-
237
- `ContinuousClock` and `SuspendingClock` now expose `.epoch` (SE-0473), enabling instant comparison and conversion between clock types.
238
-
239
- ```swift
240
- let continuous = ContinuousClock()
241
- let elapsed = continuous.now - continuous.epoch // Duration since system boot
242
232
  ```
243
233
 
244
- ## Actor Isolation Rules
245
-
246
- 1. All mutable shared state MUST be protected by an actor or global actor.
247
- 2. `@MainActor` for all UI-touching code. No exceptions.
248
- 3. Use `nonisolated` only for methods that access immutable (`let`) properties
249
- or are pure computations.
250
- 4. Use `@concurrent` to explicitly move work off the caller's actor.
251
- 5. Never use `nonisolated(unsafe)` unless you have proven internal
252
- synchronization and exhausted all other options.
253
- 6. Never add manual locks (`NSLock`, `DispatchSemaphore`) inside actors.
254
-
255
- ## Sendable Rules
234
+ ## Cancellation
256
235
 
257
- 1. Value types (structs, enums) are automatically `Sendable` when all stored
258
- properties are `Sendable`.
259
- 2. Actors are implicitly `Sendable`.
260
- 3. `@MainActor` classes are implicitly `Sendable`. Do NOT add redundant
261
- `Sendable` conformance.
262
- 4. Non-actor classes: must be `final` with all stored properties `let` and
263
- `Sendable`.
264
- 5. `@unchecked Sendable` is a last resort. Document why the compiler cannot
265
- prove safety.
266
- 6. Use `sending` parameters (SE-0430) for finer-grained isolation control.
267
- 7. Use `@preconcurrency import` only for third-party libraries you cannot
268
- modify. Plan to remove it.
236
+ Cancellation is a request the task must honor itself.
269
237
 
270
- ## Structured Concurrency Patterns
238
+ - In loops, test `Task.isCancelled` or call `try Task.checkCancellation()`.
239
+ - In SwiftUI, start work with `.task`; it is cancelled when the view goes away.
240
+ - Release resources on cancellation with `withTaskCancellationHandler`.
241
+ - A `Task` you store must be cancelled by you, in `deinit` or `onDisappear`.
242
+ An unstructured task is never cancelled because its creator was.
271
243
 
272
- ### Async Defer
244
+ ## Actor reentrancy
273
245
 
274
- `defer` blocks can now contain `await` (SE-0493). Use for async cleanup - closing connections, flushing buffers, or releasing resources that require an async call.
246
+ An actor runs one piece of code at a time, but every `await` inside it lets
247
+ other calls in. State read before an `await` may be stale after it.
275
248
 
276
249
  ```swift
277
- func fetchData() async throws -> Data {
278
- let connection = try await openConnection()
279
- defer { await connection.close() }
280
- return try await connection.read()
281
- }
282
- ```
250
+ actor TicketCounter {
251
+ private var sold = 0
252
+ private let audit: AuditLog
283
253
 
284
- **Task:** Unstructured, inherits caller context.
285
- ```swift
286
- Task { await doWork() }
287
- ```
254
+ init(audit: AuditLog) { self.audit = audit }
288
255
 
289
- **Task.detached:** No inherited context. Use only when you explicitly need to
290
- break isolation inheritance.
291
-
292
- **Task.immediate:** Starts immediately on current actor. Use for
293
- latency-sensitive work.
294
- ```swift
295
- Task.immediate { await handleUserInput() }
296
- ```
297
-
298
- **async let:** Fixed number of concurrent operations.
299
- ```swift
300
- async let a = fetchA()
301
- async let b = fetchB()
302
- let result = try await (a, b)
303
- ```
304
-
305
- **TaskGroup:** Dynamic number of concurrent operations.
306
- ```swift
307
- try await withThrowingTaskGroup(of: Item.self) { group in
308
- for id in ids {
309
- group.addTask { try await fetch(id) }
256
+ func sellLosingUpdates() async {
257
+ let current = sold
258
+ await audit.record(current)
259
+ sold = current + 1 // another call may have run during the await
310
260
  }
311
- for try await item in group { process(item) }
312
- }
313
- ```
314
-
315
- ## Task Cancellation
316
-
317
- - Cancellation is cooperative. Check `Task.isCancelled` or call
318
- `try Task.checkCancellation()` in loops.
319
- - Use `.task` modifier in SwiftUI -- it handles cancellation on view disappear.
320
- - Use `withTaskCancellationHandler` for cleanup.
321
- - Cancel stored tasks in `deinit` or `onDisappear`.
322
-
323
- ## Actor Reentrancy
324
261
 
325
- Actors are reentrant. State can change across suspension points.
326
-
327
- ```swift
328
- // WRONG: State may change during await
329
- actor Counter {
330
- var count = 0
331
- func increment() async {
332
- let current = count
333
- await someWork()
334
- count = current + 1 // BUG: count may have changed
262
+ func sell() async {
263
+ sold += 1 // read and write with no suspension between them
264
+ await audit.record(sold)
335
265
  }
336
266
  }
337
-
338
- // CORRECT: Mutate synchronously, no reentrancy risk
339
- actor Counter {
340
- var count = 0
341
- func increment() { count += 1 }
342
- }
343
267
  ```
344
268
 
345
- ## AsyncSequence and AsyncStream
269
+ ## Streams and continuations
346
270
 
347
- Use `AsyncStream` to bridge callback/delegate APIs:
271
+ Bridge APIs that call back many times with `AsyncStream`, and single-shot
272
+ callbacks with `withCheckedContinuation` or `withCheckedThrowingContinuation`.
273
+ A continuation is resumed exactly once on every path.
348
274
 
349
275
  ```swift
350
- let stream = AsyncStream<Location> { continuation in
351
- let delegate = LocationDelegate { location in
352
- continuation.yield(location)
276
+ func readings(from scale: BluetoothScale) -> AsyncStream<Measurement<UnitMass>> {
277
+ AsyncStream { continuation in
278
+ let subscription = scale.observe { continuation.yield($0) }
279
+ continuation.onTermination = { _ in subscription.cancel() }
280
+ scale.startStreaming()
353
281
  }
354
- continuation.onTermination = { _ in delegate.stop() }
355
- delegate.start()
356
282
  }
357
283
  ```
358
284
 
359
- Use `withCheckedContinuation` / `withCheckedThrowingContinuation` for
360
- single-value callbacks. Resume exactly once.
361
-
362
- ## `@Observable` and Concurrency
363
-
364
- - `@Observable` classes should be `@MainActor` for view models.
365
- - Use `@State` to own an `@Observable` instance (replaces `@StateObject`).
366
- - Use `Observations { }` (SE-0475) for async observation of `@Observable`
367
- properties as an `AsyncSequence`.
368
-
369
- ## Synchronization Primitives
370
-
371
- When actors are not the right fit - synchronous access, performance-critical
372
- paths, or bridging C/ObjC - use low-level synchronization primitives:
373
-
374
- - **`Mutex<Value>`** (iOS 18+, `Synchronization` module): Preferred lock for
375
- new code. Stores protected state inside the lock. `withLock { }` pattern.
376
- - **`OSAllocatedUnfairLock`** (iOS 16+, `os` module): Use when targeting
377
- older iOS versions. Supports ownership assertions for debugging.
378
- - **`Atomic<Value>`** (iOS 18+, `Synchronization` module): Lock-free atomics
379
- for simple counters and flags. Requires explicit memory ordering.
380
-
381
- **Key rule:** Never put locks inside actors (double synchronization), and never
382
- hold a lock across `await` (deadlock risk). See
383
- [references/synchronization-primitives.md](references/synchronization-primitives.md) for full API details, code examples,
384
- and a decision guide for choosing locks vs actors.
385
-
386
- ## Common Mistakes
387
-
388
- 1. **Blocking the main actor.** Heavy computation on `@MainActor` freezes UI.
389
- Move to a `@concurrent` function.
390
- 2. **Unnecessary @MainActor.** Network layers, data processing, and model code
391
- do not need `@MainActor`. Only UI-touching code does.
392
- 3. **Actors for stateless code.** No mutable state means no actor needed. Use a
393
- plain struct or function.
394
- 4. **Actors for immutable data.** Use a `Sendable` struct, not an actor.
395
- 5. **Task.detached without good reason.** Loses priority, task-local values,
396
- and cancellation propagation.
397
- 6. **Forgetting task cancellation.** Store `Task` references and cancel them, or
398
- use the `.task` view modifier.
399
- 7. **Retain cycles in Tasks.** Use `[weak self]` when capturing `self` in
400
- long-lived stored tasks.
401
- 8. **Semaphores in async context.** `DispatchSemaphore.wait()` in async code
402
- will deadlock. Use structured concurrency instead.
403
- 9. **Split isolation.** Mixing `@MainActor` and `nonisolated` properties in one
404
- type. Isolate the entire type consistently.
405
- 10. **MainActor.run instead of static isolation.** Prefer `@MainActor func`
406
- over `await MainActor.run { }`.
407
- 11. **Using GCD APIs.** Never use DispatchQueue, DispatchGroup, DispatchSemaphore, or any GCD API. Use async/await, actors, and TaskGroups instead. GCD has no data-race safety guarantees.
408
-
409
- ## Review Checklist
410
-
411
- - [ ] All mutable shared state is actor-isolated
412
- - [ ] No data races (no unprotected cross-isolation access)
413
- - [ ] Tasks are cancelled when no longer needed
414
- - [ ] No blocking calls on `@MainActor`
415
- - [ ] No manual locks inside actors
416
- - [ ] `Sendable` conformance is correct (no unjustified `@unchecked`)
417
- - [ ] Actor reentrancy is handled (no state assumptions across awaits)
418
- - [ ] `@preconcurrency` imports are documented with removal plan
419
- - [ ] Heavy work uses `@concurrent`, not `@MainActor`
420
- - [ ] `.task` modifier used in SwiftUI instead of manual Task management
285
+ Delegate bridges, cancellation-aware continuations and the full GCD mapping are
286
+ in [bridging-interop.md](references/bridging-interop.md).
287
+
288
+ ## Observable models
289
+
290
+ - Isolate `@Observable` view models to `@MainActor`.
291
+ - Own them in a view with `@State`, which replaces `@StateObject`.
292
+ - Read their changes from async code with `Observations { }` (SE-0475).
293
+
294
+ ## Locks and atomics
295
+
296
+ Actors are the default for shared mutable state. Locks fit when callers must
297
+ stay synchronous, when a path is hot enough that an actor hop costs too much,
298
+ or when C and Objective-C callbacks touch the state.
299
+
300
+ | Primitive | Minimum OS | Module | Use |
301
+ |---|---|---|---|
302
+ | `Mutex<Value>` | iOS 18 | `Synchronization` | First choice in new code; owns the state it guards, accessed through `withLock` |
303
+ | `OSAllocatedUnfairLock` | iOS 16 | `os` | Older deployment targets; offers ownership preconditions for debugging |
304
+ | `Atomic<Value>` | iOS 18 | `Synchronization` | Lock-free counters and flags; every call names a memory ordering |
305
+
306
+ Two absolute rules: no lock inside an actor, since that synchronizes twice, and
307
+ no lock held across an `await`, since that can deadlock. Details and a decision
308
+ guide: [synchronization-primitives.md](references/synchronization-primitives.md).
309
+
310
+ ## Choosing how code moves between contexts
311
+
312
+ The same rule covers GCD, `MainActor.run` and `Task.detached`: **state
313
+ isolation in the declaration first, hop dynamically only when the declaration
314
+ cannot say it, and keep Dispatch only where an API requires a queue.** A
315
+ declaration is checked by the compiler; a hop inside a function body and a
316
+ Dispatch queue are not visible to that checking in the same way, so each step
317
+ down this list gives up guarantees.
318
+
319
+ | Goal | Default | Acceptable when | Do not |
320
+ |---|---|---|---|
321
+ | Run on the main actor | `@MainActor` on the type, function or closure | `await MainActor.run { }` for one short batch of UI updates inside an async function that must itself stay `nonisolated`; `Task { @MainActor in }` from synchronous nonisolated code; `MainActor.assumeIsolated { }` in a synchronous callback documented to arrive on the main thread | `DispatchQueue.main.async` in new code |
322
+ | Run away from the caller | `@concurrent` async function (6.2+); on 6.0 and 6.1 a `nonisolated` async function | `Task.detached` when the work must not inherit the actor, priority or task-local values, and you will cancel it yourself | `DispatchQueue.global().async` in new code |
323
+ | Protect state | An actor | `Mutex`, `Atomic` or `OSAllocatedUnfairLock` for synchronous callers | A serial queue used as a lock in new code |
324
+ | Fan out and join | `async let`, task groups | | `DispatchGroup`, `concurrentPerform` |
325
+ | Wait for a result | `await` | | `DispatchSemaphore.wait()` or `DispatchGroup.wait()` from async code, ever |
326
+ | API demands a queue | Pass a `DispatchQueue` and enter isolation at once in the callback | Back a custom actor with a `DispatchSerialQueue` as its executor (iOS 17) when it must share a queue with such an API | Mix queue-confined state with actor state |
327
+
328
+ So GCD is not banned as a type in the codebase; it is banned as the way new code
329
+ expresses isolation or coordination, because the compiler cannot prove what a
330
+ custom queue protects. `MainActor.run` and `Task.detached` are legitimate but
331
+ second choices, each with a named reason.
332
+
333
+ ## Mistakes to catch
334
+
335
+ - Heavy computation on the main actor freezes the UI; move it to `@concurrent`.
336
+ - `@MainActor` on networking, parsing or model code that never touches the UI.
337
+ - An actor for code with no mutable state; use a struct or a free function.
338
+ - An actor wrapping immutable data; use a `Sendable` struct.
339
+ - `Task.detached` with no stated reason: it discards the actor, priority and
340
+ task-local values. Like any unstructured task it is also not cancelled with
341
+ its creator.
342
+ - Tasks started and forgotten; keep the handle and cancel it, or use `.task`.
343
+ - A long-lived stored task capturing `self` strongly; capture `[weak self]`.
344
+ - `DispatchSemaphore.wait()` in async code: it blocks a cooperative thread and
345
+ can deadlock the pool.
346
+ - Mutable state split across isolations in one type, for example some `var`s
347
+ on the main actor and others `nonisolated`. `nonisolated let` constants and
348
+ pure helpers next to isolated state are fine.
349
+ - `await MainActor.run { }` where `@MainActor` on the function would do.
350
+ - New Dispatch code for isolation or coordination (see the rule above).
351
+
352
+ ## Review checklist
353
+
354
+ - [ ] Every piece of shared mutable state has one isolation owner.
355
+ - [ ] No access crosses isolation without the compiler's approval.
356
+ - [ ] Tasks are cancelled when their result is no longer wanted.
357
+ - [ ] Nothing blocking runs on `@MainActor`.
358
+ - [ ] No manual locks inside actors.
359
+ - [ ] `Sendable` conformances are true; each `@unchecked` names its invariant.
360
+ - [ ] No assumption about actor state survives an `await`.
361
+ - [ ] Each `@preconcurrency import` has a removal plan.
362
+ - [ ] CPU-heavy work is `@concurrent`, not on the main actor.
363
+ - [ ] SwiftUI work starts from `.task`, not hand-managed tasks.
421
364
 
422
365
  ## References
423
366
 
424
- - [references/concurrency-patterns.md](references/concurrency-patterns.md) - detailed concurrency patterns and migration examples
425
- - [references/approachable-concurrency.md](references/approachable-concurrency.md) - approachable concurrency mode quick-reference
426
- - [references/swiftui-concurrency.md](references/swiftui-concurrency.md) - SwiftUI-specific concurrency guidance
427
- - [references/synchronization-primitives.md](references/synchronization-primitives.md) - Mutex, OSAllocatedUnfairLock, locks vs actors
428
- - [references/bridging-interop.md](references/bridging-interop.md) - checked continuations, delegate bridging, GCD migration table
429
- - [references/diagnostics.md](references/diagnostics.md) - compiler diagnostic → fix reference, strict concurrency adoption
430
- - [references/async-algorithms.md](references/async-algorithms.md) - swift-async-algorithms: debounce, throttle, merge, combineLatest, chunks
367
+ - [concurrency-patterns.md](references/concurrency-patterns.md): approachable
368
+ concurrency in depth, before and after examples, `weak let`, global state,
369
+ build settings and migration.
370
+ - [approachable-concurrency.md](references/approachable-concurrency.md): quick
371
+ reference for detecting the mode and fixing code inside it.
372
+ - [swiftui-concurrency.md](references/swiftui-concurrency.md): main-actor
373
+ views, framework callbacks that run off the main thread, `.task`, view models.
374
+ - [synchronization-primitives.md](references/synchronization-primitives.md):
375
+ `Mutex`, `OSAllocatedUnfairLock`, `Atomic`, memory ordering, locks versus
376
+ actors.
377
+ - [bridging-interop.md](references/bridging-interop.md): continuations,
378
+ delegates, streams from callbacks, and replacing GCD.
379
+ - [diagnostics.md](references/diagnostics.md): compiler messages and fixes,
380
+ adoption order, Thread Sanitizer.
381
+ - [async-algorithms.md](references/async-algorithms.md): the
382
+ swift-async-algorithms package.