@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,347 +1,283 @@
1
1
  # Synchronization Primitives
2
2
 
3
- Low-level synchronization tools for protecting shared mutable state when actors
4
- are not the right fit. All primitives discussed here are `Sendable` and safe
5
- to use from multiple threads.
6
-
7
- ## Contents
8
-
9
- - [Mutex](#mutex)
10
- - [OSAllocatedUnfairLock](#osallocatedunfairlock)
11
- - [Atomic](#atomic)
12
- - [Locks vs Actors: When to Use Each](#locks-vs-actors-when-to-use-each)
3
+ When an actor is the wrong shape for some shared mutable state, these types
4
+ protect it instead. Each one is `Sendable` and safe to use from any thread.
13
5
 
14
6
  ## Mutex
15
7
 
16
- **Module:** `Synchronization` · **Availability:** iOS 18.0+
17
-
18
- `Mutex<Value>` is a synchronization primitive that protects shared mutable
19
- state via mutual exclusion. It blocks threads attempting to acquire the lock,
20
- ensuring only one execution context accesses the protected value at a time.
21
-
22
- **Documentation:**
23
- [sosumi.ai/documentation/synchronization/mutex](https://sosumi.ai/documentation/synchronization/mutex)
24
-
25
- ### Basic Usage
8
+ `Mutex<Value>` lives in the `Synchronization` module and needs iOS 18.0 or
9
+ later. It guarantees mutual exclusion: a thread that asks for a lock someone
10
+ else holds waits until it is released. Documentation:
11
+ https://developer.apple.com/documentation/synchronization/mutex
26
12
 
27
13
  ```swift
28
14
  import Synchronization
15
+ import UIKit
29
16
 
30
- class ImageCache: Sendable {
31
- let storage = Mutex<[String: UIImage]>([:])
17
+ final class AvatarCache: Sendable {
18
+ private let images = Mutex<[String: UIImage]>([:])
32
19
 
33
- func image(forKey key: String) -> UIImage? {
34
- storage.withLock { $0[key] }
20
+ func image(for handle: String) -> UIImage? {
21
+ images.withLock { $0[handle] }
35
22
  }
36
23
 
37
- func store(_ image: UIImage, forKey key: String) {
38
- storage.withLock { $0[key] = image }
24
+ func store(_ image: UIImage, for handle: String) {
25
+ images.withLock { $0[handle] = image }
39
26
  }
40
27
 
41
- func removeAll() {
42
- storage.withLock { $0.removeAll() }
28
+ func purge() {
29
+ images.withLock { $0.removeAll() }
43
30
  }
44
31
  }
45
32
  ```
46
33
 
47
- ### withLockIfAvailable
48
-
49
- Use `withLockIfAvailable` to attempt acquisition without blocking. Returns
50
- `nil` if the lock is already held.
34
+ `withLockIfAvailable` tries once and returns `nil` instead of waiting when the
35
+ lock is taken:
51
36
 
52
37
  ```swift
53
- let counter = Mutex<Int>(0)
38
+ let pendingFlushes = Mutex<Int>(0)
54
39
 
55
- // Non-blocking attempt - returns nil if lock is contended
56
- if let value = counter.withLockIfAvailable({ $0 }) {
57
- print("Current count: \(value)")
40
+ if let count = pendingFlushes.withLockIfAvailable({ $0 }) {
41
+ metrics.report(pendingFlushes: count)
58
42
  } else {
59
- print("Lock was busy, skipping")
43
+ // contended: skip this sample
60
44
  }
61
45
  ```
62
46
 
63
- ### Key Properties
47
+ Properties worth remembering:
64
48
 
65
- - **Generic over `Value`:** The protected state is stored inside the mutex,
66
- making it clear what the lock protects.
67
- - **`Sendable`:** `Mutex` conforms to `Sendable`, so it can be stored in
68
- `Sendable` types (classes, actors, global state).
69
- - **Non-recursive:** Attempting to lock a `Mutex` that you already hold on the
70
- same thread is undefined behavior.
71
- - **Synchronous only:** Do not `await` inside `withLock`. The lock is held for
72
- the duration of the closure - blocking across a suspension point will
73
- deadlock or starve other threads.
49
+ - It is generic over the protected value and stores that value itself, so it
50
+ is always clear what the lock guards.
51
+ - It is `Sendable`, so it can sit in a `Sendable` class, in global state, or
52
+ (rarely) next to an actor.
53
+ - It is not recursive. Locking it again on the thread that holds it is
54
+ undefined behavior.
55
+ - It is synchronous. The lock is held for the entire `withLock` closure, so
56
+ never `await` inside it; suspending while holding a lock can deadlock or
57
+ starve the thread pool.
74
58
 
75
59
  ## OSAllocatedUnfairLock
76
60
 
77
- **Module:** `os` · **Availability:** iOS 16.0+
78
-
79
- `OSAllocatedUnfairLock<State>` wraps `os_unfair_lock` in a safe Swift API.
80
- It heap-allocates the underlying lock, avoiding the unsound address-of
81
- problem that makes raw `os_unfair_lock` unusable from Swift.
61
+ `OSAllocatedUnfairLock<State>` comes from the `os` module and needs iOS 16.0.
62
+ It wraps `os_unfair_lock` in a safe API. Because it allocates the lock on the
63
+ heap, it avoids the problem that makes a raw `os_unfair_lock` unsound in Swift:
64
+ Swift gives no stable address for a stored struct. Documentation:
65
+ https://developer.apple.com/documentation/os/osallocatedunfairlock
82
66
 
83
- **Documentation:**
84
- [sosumi.ai/documentation/os/osallocatedunfairlock](https://sosumi.ai/documentation/os/osallocatedunfairlock)
85
-
86
- ### State-Protecting Lock
67
+ Guarding state:
87
68
 
88
69
  ```swift
89
70
  import os
90
71
 
91
- enum LoadState: Sendable {
92
- case idle
93
- case loading
94
- case complete(Data)
95
- case failed(Error)
72
+ enum UploadPhase: Sendable {
73
+ case waiting
74
+ case sending(progress: Double)
75
+ case done(receipt: String)
76
+ case failed(any Error)
96
77
  }
97
78
 
98
- final class ResourceLoader: Sendable {
99
- let state = OSAllocatedUnfairLock(initialState: LoadState.idle)
100
-
101
- func beginLoading() {
102
- state.withLock { $0 = .loading }
103
- }
79
+ final class UploadTracker: Sendable {
80
+ private let phase = OSAllocatedUnfairLock(initialState: UploadPhase.waiting)
104
81
 
105
- func completeLoading(with data: Data) {
106
- state.withLock { $0 = .complete(data) }
82
+ func update(_ newPhase: UploadPhase) {
83
+ phase.withLock { $0 = newPhase }
107
84
  }
108
85
 
109
- var currentState: LoadState {
110
- state.withLock { $0 }
86
+ var current: UploadPhase {
87
+ phase.withLock { $0 }
111
88
  }
112
89
  }
113
90
  ```
114
91
 
115
- ### Stateless Lock
116
-
117
- When protecting external state or a code section rather than a specific value:
92
+ Guarding a critical section with no state inside the lock:
118
93
 
119
94
  ```swift
120
- let lock = OSAllocatedUnfairLock()
95
+ let journalLock = OSAllocatedUnfairLock()
121
96
 
122
- lock.withLock {
123
- // Critical section - no associated state
124
- writeToSharedFile(data)
97
+ func appendToJournal(_ line: String) {
98
+ journalLock.withLock {
99
+ writeLine(line, toFileAt: journalURL)
100
+ }
125
101
  }
126
102
  ```
127
103
 
128
- ### Manual lock/unlock
129
-
130
- Available but discouraged. Must unlock from the same thread that locked.
131
- **Never** use across `await` suspension points.
104
+ `lock()` and `unlock()` also exist but are discouraged. If you use them, unlock
105
+ on the same thread that locked, never span an `await`, and pair them with
106
+ `defer`:
132
107
 
133
108
  ```swift
134
- lock.lock()
135
- defer { lock.unlock() }
136
- // Critical section
109
+ journalLock.lock()
110
+ defer { journalLock.unlock() }
111
+ writeLine("checkpoint", toFileAt: journalURL)
137
112
  ```
138
113
 
139
- ### Mutex vs OSAllocatedUnfairLock
114
+ ## Mutex or OSAllocatedUnfairLock
140
115
 
141
- | | `Mutex<Value>` | `OSAllocatedUnfairLock<State>` |
116
+ | | `Mutex` | `OSAllocatedUnfairLock` |
142
117
  |---|---|---|
143
- | **Availability** | iOS 18+ | iOS 16+ |
144
- | **Module** | `Synchronization` | `os` |
145
- | **State model** | Value stored inside lock (generic `Value`) | Optional state via `initialState:` |
146
- | **`withLockIfAvailable`** | Returns `nil` on contention | Returns `nil` on contention |
147
- | **Ownership assertions** | Not available | `precondition(.owner)` / `precondition(.notOwner)` |
148
- | **Manual lock/unlock** | Not available | Available (`lock()` / `unlock()`) |
149
- | **Recommendation** | Preferred for iOS 18+ code | Use when targeting iOS 16-17 |
150
-
151
- **Guideline:** Use `Mutex` for new code targeting iOS 18+. For apps that run on
152
- iOS 16 through current releases, either keep the shared abstraction backed by
153
- `OSAllocatedUnfairLock` or branch with `#available(iOS 18, *)` so iOS 18+ uses
154
- `Mutex` and iOS 16-17 uses `OSAllocatedUnfairLock`. Prefer
155
- `OSAllocatedUnfairLock` when you need ownership assertions for debugging.
118
+ | Minimum OS | iOS 18 | iOS 16 |
119
+ | Module | `Synchronization` | `os` |
120
+ | State | Always stores a generic `Value` | Optional, via `initialState:` |
121
+ | Non-blocking attempt | `withLockIfAvailable` | `withLockIfAvailable` |
122
+ | Ownership checks | None | `precondition(.owner)`, `precondition(.notOwner)` |
123
+ | Manual `lock()` / `unlock()` | No | Yes |
124
+
125
+ - Targeting iOS 18 or later: use `Mutex`.
126
+ - Targeting iOS 16 or 17: use `OSAllocatedUnfairLock`.
127
+ - Supporting iOS 16 through the current release: build the shared abstraction
128
+ on `OSAllocatedUnfairLock`, or branch with `#available(iOS 18, *)` and use
129
+ `Mutex` where it exists.
130
+ - Want to assert lock ownership while debugging: `OSAllocatedUnfairLock`.
156
131
 
157
132
  ## Atomic
158
133
 
159
- **Module:** `Synchronization` · **Availability:** iOS 18.0+
160
-
161
- `Atomic<Value>` provides lock-free atomic operations on values conforming to
162
- `AtomicRepresentable`. Use atomics for simple counters, flags, and
163
- compare-and-swap patterns where a full lock would be overkill.
164
-
165
- **Documentation:**
166
- [sosumi.ai/documentation/synchronization/atomic](https://sosumi.ai/documentation/synchronization/atomic)
167
-
168
- ### Counter Example
134
+ `Atomic<Value>` is in `Synchronization` and needs iOS 18.0. It performs
135
+ lock-free operations on types conforming to `AtomicRepresentable` and suits
136
+ counters, flags and compare-and-exchange where a lock would be overkill.
137
+ Documentation: https://developer.apple.com/documentation/synchronization/atomic
169
138
 
170
139
  ```swift
171
140
  import Synchronization
172
141
 
173
- final class RequestTracker: Sendable {
174
- let activeRequests = Atomic<Int>(0)
175
-
176
- func beginRequest() {
177
- activeRequests.wrappingAdd(1, ordering: .relaxed)
178
- }
142
+ final class ActiveStreams: Sendable {
143
+ private let count = Atomic<Int>(0)
179
144
 
180
- func endRequest() {
181
- activeRequests.wrappingSubtract(1, ordering: .relaxed)
182
- }
145
+ func opened() { count.wrappingAdd(1, ordering: .relaxed) }
146
+ func closed() { count.wrappingSubtract(1, ordering: .relaxed) }
147
+ var value: Int { count.load(ordering: .relaxed) }
148
+ }
183
149
 
184
- var count: Int {
185
- activeRequests.load(ordering: .relaxed)
150
+ final class Teardown: Sendable {
151
+ private let finished = Atomic<Bool>(false)
152
+
153
+ func runOnce() {
154
+ let (won, _) = finished.compareExchange(
155
+ expected: false,
156
+ desired: true,
157
+ ordering: .acquiringAndReleasing
158
+ )
159
+ guard won else { return }
160
+ closeSockets()
186
161
  }
187
162
  }
188
163
  ```
189
164
 
190
- ### Boolean Flag
165
+ ### Memory ordering
191
166
 
192
- ```swift
193
- let isShutdown = Atomic<Bool>(false)
194
-
195
- func shutdown() {
196
- let (exchanged, _) = isShutdown.compareExchange(
197
- expected: false,
198
- desired: true,
199
- ordering: .acquiringAndReleasing
200
- )
201
- guard exchanged else { return } // Already shut down
202
- performCleanup()
203
- }
204
- ```
167
+ Every atomic call names an ordering.
205
168
 
206
- ### Memory Ordering
169
+ | Ordering | Use |
170
+ |---|---|
171
+ | `.relaxed` | Counters and statistics; no ordering relative to other memory |
172
+ | `.acquiring` | A load that must see everything written before the matching release |
173
+ | `.releasing` | A store whose earlier writes must be visible to the matching acquire |
174
+ | `.acquiringAndReleasing` | Compare-and-exchange and other read-modify-write operations |
175
+ | `.sequentiallyConsistent` | Strongest and slowest; rarely required, use only with a proven need |
207
176
 
208
- Atomic operations require an explicit memory ordering:
177
+ Rule of thumb: `.relaxed` for plain counters, `.acquiringAndReleasing` for
178
+ compare-and-exchange.
209
179
 
210
- | Ordering | Use case |
211
- |---|---|
212
- | `.relaxed` | Counters, statistics - no ordering guarantees needed |
213
- | `.acquiring` | Read that must see all writes before a corresponding release |
214
- | `.releasing` | Write that must be visible to a corresponding acquire |
215
- | `.acquiringAndReleasing` | Compare-and-swap, read-modify-write |
216
- | `.sequentiallyConsistent` | Strongest guarantee - rarely needed |
217
-
218
- **Guideline:** Use `.relaxed` for simple counters. Use
219
- `.acquiringAndReleasing` for compare-and-swap patterns. Avoid
220
- `.sequentiallyConsistent` unless you have a proven need - it is the most
221
- expensive ordering.
222
-
223
- ### When to Use Atomics vs Mutex
224
-
225
- - **Atomics:** Simple scalar values (Int, Bool, UInt64), single-field updates,
226
- counters, flags. Lock-free and very fast.
227
- - **Mutex:** Compound state (dictionaries, structs with multiple fields),
228
- multi-step operations that must be atomic as a group.
229
-
230
- ## Locks vs Actors: When to Use Each
231
-
232
- ### Use Actors When:
233
-
234
- - **Async isolation is natural.** The protected state is accessed from async
235
- contexts and you can afford the hop.
236
- - **Callers can suspend.** Actor-isolated APIs are `async` from outside the
237
- actor, so they fit task-based code but not synchronous C callbacks, real-time
238
- hooks, or other no-suspension call sites.
239
- - **Structured concurrency.** You want the compiler to enforce isolation
240
- boundaries and prevent data races statically.
241
- - **Most Swift code.** Actors are the default recommendation for shared mutable
242
- state in Swift concurrency.
243
- - **Complex state with multiple methods.** Actor isolation protects all
244
- properties and methods automatically.
180
+ ### Atomic or Mutex
181
+
182
+ - **Atomic:** a single scalar such as `Int`, `Bool` or `UInt64`, updated one
183
+ field at a time: counters, flags. Lock-free and very fast.
184
+ - **Mutex:** compound state such as dictionaries or structs with several
185
+ fields, and any sequence of steps that must happen as one unit.
186
+
187
+ ## Locks or actors
188
+
189
+ ### Choose an actor when
190
+
191
+ - the state is reached from async code and the cost of hopping is acceptable;
192
+ - callers can suspend. From outside, an actor's API is `async`, which rules it
193
+ out for synchronous C callbacks, real-time audio hooks and similar call sites;
194
+ - you want the compiler to enforce the isolation boundary;
195
+ - there is no special constraint: actors are the default for shared mutable
196
+ state in most Swift code;
197
+ - the state is rich and has many operations, since isolation covers all of
198
+ them at once.
245
199
 
246
200
  ```swift
247
- // GOOD: Actor for a cache accessed from async contexts
248
- actor ImageDownloader {
249
- private var cache: [URL: UIImage] = [:]
201
+ actor ArtworkLoader {
202
+ private var loaded: [URL: UIImage] = [:]
250
203
 
251
- func image(for url: URL) async throws -> UIImage {
252
- if let cached = cache[url] { return cached }
204
+ func artwork(at url: URL) async throws -> UIImage? {
205
+ if let image = loaded[url] { return image }
253
206
  let (data, _) = try await URLSession.shared.data(from: url)
254
- let image = UIImage(data: data)!
255
- cache[url] = image
207
+ let image = UIImage(data: data)
208
+ loaded[url] = image
256
209
  return image
257
210
  }
258
211
  }
259
212
  ```
260
213
 
261
- ### Use Mutex / Locks When:
214
+ ### Choose a lock when
262
215
 
263
- - **Synchronous access is required.** Callers cannot (or should not) be async.
264
- Accessing an actor from synchronous code requires `Task` and introduces
265
- unwanted asynchrony.
266
- - **Performance-critical paths.** Lock acquisition is nanoseconds; actor hops
267
- involve task scheduling. For tight loops or high-frequency access, a lock
268
- may be significantly faster.
269
- - **Bridging with C/ObjC.** C callbacks, delegate methods, or ObjC APIs that
270
- cannot be made async.
271
- - **Simple counters or flags.** `Atomic<Int>` or `Atomic<Bool>` is cheaper and
272
- simpler than creating an actor for a single value.
216
+ - callers must stay synchronous; calling an actor from sync code requires a
217
+ `Task` and makes the operation asynchronous;
218
+ - the path is hot: taking an uncontended lock costs nanoseconds while an actor
219
+ hop involves scheduling, so tight loops can be far faster with a lock;
220
+ - C or Objective-C callbacks, delegates or APIs that cannot become async touch
221
+ the state;
222
+ - the state is one counter or flag, where `Atomic<Int>` or `Atomic<Bool>` is
223
+ both cheaper and simpler than an actor.
273
224
 
274
225
  ```swift
275
- // GOOD: Mutex for synchronous, high-frequency access
276
- final class MetricsCollector: Sendable {
277
- let metrics = Mutex<[String: Int]>([:])
226
+ final class EventTally: Sendable {
227
+ private let counts = Mutex<[String: Int]>([:])
278
228
 
279
- // Called from tight loops, C callbacks, or synchronous code
280
- func increment(_ key: String) {
281
- metrics.withLock { $0[key, default: 0] += 1 }
229
+ func record(_ name: String) {
230
+ counts.withLock { $0[name, default: 0] += 1 }
282
231
  }
283
232
 
284
233
  func snapshot() -> [String: Int] {
285
- metrics.withLock { $0 }
234
+ counts.withLock { $0 }
286
235
  }
287
236
  }
288
237
  ```
289
238
 
290
- ### Decision Guide
291
-
292
- ```text
293
- Need shared mutable state protection?
294
- ├── Can all access be async?
295
- │ ├── Yes → Use an actor
296
- │ └── No → Use Mutex or OSAllocatedUnfairLock
297
- ├── Single scalar value (counter, flag)?
298
- │ └── Use Atomic<Value>
299
- ├── Performance-critical (nanosecond-level)?
300
- │ └── Use Mutex or Atomic
301
- └── Bridging C/ObjC callbacks?
302
- └── Use Mutex or OSAllocatedUnfairLock
303
- ```
239
+ ## Decision guide
240
+
241
+ | Situation | Use |
242
+ |---|---|
243
+ | Every access can be async | An actor |
244
+ | Some access must be synchronous | `Mutex`, or `OSAllocatedUnfairLock` below iOS 18 |
245
+ | One counter or flag | `Atomic<Value>` |
246
+ | Nanosecond-sensitive path | `Mutex` or `Atomic` |
247
+ | C or Objective-C callbacks | `Mutex` or `OSAllocatedUnfairLock` |
304
248
 
305
- ### Anti-Patterns
249
+ ## Anti-patterns
306
250
 
307
- **Never put locks inside actors.** An actor already serializes access; adding
308
- a lock creates double synchronization and risks deadlocks.
251
+ **A lock inside an actor.** The actor already serializes access; the lock adds
252
+ a second layer and a way to deadlock.
309
253
 
310
254
  ```swift
311
- // WRONG: Lock inside an actor - double synchronization
312
- actor BadCache {
313
- let lock = Mutex<[String: Data]>([:]) // Unnecessary!
314
- // The actor already protects its state
255
+ // Wrong
256
+ actor PrefetchQueueWrong {
257
+ private let pending = Mutex<[URL]>([])
315
258
  }
316
259
 
317
- // CORRECT: Just use the actor's built-in isolation
318
- actor GoodCache {
319
- var cache: [String: Data] = [:]
320
-
321
- func store(_ data: Data, key: String) {
322
- cache[key] = data
323
- }
260
+ // Right
261
+ actor PrefetchQueue {
262
+ private var pending: [URL] = []
263
+ func enqueue(_ url: URL) { pending.append(url) }
324
264
  }
325
265
  ```
326
266
 
327
- **Avoid reaching first for `DispatchSemaphore` or `NSLock` in modern Swift.**
328
- `NSLock` is `Sendable`, but `Mutex` (iOS 18+) and `OSAllocatedUnfairLock`
329
- (iOS 16+) make the protected state and lock ownership clearer in Swift
330
- concurrency code. Use `NSLock` only when compatibility or existing API shape
331
- requires it.
267
+ **Old primitives by reflex.** `DispatchSemaphore` and `NSLock` should not be the
268
+ first tool in modern Swift. `NSLock` is `Sendable`, so it is legal, but `Mutex`
269
+ (iOS 18) and `OSAllocatedUnfairLock` (iOS 16) tie the lock to the state it
270
+ protects and make ownership clearer. Keep `NSLock` for compatibility or where an
271
+ existing API expects it.
332
272
 
333
- **Never hold a lock across `await`.** This blocks the thread and can deadlock
334
- the cooperative thread pool.
273
+ **A lock held across `await`.** The thread stays blocked while the task is
274
+ suspended, which can exhaust or deadlock the cooperative pool.
335
275
 
336
276
  ```swift
337
- // WRONG: Holding lock across suspension point
338
- mutex.withLock { value in
339
- value = await fetchData() // DEADLOCK RISK
340
- }
277
+ // Wrong: suspends while holding the lock
278
+ // latest.withLock { $0 = await feed.fetch() }
341
279
 
342
- // CORRECT: Fetch first, then lock to update
343
- let data = await fetchData()
344
- mutex.withLock { value in
345
- value = data
346
- }
280
+ // Right: await first, lock only to publish the result
281
+ let fresh = await feed.fetch()
282
+ latest.withLock { $0 = fresh }
347
283
  ```