@mmerterden/multi-agent-pipeline 20.7.0 → 20.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +0 -10
  3. package/docs/facts.json +1 -1
  4. package/manifest.json +266 -267
  5. package/package.json +2 -2
  6. package/pipeline/scripts/_notices.mjs +1 -1
  7. package/pipeline/skills/.skill-manifest.json +68 -68
  8. package/pipeline/skills/shared/README.md +70 -70
  9. package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
  10. package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
  11. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
  12. package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
  13. package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
  14. package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
  15. package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
  16. package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
  17. package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
  18. package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
  19. package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
  20. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
  21. package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
  22. package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
  23. package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
  24. package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
  25. package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
  26. package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
  27. package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
  28. package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
  29. package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
  30. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
  31. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
  32. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
  33. package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
  34. package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
  35. package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
  36. package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
  37. package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
  38. package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
  39. package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
  40. package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
  41. package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
  42. package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
  43. package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
  44. package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
  45. package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
  46. package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
  47. package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
  48. package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
  49. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
  50. package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
  51. package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
  52. package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
  53. package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
  54. package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
  55. package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
  56. package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
  57. package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
  58. package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
  59. package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
  60. package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
  61. package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
  62. package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
  63. package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
  64. package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
  65. package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
  66. package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
  67. package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
  68. package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
  69. package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
  70. package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
  71. package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
  72. package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
  73. package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
  74. package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
  75. package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
  76. package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
  77. package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
  78. package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
  79. package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
  80. package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
  81. package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
  82. package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
  83. package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
  84. package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
  85. package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
  86. package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
  87. package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
  88. package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
  89. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
  90. package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
  91. package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
  92. package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
  93. package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
  94. package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
  95. package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
  96. package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
  97. package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
  98. package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
  99. package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
  100. package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
  101. package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
  102. package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
  103. package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
  104. package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
  105. package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
  106. package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
  107. package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
  108. package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
  109. package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
  110. package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
  111. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
  112. package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
  113. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
  114. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
  115. package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
  116. package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
  117. package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
  118. package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
  119. package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
  120. package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
  121. package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
  122. package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
  123. package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
  124. package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
  125. package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
  126. package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
  127. package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
  128. package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
  129. package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
  130. package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
  131. package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
  132. package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
  133. package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
  134. package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
  135. package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
  136. package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
  137. package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
  138. package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
  139. package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
  140. package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
  141. package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
  142. package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
  143. package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
  144. package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
  145. package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
  146. package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
  147. package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
  148. package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
  149. package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
  150. package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
  151. package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
  152. package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
  153. package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
  154. package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
  155. package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
  156. package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
  157. package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
  158. package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
  159. package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
  160. package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
  161. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
  162. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
  163. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
  164. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
  165. package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
  166. package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
  167. package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
  168. package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
  169. package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
  170. package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
  171. package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
  172. package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
  173. package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
  174. package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
  175. package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
  176. package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
  177. package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
  178. package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
  179. package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
  180. package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
  181. package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
  182. package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
  183. package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
  184. package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
  185. package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
  186. package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
  187. package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
  188. package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
  189. package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
  190. package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
  191. package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
  192. package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
  193. package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
  194. package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
  195. package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
  196. package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
  197. package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
  198. package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
  199. package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
  200. package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
  201. package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
  202. package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
  203. package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
  204. package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
  205. package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
  206. package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
  207. package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
  208. package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
  209. package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
  210. package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
  211. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
  212. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
  213. package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
  214. package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
  215. package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
  216. package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
  217. package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
  218. package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
  219. package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
  220. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
  221. package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
  222. package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
  223. package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
  224. package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
  225. package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
  226. package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
  227. package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
  228. package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
  229. package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
  230. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
  231. package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
  232. package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
  233. package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
  234. package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
  235. package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
  236. package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
  237. package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
  238. package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
  239. package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
  240. package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
  241. package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
  242. package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
  243. package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
  244. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
  245. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
  246. package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
  247. package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
  248. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
  249. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
  250. package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
  251. package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
  252. package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
  253. package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
  254. package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
  255. package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
  256. package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
  257. package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
  258. package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
  259. package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
  260. package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
  261. package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
  262. package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
  263. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
  264. package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
@@ -1,500 +1,456 @@
1
1
  ---
2
2
  name: coreml
3
- description: "Integrate Core ML models in iOS apps for on-device machine learning inference. Covers model loading (.mlmodel, .mlpackage, .mlmodelc), predictions with auto-generated classes and MLFeatureProvider, compute unit configuration (CPU, GPU, Neural Engine), MLTensor, VNCoreMLRequest, MLComputePlan, multi-model pipelines, and deployment strategies. Use when loading Core ML models, making predictions, configuring compute units, or profiling model performance."
3
+ description: "Swift-side Core ML: loading .mlmodel, .mlpackage and .mlmodelc, predictions via generated classes and MLFeatureProvider, compute units, async and stateful prediction with MLState, MLTensor, MLMultiArray, Vision CoreMLRequest and VNCoreMLRequest, MLComputePlan, multi-model pipelines, deployment and profiling. Use when integrating, reviewing, deploying or profiling a Core ML model in an app. Not for Python conversion (apple-on-device-ai)."
4
4
  metadata:
5
- source: "dpearson2699/swift-ios-skills (PolyForm Perimeter 1.0.0)"
5
+ source: multi-agent-pipeline
6
6
  ---
7
- # Core ML Swift Integration
8
7
 
9
- Load, configure, and run Core ML models in iOS apps. This skill covers the
10
- Swift side: model loading, prediction, MLTensor, profiling, and deployment.
11
- Target iOS 26+ with Swift 6.3, backward-compatible to iOS 14 unless noted.
8
+ # Core ML
12
9
 
13
- > **Scope boundary:** Python-side model conversion, optimization (quantization,
14
- > palettization, pruning), and framework selection live in the `apple-on-device-ai`
15
- > skill. This skill owns Swift integration only.
10
+ This skill covers the app side of Core ML: getting a model into memory,
11
+ feeding it, reading its output, and shipping it. Baseline: iOS 26 and Swift
12
+ 6.3, with each API's lower floor stated where it matters (much of Core ML goes
13
+ back to iOS 14 or earlier).
16
14
 
