@mmerterden/multi-agent-pipeline 20.7.0 → 20.8.1

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