17
- See [references/coreml-swift-integration.md](references/coreml-swift-integration.md) for complete code patterns including
18
- actor-based caching, batch inference, image preprocessing, and testing.
15
+ Out of scope here: converting or compressing models in Python (quantization,
16
+ palettization, pruning) and choosing between on-device AI frameworks; those
17
+ belong to `apple-on-device-ai`. Text recognition, barcodes and document
18
+ scanning with Vision belong to `vision-framework`.
19
19
 
20
- ## Contents
20
+ Longer code (an actor that owns models, SwiftUI wiring, custom feature
21
+ providers, stateful sessions, pixel buffers, tensors, Vision pipelines,
22
+ NaturalLanguage, compute plans, lifecycle, errors, tests) is in
23
+ `references/coreml-swift-integration.md`.
21
24
 
22
- - [Loading Models](#loading-models)
23
- - [Model Configuration](#model-configuration)
24
- - [Making Predictions](#making-predictions)
25
- - [MLTensor (iOS 18+)](#mltensor-ios-18)
26
- - [Working with MLMultiArray](#working-with-mlmultiarray)
27
- - [Image Preprocessing](#image-preprocessing)
28
- - [Multi-Model Pipelines](#multi-model-pipelines)
29
- - [Vision Integration](#vision-integration)
30
- - [Performance Profiling](#performance-profiling)
31
- - [Model Deployment](#model-deployment)
32
- - [Memory Management](#memory-management)
33
- - [Common Mistakes](#common-mistakes)
34
- - [Review Checklist](#review-checklist)
35
- - [References](#references)
25
+ ## Loading a model
36
26
 
37
- ## Loading Models
38
-
39
- ### Auto-Generated Classes
40
-
41
- When you add a `.mlmodel` or `.mlpackage` to an app target, Xcode generates a Swift
42
- class with typed input/output. Use this whenever possible.
27
+ **Generated class.** Drop a `.mlmodel` or `.mlpackage` into a target and Xcode
28
+ generates a Swift class with typed inputs and outputs. Use it whenever it
29
+ exists.
43
30
 
44
31
  ```swift
45
32
  import CoreML
46
33
 
47
- let config = MLModelConfiguration()
48
- config.computeUnits = .all
49
-
50
- let model = try MyImageClassifier(configuration: config)
34
+ func makeDenoiser() throws -> PhotoDenoiser {
35
+ let settings = MLModelConfiguration()
36
+ settings.computeUnits = .all
37
+ return try PhotoDenoiser(configuration: settings)
38
+ }
51
39
  ```
52
40
 
53
- ### Manual Loading
54
-
55
- Load from a URL when the model is downloaded at runtime or stored outside the
56
- bundle.
41
+ **From a URL.** For models that are downloaded or stored outside the bundle:
57
42
 
58
43
  ```swift
59
- let modelURL = Bundle.main.url(
60
- forResource: "MyModel", withExtension: "mlmodelc"
61
- )!
62
- let model = try MLModel(contentsOf: modelURL, configuration: config)
63
- ```
64
-
65
- ### Async Loading (iOS 15+)
66
-
67
- Load models without blocking the main thread. Prefer this for large models.
44
+ import CoreML
68
45
 
69
- ```swift
70
- let model = try await MLModel.load(
71
- contentsOf: modelURL,
72
- configuration: config
73
- )
46
+ func bundledModel(named name: String) throws -> MLModel {
47
+ guard let url = Bundle.main.url(forResource: name, withExtension: "mlmodelc") else {
48
+ throw CocoaError(.fileNoSuchFile)
49
+ }
50
+ return try MLModel(contentsOf: url, configuration: MLModelConfiguration())
51
+ }
74
52
  ```
75
53
 
76
- ### Compile at Runtime (iOS 16+)
77
-
78
- Compile a `.mlpackage` or `.mlmodel` to `.mlmodelc` on device. Useful for
79
- models downloaded from a server. Do this once per model version, not on every
80
- launch.
54
+ **Asynchronously.** `MLModel.load(contentsOf:configuration:)` (async, iOS 15+)
55
+ keeps large models from stalling the main thread and is the preferred loader.
81
56
 
82
- ```swift
83
- let compiledURL = try await MLModel.compileModel(at: packageURL)
84
- let model = try await MLModel.load(contentsOf: compiledURL, configuration: config)
85
- ```
57
+ **Compiling on device.** `MLModel.compileModel(at:)` (async form, iOS 16+)
58
+ turns a `.mlmodel` or `.mlpackage` into a `.mlmodelc` on the device, which is
59
+ how server-delivered models become loadable. Two rules travel together:
86
60
 
87
- Cache the compiled URL -- recompiling on every launch is a bug. Copy
88
- `compiledURL` to a persistent location (e.g., Application Support). When
89
- reviewing runtime-loaded models, call out both facts together: async
90
- `MLModel.compileModel(at:)` is iOS 16+, and compiled models must be cached so the
91
- app does not recompile on every launch.
61
+ 1. Compile once per model version, never on every launch; recompiling at each
62
+ start is a bug.
63
+ 2. The returned URL points into a temporary location. Move the `.mlmodelc`
64
+ somewhere durable such as Application Support and reuse it.
92
65
 
93
- ## Model Configuration
66
+ When reviewing runtime-loaded models, state both: the async compile API needs
67
+ iOS 16, and its output must be cached.
94
68
 
95
- `MLModelConfiguration` controls compute units, GPU access, and model parameters.
69
+ ## Configuration and compute units
96
70
 
97
- ### Compute Units Decision Table
71
+ `MLModelConfiguration` chooses hardware, GPU precision and model parameters.
98
72
 
99
- | Value | Uses | When to Choose |
73
+ | `computeUnits` | Hardware | When |
100
74
  |---|---|---|
101
- | `.all` | CPU + GPU + Neural Engine | Default. Let the system decide. |
102
- | `.cpuOnly` | CPU | Deterministic tests, CPU-only fallbacks, or constrained work after profiling shows accelerator policy, contention, thermal state, or energy budget is the limiting factor. |
103
- | `.cpuAndGPU` | CPU + GPU | Need GPU but model has ops unsupported by ANE. |
104
- | `.cpuAndNeuralEngine` (iOS 16+) | CPU + Neural Engine | Best energy efficiency for compatible models. |
75
+ | `.all` (default) | CPU, GPU, Neural Engine; the system decides | Almost always |
76
+ | `.cpuOnly` | CPU | Deterministic tests, CPU-only fallbacks, or when profiling shows accelerator policy, contention, thermal state or energy budget is the constraint |
77
+ | `.cpuAndGPU` | CPU and GPU | The model needs the GPU but has operations the Neural Engine cannot run |
78
+ | `.cpuAndNeuralEngine` (iOS 16+) | CPU and Neural Engine | Best energy efficiency for models the Neural Engine fully supports |
105
79
 
106
80
  ```swift
107
- let config = MLModelConfiguration()
108
- config.computeUnits = .cpuAndNeuralEngine
109
-
110
- // Optional fallback for constrained work after profiling and policy review
111
- config.computeUnits = .cpuOnly
112
- ```
113
-
114
- ### Configuration Properties
81
+ import CoreML
115
82
 
116
- ```swift
117
- let config = MLModelConfiguration()
118
- config.computeUnits = .all
119
- config.allowLowPrecisionAccumulationOnGPU = true // faster, slight precision loss
83
+ func efficientSettings(fallbackToCPU: Bool) -> MLModelConfiguration {
84
+ let settings = MLModelConfiguration()
85
+ settings.computeUnits = fallbackToCPU ? .cpuOnly : .cpuAndNeuralEngine
86
+ settings.allowLowPrecisionAccumulationOnGPU = true
87
+ return settings
88
+ }
120
89
  ```
121
90
 
122
- ## Making Predictions
91
+ `allowLowPrecisionAccumulationOnGPU` buys speed for a small loss of precision.
92
+ Choose `.cpuOnly` only after profiling says so.
123
93
 
124
- ### With Auto-Generated Classes
94
+ ## Predictions
125
95
 
126
- The generated class provides typed input/output structs.
96
+ **Generated class:**
127
97
 
128
98
  ```swift
129
- let model = try MyImageClassifier(configuration: config)
130
- let input = MyImageClassifierInput(image: pixelBuffer)
131
- let output = try model.prediction(input: input)
132
- print(output.classLabel) // "golden_retriever"
133
- print(output.classLabelProbs) // ["golden_retriever": 0.95, ...]
99
+ import CoreML
100
+
101
+ func tagScene(_ frame: CVPixelBuffer, with model: SceneTagger) throws -> (String, Double) {
102
+ let result = try model.prediction(input: SceneTaggerInput(image: frame))
103
+ return (result.classLabel, result.classLabelProbs[result.classLabel] ?? 0)
104
+ }
134
105
  ```
135
106
 
136
- ### With MLDictionaryFeatureProvider
107
+ `classLabel` is the winning label and `classLabelProbs` maps every label to
108
+ its probability.
137
109
 
138
- Use when inputs are dynamic or not known at compile time.
110
+ **Dictionary provider**, for inputs only known at run time:
139
111
 
140
112
  ```swift
141
- let inputFeatures = try MLDictionaryFeatureProvider(dictionary: [
142
- "image": MLFeatureValue(pixelBuffer: pixelBuffer),
143
- "confidence_threshold": MLFeatureValue(double: 0.5),
144
- ])
145
- let output = try model.prediction(from: inputFeatures)
146
- let label = output.featureValue(for: "classLabel")?.stringValue
147
- ```
113
+ import CoreML
148
114
 
149
- ### Prediction Inside Async Workflows
115
+ func tagWithThreshold(_ frame: CVPixelBuffer, cutoff: Double, model: MLModel) async throws -> String? {
116
+ let inputs = try MLDictionaryFeatureProvider(dictionary: [
117
+ "image": MLFeatureValue(pixelBuffer: frame),
118
+ "threshold": MLFeatureValue(double: cutoff)
119
+ ])
120
+ let outputs = try await model.prediction(from: inputs)
121
+ return outputs.featureValue(for: "label")?.stringValue
122
+ }
123
+ ```
150
124
 
151
- `MLModel.prediction(...)` is synchronous. In async pipelines, keep model loading
152
- async, then run prediction from an actor or non-main task without adding `await`
153
- to the prediction call.
125
+ ### Sync or async prediction
154
126
 
155
- ```swift
156
- let output = try model.prediction(from: inputFeatures)
157
- ```
127
+ - `prediction(from:)` and `prediction(from:options:)` exist in a synchronous
128
+ throwing form on every supported OS.
129
+ - From iOS 17 there is also `prediction(from:options:) async throws`, which
130
+ may be called concurrently on the same model. Inside an `async` function the
131
+ compiler resolves to that overload, so the call needs `try await`; leaving
132
+ out `await` there does not compile.
133
+ - In synchronous code (a serial queue, a synchronous actor method) the
134
+ synchronous form is used without `await`.
135
+ - Loading stays async either way (`MLModel.load`).
158
136
 
159
- ### Batch Prediction
137
+ ### Batches
160
138
 
161
- Process multiple inputs in one call for better throughput.
139
+ Processing several inputs per call raises throughput:
162
140
 
163
141
  ```swift
164
- let batchInputs = try MLArrayBatchProvider(array: inputs.map { input in
165
- try MLDictionaryFeatureProvider(dictionary: ["image": MLFeatureValue(pixelBuffer: input)])
166
- })
167
- let batchOutput = try model.predictions(fromBatch: batchInputs)
168
- for i in 0..<batchOutput.count {
169
- let result = batchOutput.features(at: i)
170
- print(result.featureValue(for: "classLabel")?.stringValue ?? "unknown")
142
+ import CoreML
143
+
144
+ func labels(for frames: [CVPixelBuffer], model: MLModel) throws -> [String] {
145
+ let rows = try frames.map { try MLDictionaryFeatureProvider(dictionary: ["image": MLFeatureValue(pixelBuffer: $0)]) }
146
+ let answers = try model.predictions(fromBatch: MLArrayBatchProvider(array: rows))
147
+ return (0..<answers.count).compactMap { answers.features(at: $0).featureValue(for: "label")?.stringValue }
171
148
  }
172
149
  ```
173
150
 
174
- Use `predictions(fromBatch:)` when batching without explicit
175
- `MLPredictionOptions`. Use `predictions(from:options:)` only when passing both an
176
- `MLBatchProvider` and `MLPredictionOptions`; `predictions(from:)` by itself is
177
- not the no-options batch API.
151
+ Two batch spellings are valid: `predictions(fromBatch:)` without options, and
152
+ `predictions(from:options:)` when you pass an `MLBatchProvider` together with
153
+ `MLPredictionOptions`. There is no options-free `predictions(from:)`; do not
154
+ write one.
178
155
 
179
- ### Stateful Prediction (iOS 18+)
156
+ ### Stateful models with MLState (iOS 18+)
180
157
 
181
- Use `MLState` for models that maintain state across predictions (sequence models,
182
- LLMs, audio accumulators). Create state once and pass it to each prediction call.
158
+ Sequence models (language models, streaming audio, time series) keep context
159
+ between calls. Create a state once per stream and pass it to every call.
183
160
 
184
161
  ```swift
185
- let state = model.makeState()
162
+ import CoreML
186
163
 
187
- // Each synchronous prediction carries forward the internal model state
188
- for frame in audioFrames {
189
- let input = try MLDictionaryFeatureProvider(dictionary: [
190
- "audio_features": MLFeatureValue(multiArray: frame)
191
- ])
192
- let output = try model.prediction(from: input, using: state)
193
- let classification = output.featureValue(for: "label")?.stringValue
164
+ func classifyStream(_ windows: [MLMultiArray], model: MLModel) throws -> [String] {
165
+ let memory = model.makeState()
166
+ return try windows.compactMap { window in
167
+ let input = try MLDictionaryFeatureProvider(dictionary: ["samples": MLFeatureValue(multiArray: window)])
168
+ return try model.prediction(from: input, using: memory).featureValue(for: "label")?.stringValue
169
+ }
194
170
  }
195
171
  ```
196
172
 
197
- `MLState` is `Sendable`, but `Sendable` does not make one state safe for
198
- concurrent inference. Predictions using the same state must be serialized; do
199
- not read or write state buffers while a prediction is in flight. Call
200
- `model.makeState()` for each independent concurrent stream. If you need
201
- `MLPredictionOptions`, iOS 18+ also provides the async
202
- `prediction(from:using:options:)` overload; the same one-in-flight-per-state rule
203
- still applies.
173
+ Rules for `MLState`:
174
+
175
+ - It is `Sendable`, which lets it move between concurrency domains. It does
176
+ not make concurrent predictions on one state safe: run them one at a time.
177
+ - Do not read or write the state's buffers while a prediction is running.
178
+ - Independent concurrent streams each get their own `model.makeState()`.
179
+ - The async `prediction(from:using:options:)` (iOS 18) is there when you need
180
+ options or are in async code; the same one-prediction-in-flight rule holds.
181
+ The synchronous `prediction(from:using:)` is for synchronous loops.
204
182
 
205
183
  ## MLTensor (iOS 18+)
206
184
 
207
- `MLTensor` is a Swift-native multidimensional array for pre/post-processing.
208
- Operations run lazily -- call `await tensor.shapedArray(of:)` to materialize results.
185
+ `MLTensor` is a Swift multidimensional array for pre- and post-processing.
186
+ Operations are lazy; results materialize only when you await
187
+ `shapedArray(of:)`.
209
188
 
210
189
  ```swift
211
190
  import CoreML
212
191
 
213
- // Creation
214
- let tensor = MLTensor([1.0, 2.0, 3.0, 4.0])
215
- let zeros = MLTensor(zeros: [3, 224, 224], scalarType: Float.self)
216
-
217
- // Reshaping
218
- let reshaped = tensor.reshaped(to: [2, 2])
219
-
220
- // Math operations
221
- let softmaxed = tensor.softmax(alongAxis: -1)
222
- let centered = tensor - tensor.mean()
192
+ func normalizedScores(_ logits: [Float]) async -> MLMultiArray {
193
+ let raw = MLTensor(logits).reshaped(to: [1, logits.count])
194
+ let centered = raw - raw.mean()
195
+ let probabilities = centered.softmax(alongAxis: -1)
196
+ let shaped = await probabilities.shapedArray(of: Float.self)
197
+ return MLMultiArray(shaped)
198
+ }
223
199
 
224
- // Interop with MLShapedArray / MLMultiArray
225
- let shaped = await tensor.shapedArray(of: Float.self)
226
- let multiArray = try MLMultiArray(shaped)
227
- let shapedAgain = MLShapedArray<Float>(multiArray)
200
+ func tensor(from array: MLMultiArray) -> MLTensor {
201
+ MLTensor(MLShapedArray<Float>(array))
202
+ }
228
203
  ```
229
204
 
230
- Do not invent `MLTensor` APIs for statistics or bridging. Avoid examples such as
231
- `MLTensor(multiArray)`, `tensor.std()`, `tensor.standardDeviation()`, direct
232
- lazy-buffer access, or synchronous extraction; perform unsupported DSP/statistics
233
- outside the tensor pipeline or with source-confirmed tensor operations.
205
+ Stay with documented operations. There is no `MLTensor(multiArray)`
206
+ initializer, no `std()` or `standardDeviation()`, no direct access to the lazy
207
+ storage, and no synchronous extraction. Go through `MLShapedArray` for
208
+ conversions, and build statistics from documented pieces (`mean()`,
209
+ `squareRoot()`, arithmetic) or do them outside the tensor pipeline.
210
+ `MLTensor(zeros:scalarType:)` and `MLTensor(ones:scalarType:)` create filled
211
+ tensors.
234
212
 
235
- ## Working with MLMultiArray
213
+ ## MLMultiArray
236
214
 
237
- `MLMultiArray` is the primary data exchange type for non-image model inputs and
238
- outputs. Use it when the auto-generated class expects array-type features.
215
+ `MLMultiArray` is the exchange type for non-image inputs and outputs; generated
216
+ classes use it for array features.
239
217
 
240
218
  ```swift
241
- // Create a 3D array: [batch, sequence, features]
242
- let array = try MLMultiArray(shape: [1, 128, 768], dataType: .float32)
219
+ import CoreML
243
220
 
244
- // Write values
245
- for i in 0..<128 {
246
- array[[0, i, 0] as [NSNumber]] = NSNumber(value: Float(i))
221
+ func embeddingInput(tokens: Int, width: Int) throws -> MLMultiArray {
222
+ let grid = try MLMultiArray(shape: [1, NSNumber(value: tokens), NSNumber(value: width)], dataType: .float32)
223
+ grid[[0, 0, 0] as [NSNumber]] = 0.25
224
+ return grid
247
225
  }
248
226
 
249
- // Read values
250
- let value = array[[0, 0, 0] as [NSNumber]].floatValue
227
+ func firstValue(of grid: MLMultiArray) -> Float {
228
+ grid[[0, 0, 0] as [NSNumber]].floatValue
229
+ }
251
230
 
252
- let data: [Float] = [1.0, 2.0, 3.0]
253
- let shaped = MLShapedArray(scalars: data, shape: [3])
254
- let fromShaped = try MLMultiArray(shaped)
231
+ func packed(_ values: [Float]) -> MLMultiArray {
232
+ MLMultiArray(MLShapedArray<Float>(scalars: values, shape: [1, values.count]))
233
+ }
255
234
  ```
256
235
 
257
- See [references/coreml-swift-integration.md](references/coreml-swift-integration.md) for advanced MLMultiArray patterns
258
- including NLP tokenization and audio feature extraction.
236
+ The shape reads batch, sequence, features. Tokenized text and audio feature
237
+ patterns are in the reference.
259
238
 
260
- ## Image Preprocessing
239
+ ## Image input
261
240
 
262
- Image models expect `CVPixelBuffer` input. Use `CGImage` conversion for photos
263
- from the camera or photo library. Vision's `VNCoreMLRequest` handles this
264
- automatically; manual conversion is needed only for direct `MLModel` prediction.
241
+ Image models take a `CVPixelBuffer`. When Vision drives the model
242
+ (`CoreMLRequest` or `VNCoreMLRequest`), conversion happens automatically; the
243
+ manual path is only for direct `MLModel` predictions.
265
244
 
266
245
  ```swift
246
+ import CoreGraphics
267
247
  import CoreVideo
268
248
 
269
- func createPixelBuffer(from cgImage: CGImage, width: Int, height: Int) -> CVPixelBuffer? {
270
- var pixelBuffer: CVPixelBuffer?
271
- let attrs: [CFString: Any] = [
249
+ func pixelBuffer(from picture: CGImage, side: Int) -> CVPixelBuffer? {
250
+ let options = [
272
251
  kCVPixelBufferCGImageCompatibilityKey: true,
273
- kCVPixelBufferCGBitmapContextCompatibilityKey: true,
274
- ]
275
- CVPixelBufferCreate(kCFAllocatorDefault, width, height,
276
- kCVPixelFormatType_32ARGB, attrs as CFDictionary, &pixelBuffer)
277
-
278
- guard let buffer = pixelBuffer else { return nil }
252
+ kCVPixelBufferCGBitmapContextCompatibilityKey: true
253
+ ] as CFDictionary
254
+ var buffer: CVPixelBuffer?
255
+ guard CVPixelBufferCreate(kCFAllocatorDefault, side, side, kCVPixelFormatType_32ARGB, options, &buffer) == kCVReturnSuccess,
256
+ let buffer else { return nil }
279
257
  CVPixelBufferLockBaseAddress(buffer, [])
258
+ defer { CVPixelBufferUnlockBaseAddress(buffer, []) }
280
259
  let context = CGContext(
281
- data: CVPixelBufferGetBaseAddress(buffer),
282
- width: width, height: height,
260
+ data: CVPixelBufferGetBaseAddress(buffer), width: side, height: side,
283
261
  bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(buffer),
284
- space: CGColorSpaceCreateDeviceRGB(),
285
- bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue
262
+ space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue
286
263
  )
287
- context?.draw(cgImage, in: CGRect(x: 0, y: 0, width: width, height: height))
288
- CVPixelBufferUnlockBaseAddress(buffer, [])
264
+ context?.draw(picture, in: CGRect(x: 0, y: 0, width: side, height: side))
289
265
  return buffer
290
266
  }
291
267
  ```
292
268
 
293
- For additional preprocessing patterns (normalization, center-cropping), see
294
- [references/coreml-swift-integration.md](references/coreml-swift-integration.md).
269
+ Normalization and center-crop helpers are in the reference.
295
270
 
296
- ## Multi-Model Pipelines
271
+ ## Chaining models
297
272
 
298
- Chain models when preprocessing or postprocessing requires a separate model.
273
+ When pre- or post-processing is its own model, call them in order:
299
274
 
300
275
  ```swift
301
- // Sequential inference: preprocessor -> main model -> postprocessor
302
- let preprocessed = try preprocessor.prediction(from: rawInput)
303
- let mainOutput = try mainModel.prediction(from: preprocessed)
304
- let finalOutput = try postprocessor.prediction(from: mainOutput)
305
- ```
276
+ import CoreML
306
277
 
307
- For Xcode-managed pipelines, use the pipeline model type in the `.mlpackage`.
308
- Each sub-model runs on its optimal compute unit.
278
+ func runChain(_ input: MLFeatureProvider, stages: [MLModel]) async throws -> MLFeatureProvider {
279
+ var current = input
280
+ for stage in stages {
281
+ current = try await stage.prediction(from: current)
282
+ }
283
+ return current
284
+ }
285
+ ```
309
286
 
310
- ## Vision Integration
287
+ For chains that Xcode manages, build a pipeline model inside the `.mlpackage`;
288
+ each sub-model then runs on the compute unit that suits it.
311
289
 
312
- Use Vision to run Core ML image models with automatic image preprocessing
313
- (resizing, normalization, color space, orientation).
290
+ ## Through Vision
314
291
 
315
- ### Modern: CoreMLRequest (iOS 18+)
292
+ Vision takes care of resizing, cropping, normalization, color space and
293
+ orientation.
316
294
 
317
295
  ```swift
318
- import Vision
319
296
  import CoreML
297
+ import Vision
320
298
 
321
- let model = try MLModel(contentsOf: modelURL, configuration: config)
322
- let request = CoreMLRequest(model: .init(model))
323
- let results = try await request.perform(on: cgImage)
324
-
325
- if let classification = results.first as? ClassificationObservation {
326
- print("\(classification.identifier): \(classification.confidence)")
299
+ func dominantLabel(in photo: CGImage, model: MLModel) async throws -> (String, Float)? {
300
+ let request = CoreMLRequest(model: try CoreMLModelContainer(model: model))
301
+ let observations = try await request.perform(on: photo)
302
+ guard let top = observations.first as? ClassificationObservation else { return nil }
303
+ return (top.identifier, top.confidence)
327
304
  }
328
305
  ```
329
306
 
330
- ### Legacy: VNCoreMLRequest
307
+ `CoreMLRequest` needs iOS 18. The legacy route for detection models:
331
308
 
332
309
  ```swift
333
- let vnModel = try VNCoreMLModel(for: model)
334
- let request = VNCoreMLRequest(model: vnModel) { request, error in
335
- guard let results = request.results as? [VNRecognizedObjectObservation] else { return }
336
- for observation in results {
337
- let label = observation.labels.first?.identifier ?? "unknown"
338
- let confidence = observation.labels.first?.confidence ?? 0
339
- let boundingBox = observation.boundingBox // normalized coordinates
340
- print("\(label): \(confidence) at \(boundingBox)")
310
+ import CoreML
311
+ import Vision
312
+
313
+ func legacyDetections(in frame: CVPixelBuffer, model: MLModel) throws -> [(String, Float, CGRect)] {
314
+ let request = VNCoreMLRequest(model: try VNCoreMLModel(for: model))
315
+ request.imageCropAndScaleOption = .scaleFill
316
+ try VNImageRequestHandler(cvPixelBuffer: frame).perform([request])
317
+ let objects = request.results as? [VNRecognizedObjectObservation] ?? []
318
+ return objects.compactMap { object in
319
+ guard let label = object.labels.first else { return nil }
320
+ return (label.identifier, label.confidence, object.boundingBox)
341
321
  }
342
322
  }
343
- request.imageCropAndScaleOption = .scaleFill
344
-
345
- let handler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer)
346
- try handler.perform([request])
347
323
  ```
348
324
 
349
- > For complete Vision framework patterns (text recognition, barcode detection,
350
- > document scanning), see the `vision-framework` skill.
351
-
352
- ## Performance Profiling
325
+ `boundingBox` is normalized. Everything else about Vision (OCR, barcodes,
326
+ documents) is in `vision-framework`.
353
327
 
354
- ### MLComputePlan (iOS 17.4+)
328
+ ## Profiling
355
329
 
356
- Inspect which compute device each operation will use before running predictions.
330
+ `MLComputePlan` (iOS 17.4+) tells you, before any prediction, which device
331
+ each operation prefers and how expensive it is:
357
332
 
358
333
  ```swift
359
- let computePlan = try await MLComputePlan.load(
360
- contentsOf: modelURL, configuration: config
361
- )
362
- guard case let .program(program) = computePlan.modelStructure else { return }
363
- guard let mainFunction = program.functions["main"] else { return }
364
-
365
- for operation in mainFunction.block.operations {
366
- let deviceUsage = computePlan.deviceUsage(for: operation)
367
- let estimatedCost = computePlan.estimatedCost(of: operation)
368
- print("\(operation.operatorName): \(String(describing: deviceUsage?.preferred))")
334
+ import CoreML
335
+
336
+ func opsOffAccelerators(modelURL: URL) async throws -> [String] {
337
+ let plan = try await MLComputePlan.load(contentsOf: modelURL, configuration: MLModelConfiguration())
338
+ guard case .program(let program) = plan.modelStructure,
339
+ let entry = program.functions["main"] else { return [] }
340
+ return entry.block.operations.compactMap { op in
341
+ guard let usage = plan.deviceUsage(for: op), case .cpu = usage.preferred else { return nil }
342
+ let cost = plan.estimatedCost(of: op)?.weight ?? 0
343
+ return "\(op.operatorName) cost \(cost)"
344
+ }
369
345
  }
370
346
  ```
371
347
 
372
- ### Instruments
373
-
374
- Use the **Core ML** instrument template in Instruments to profile:
375
- - Model load time
376
- - Prediction latency (per-operation breakdown)
377
- - Compute device dispatch (CPU/GPU/ANE per operation)
378
- - Memory allocation
379
-
380
- Run outside the debugger for accurate results (Xcode: Product > Profile).
381
-
382
- ## Model Deployment
348
+ The Instruments Core ML template shows load time, per-prediction latency with a
349
+ per-operation breakdown, which device each operation ran on, and memory.
350
+ Profile with Product > Profile, not under the debugger, or the numbers are
351
+ not representative.
383
352
 
384
- ### Bundle vs Downloaded Assets
353
+ ## Deployment
385
354
 
386
- | Strategy | Pros | Cons |
355
+ | Strategy | Strength | Cost |
387
356
  |---|---|---|
388
- | Bundle in app | Instant availability, works offline | Increases app download size |
389
- | Background Assets | Preferred for large or updateable model assets | Requires asset-pack setup |
390
- | On-demand resources | Smaller initial download for existing ODR apps | Legacy technology; prefer Background Assets for new work |
391
- | CloudKit / server | Maximum flexibility | Requires network, longer setup |
392
-
393
- ### Size Considerations
394
-
395
- - For iOS/iPadOS 18+, App Store Connect lists a 4 GB thinned app bundle limit
396
- and 8 GB thinned ODR asset-pack limit.
397
- - Prefer Background Assets for new large or updateable model assets; keep ODR
398
- guidance for existing projects that already use it.
399
- - Pre-compile to `.mlmodelc` to skip on-device compilation
400
- - For downloaded `.mlmodel` or `.mlpackage` files, compile once with
401
- `MLModel.compileModel(at:)`, move the resulting `.mlmodelc` out of Core ML's
402
- temporary location, and cache it by model version.
403
- - Validate memory and performance on physical target devices, especially the
404
- lowest-memory supported device. Check model load, first prediction, repeated
405
- predictions, background/foreground transitions, and low-memory behavior.
406
-
407
- For Background Assets, make the asset pack locally available, resolve the model
408
- URL, then load the compiled model with `MLModel.load(contentsOf:configuration:)`.
357
+ | In the app bundle | Available instantly and offline | Bigger download |
358
+ | Background Assets | Preferred for large or updatable models | Asset pack setup |
359
+ | On-demand resources | Smaller first download for apps already on ODR | Legacy; choose Background Assets for new work |
360
+ | CloudKit or own server | Most flexible | Needs network, more plumbing |
361
+
362
+ - Size ceilings change; check the current App Store Connect limits. For
363
+ iOS/iPadOS 18 and later they list 4 GB for the thinned app bundle and 8 GB
364
+ per thinned on-demand-resource asset pack.
365
+ - Keep on-demand-resource guidance for projects that already use it.
366
+ - Ship `.mlmodelc` (precompiled) so the device does not compile at first use.
367
+ - For downloaded `.mlmodel`/`.mlpackage` files: compile once with
368
+ `compileModel(at:)`, move the result out of Core ML's temporary directory,
369
+ and key the cache by model version.
370
+ - With Background Assets: make the asset pack locally available, resolve the
371
+ model's URL inside it, then `MLModel.load(contentsOf:configuration:)`.
372
+ - Test on physical devices, above all the lowest-memory one you support: load
373
+ time, first prediction, repeated predictions, background and foreground
374
+ transitions, and low-memory behavior.
375
+
376
+ On-demand resources, for apps that already use them:
409
377
 
410
378
  ```swift
411
- // Existing On-Demand Resources project
412
- let request = NSBundleResourceRequest(tags: ["ml-model-v2"])
413
- try await request.beginAccessingResources()
414
- let modelURL = Bundle.main.url(forResource: "LargeModel", withExtension: "mlmodelc")!
415
- let model = try await MLModel.load(contentsOf: modelURL, configuration: config)
416
- // Call request.endAccessingResources() when done
379
+ import CoreML
380
+
381
+ func loadTaggedModel(tag: String, name: String) async throws -> (MLModel, NSBundleResourceRequest) {
382
+ let request = NSBundleResourceRequest(tags: [tag])
383
+ try await request.beginAccessingResources()
384
+ guard let url = Bundle.main.url(forResource: name, withExtension: "mlmodelc") else {
385
+ request.endAccessingResources()
386
+ throw CocoaError(.fileNoSuchFile)
387
+ }
388
+ let model = try await MLModel.load(contentsOf: url, configuration: MLModelConfiguration())
389
+ return (model, request)
390
+ }
417
391
  ```
418
392
 
419
- ## Memory Management
420
-
421
- - **Unload on background:** Release model references when the app enters background
422
- to free GPU/ANE memory. Reload on foreground return.
423
- - **Choose compute units by context:** use `.all` by default. Consider `.cpuOnly`
424
- only when profiling or app policy shows accelerator contention, thermal state,
425
- energy budget, deterministic testing, or a legitimate background execution
426
- constraint makes CPU the right tradeoff.
427
- - **Share model instances:** Never create multiple `MLModel` instances from the same
428
- compiled model. Use an actor to provide shared access.
429
- - **Monitor memory pressure:** Large models (>100 MB) can trigger memory warnings.
430
- Register for `UIApplication.didReceiveMemoryWarningNotification` and release
431
- cached models when under pressure.
432
-
433
- See [references/coreml-swift-integration.md](references/coreml-swift-integration.md) for an actor-based model manager with
434
- lifecycle-aware loading and cache eviction.
435
-
436
- ## Common Mistakes
437
-
438
- **DON'T:** Load models on the main thread.
439
- **DO:** Use `MLModel.load(contentsOf:configuration:)` async API or load on a background actor.
440
- **Why:** Large models can take seconds to load, freezing the UI.
441
-
442
- **DON'T:** Recompile `.mlpackage` to `.mlmodelc` on every app launch.
443
- **DO:** Compile once with `MLModel.compileModel(at:)` and cache the compiled URL persistently.
444
- **Why:** Compilation is expensive. Cache the `.mlmodelc` in Application Support.
445
-
446
- **DON'T:** Hardcode `.cpuOnly` unless you have a specific reason.
447
- **DO:** Use `.all` and let the system choose the optimal compute unit.
448
- **Why:** `.all` enables Neural Engine and GPU, which are faster and more energy-efficient.
449
-
450
- **DON'T:** Claim GPU or Neural Engine are categorically unavailable for all
451
- background-adjacent work.
452
- **DO:** Treat background execution as policy-, mode-, contention-, thermal-, and
453
- energy-dependent, and profile the actual workload on device.
454
- **Why:** Apps may be suspended, throttled, or limited by their background mode;
455
- `.cpuOnly` is a tradeoff, not a universal requirement.
456
-
457
- **DON'T:** Ignore `MLFeatureValue` type mismatches between input and model expectations.
458
- **DO:** Match types exactly -- use `MLFeatureValue(pixelBuffer:)` for images, not raw data.
459
- **Why:** Type mismatches cause cryptic runtime crashes or silent incorrect results.
460
-
461
- **DON'T:** Create a new `MLModel` instance for every prediction.
462
- **DO:** Load once and reuse. Use an actor to manage the model lifecycle.
463
- **Why:** Model loading allocates significant memory and compute resources.
464
-
465
- **DON'T:** Skip error handling for model loading and prediction.
466
- **DO:** Catch errors and provide fallback behavior when the model fails.
467
- **Why:** Models can fail to load on older devices or when resources are constrained.
468
-
469
- **DON'T:** Assume all operations run on the Neural Engine.
470
- **DO:** Use `MLComputePlan` (iOS 17.4+) to verify device dispatch per operation.
471
- **Why:** Unsupported operations fall back to CPU, which may bottleneck the pipeline.
472
-
473
- **DON'T:** Process images manually before passing to Vision + Core ML.
474
- **DO:** Use `CoreMLRequest` (iOS 18+) or `VNCoreMLRequest` (legacy) to let Vision handle preprocessing.
475
- **Why:** Vision handles orientation, scaling, and pixel format conversion correctly.
476
-
477
- ## Review Checklist
478
-
479
- - [ ] Model loaded asynchronously (not blocking main thread)
480
- - [ ] `MLModelConfiguration.computeUnits` set appropriately for use case
481
- - [ ] Model instance reused across predictions (not recreated each time)
482
- - [ ] Auto-generated class used when available (typed inputs/outputs)
483
- - [ ] Error handling for model loading and prediction failures
484
- - [ ] Compiled model cached persistently if compiled at runtime
485
- - [ ] Image inputs use Vision pipeline (`CoreMLRequest` iOS 18+ or `VNCoreMLRequest`) for correct preprocessing
486
- - [ ] `MLComputePlan` checked to verify compute device dispatch (iOS 17.4+)
487
- - [ ] Batch predictions used when processing multiple inputs
488
- - [ ] Model size appropriate for deployment strategy (bundle, Background Assets, ODR)
489
- - [ ] Memory tested on target devices (especially older devices with less RAM)
490
- - [ ] Predictions run outside debugger for accurate performance measurement
393
+ Keep the returned request alive while the model is in use and call
394
+ `endAccessingResources()` when you are done with it.
395
+
396
+ ## Memory
397
+
398
+ - Drop model references when the app goes to the background to release GPU
399
+ and Neural Engine memory; load again on return to the foreground.
400
+ - `.all` is the default. Use `.cpuOnly` only when profiling or policy points
401
+ to contention, thermal limits, energy, deterministic tests or a real
402
+ background-execution constraint.
403
+ - Keep one `MLModel` per compiled model and share it through an actor.
404
+ - Models above roughly 100 MB can trigger memory warnings; listen for
405
+ `UIApplication.didReceiveMemoryWarningNotification` and release cached
406
+ models.
407
+
408
+ ## Common mistakes
409
+
410
+ 1. **Loading on the main thread.** Large models take seconds; use
411
+ `MLModel.load(contentsOf:configuration:)` or a background actor.
412
+ 2. **Recompiling every launch.** Compilation is expensive; compile once and
413
+ keep the `.mlmodelc` in Application Support.
414
+ 3. **Hard-coding `.cpuOnly`.** `.all` lets Core ML use the Neural Engine and
415
+ GPU, usually faster and more efficient.
416
+ 4. **Declaring GPU or Neural Engine off-limits for anything near the
417
+ background.** Access depends on system policy, execution mode, contention,
418
+ thermal state and energy; profile on a device. `.cpuOnly` is a tradeoff,
419
+ not a rule, and a backgrounded app may be suspended or throttled anyway.
420
+ 5. **Feature type mismatches.** Images go in as `MLFeatureValue(pixelBuffer:)`,
421
+ not raw bytes; mismatches crash obscurely or give silently wrong output.
422
+ 6. **A new `MLModel` per prediction.** Loading costs memory and time; load once
423
+ and reuse through an actor.
424
+ 7. **No error handling.** Loading and prediction can fail on older or
425
+ constrained devices; catch and fall back.
426
+ 8. **Assuming everything runs on the Neural Engine.** Unsupported operations
427
+ fall back to the CPU and can dominate latency; check with `MLComputePlan`.
428
+ 9. **Hand-preprocessing images for Vision.** `CoreMLRequest` (iOS 18) and
429
+ `VNCoreMLRequest` already handle orientation, scaling and pixel format.
430
+ 10. **Dropping `await` on prediction in async code.** On iOS 17 and later the
431
+ async overload is selected there; write `try await`.
432
+
433
+ ## Review checklist
434
+
435
+ - [ ] Model loaded asynchronously
436
+ - [ ] `computeUnits` chosen deliberately
437
+ - [ ] One model instance reused across predictions
438
+ - [ ] Generated class used where Xcode provides one
439
+ - [ ] Load and prediction failures handled
440
+ - [ ] Runtime-compiled models cached in a durable location
441
+ - [ ] Image inputs routed through Vision (`CoreMLRequest` on iOS 18+, otherwise `VNCoreMLRequest`)
442
+ - [ ] Device dispatch checked with `MLComputePlan` (iOS 17.4+)
443
+ - [ ] Batch API used for many inputs
444
+ - [ ] Model size matches the delivery strategy (bundle, Background Assets, ODR)
445
+ - [ ] Memory measured on target devices, especially older low-RAM ones
446
+ - [ ] Latency measured outside the debugger
491
447
 
492
448
  ## References
493
449
 
494
- - Patterns and code: [references/coreml-swift-integration.md](references/coreml-swift-integration.md)
495
- - Model conversion and optimization (Python-side): covered in the `apple-on-device-ai` skill
496
- - Apple docs: [Core ML](https://sosumi.ai/documentation/coreml) |
497
- [MLModel](https://sosumi.ai/documentation/coreml/mlmodel) |
498
- [MLTensor](https://sosumi.ai/documentation/coreml/mltensor) |
499
- [MLComputePlan](https://sosumi.ai/documentation/coreml/mlcomputeplan-1w21n) |
500
- [Background Assets](https://sosumi.ai/documentation/backgroundassets)
450
+ - `references/coreml-swift-integration.md`
451
+ - `apple-on-device-ai` for conversion and compression in Python
452
+ - https://developer.apple.com/documentation/coreml
453
+ - https://developer.apple.com/documentation/coreml/mlmodel
454
+ - https://developer.apple.com/documentation/coreml/mltensor
455
+ - https://developer.apple.com/documentation/coreml/mlcomputeplan-1w21n
456
+ - https://developer.apple.com/documentation/backgroundassets