@mmerterden/multi-agent-pipeline 20.6.0 → 20.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (326) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/LICENSE +0 -10
  3. package/docs/facts.json +1 -1
  4. package/manifest.json +328 -329
  5. package/package.json +2 -2
  6. package/pipeline/multi-agent-refs/features/design-conformance.md +62 -64
  7. package/pipeline/scripts/_notices.mjs +12 -1
  8. package/pipeline/scripts/gen-skills-index.mjs +1 -1
  9. package/pipeline/skills/.skill-manifest.json +106 -106
  10. package/pipeline/skills/shared/README.md +71 -71
  11. package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +1 -0
  12. package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
  13. package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
  14. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
  15. package/pipeline/skills/shared/external/android-architecture/SKILL.md +2 -0
  16. package/pipeline/skills/shared/external/android-performance/SKILL.md +2 -0
  17. package/pipeline/skills/shared/external/android-security/SKILL.md +2 -0
  18. package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
  19. package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
  20. package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
  21. package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
  22. package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
  23. package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
  24. package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
  25. package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
  26. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
  27. package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
  28. package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
  29. package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
  30. package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
  31. package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
  32. package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
  33. package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
  34. package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
  35. package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
  36. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
  37. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
  38. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
  39. package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
  40. package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
  41. package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
  42. package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
  43. package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
  44. package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
  45. package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
  46. package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
  47. package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
  48. package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
  49. package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
  50. package/pipeline/skills/shared/external/backlog/BACKLOG.md +1 -1
  51. package/pipeline/skills/shared/external/backlog/SKILL.md +56 -33
  52. package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
  53. package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
  54. package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
  55. package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +1 -0
  56. package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
  57. package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
  58. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
  59. package/pipeline/skills/shared/external/compose-components/SKILL.md +2 -0
  60. package/pipeline/skills/shared/external/compose-navigation/SKILL.md +3 -2
  61. package/pipeline/skills/shared/external/compose-testing/SKILL.md +2 -0
  62. package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
  63. package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
  64. package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
  65. package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
  66. package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
  67. package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
  68. package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
  69. package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
  70. package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
  71. package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
  72. package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
  73. package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
  74. package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
  75. package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
  76. package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
  77. package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
  78. package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
  79. package/pipeline/skills/shared/external/council/SKILL.md +1 -0
  80. package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
  81. package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
  82. package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
  83. package/pipeline/skills/shared/external/css-modern/SKILL.md +1 -0
  84. package/pipeline/skills/shared/external/database-patterns/SKILL.md +1 -0
  85. package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
  86. package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
  87. package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
  88. package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
  89. package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
  90. package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
  91. package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
  92. package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
  93. package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
  94. package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
  95. package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
  96. package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
  97. package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
  98. package/pipeline/skills/shared/external/evidence-github/SKILL.md +2 -0
  99. package/pipeline/skills/shared/external/evidence-registry/SKILL.md +2 -0
  100. package/pipeline/skills/shared/external/gradle-kotlin-dsl/SKILL.md +2 -0
  101. package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
  102. package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
  103. package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
  104. package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
  105. package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
  106. package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
  107. package/pipeline/skills/shared/external/html-semantic/SKILL.md +1 -0
  108. package/pipeline/skills/shared/external/humanizer/SKILL.md +1 -0
  109. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
  110. package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
  111. package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
  112. package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
  113. package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
  114. package/pipeline/skills/shared/external/ios-coding-standard/SKILL.md +1 -0
  115. package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
  116. package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
  117. package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
  118. package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
  119. package/pipeline/skills/shared/external/ios-module-structure/SKILL.md +1 -0
  120. package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
  121. package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
  122. package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
  123. package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
  124. package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
  125. package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
  126. package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
  127. package/pipeline/skills/shared/external/ios-security/SKILL.md +2 -0
  128. package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
  129. package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
  130. package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
  131. package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
  132. package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
  133. package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
  134. package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +91 -283
  135. package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +119 -151
  136. package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +60 -90
  137. package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +119 -156
  138. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +726 -787
  139. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +253 -288
  140. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +243 -304
  141. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +88 -104
  142. package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +181 -235
  143. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-key-shots.py +198 -263
  144. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +461 -466
  145. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +145 -151
  146. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +123 -141
  147. package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +146 -157
  148. package/pipeline/skills/shared/external/localization-reuse-map/scripts/snapshot-resources.sh +22 -19
  149. package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +156 -140
  150. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
  151. package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
  152. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
  153. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
  154. package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
  155. package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
  156. package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
  157. package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
  158. package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
  159. package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
  160. package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
  161. package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
  162. package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
  163. package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +1 -0
  164. package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
  165. package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
  166. package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
  167. package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
  168. package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
  169. package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
  170. package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
  171. package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
  172. package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
  173. package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
  174. package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
  175. package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
  176. package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
  177. package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
  178. package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
  179. package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
  180. package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
  181. package/pipeline/skills/shared/external/play-store-review/SKILL.md +2 -0
  182. package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
  183. package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
  184. package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
  185. package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
  186. package/pipeline/skills/shared/external/python-patterns/SKILL.md +1 -0
  187. package/pipeline/skills/shared/external/react-best-practices/SKILL.md +1 -0
  188. package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
  189. package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
  190. package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
  191. package/pipeline/skills/shared/external/rest-api-design/SKILL.md +1 -0
  192. package/pipeline/skills/shared/external/retrofit-networking/SKILL.md +2 -0
  193. package/pipeline/skills/shared/external/room-database/SKILL.md +2 -0
  194. package/pipeline/skills/shared/external/search-first/SKILL.md +1 -0
  195. package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
  196. package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
  197. package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
  198. package/pipeline/skills/shared/external/signal-community/SKILL.md +2 -0
  199. package/pipeline/skills/shared/external/skill-creator/SKILL.md +80 -41
  200. package/pipeline/skills/shared/external/skill-creator/audit.md +63 -59
  201. package/pipeline/skills/shared/external/skill-creator/checklist.md +28 -20
  202. package/pipeline/skills/shared/external/skill-creator/examples.md +40 -40
  203. package/pipeline/skills/shared/external/skill-creator/label-check.md +48 -36
  204. package/pipeline/skills/shared/external/skill-creator/scripts/audit-panel.js +91 -100
  205. package/pipeline/skills/shared/external/skill-creator/template.md +51 -39
  206. package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
  207. package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
  208. package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
  209. package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
  210. package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
  211. package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
  212. package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
  213. package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
  214. package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
  215. package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
  216. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
  217. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
  218. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
  219. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
  220. package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
  221. package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
  222. package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
  223. package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
  224. package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
  225. package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
  226. package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
  227. package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
  228. package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
  229. package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
  230. package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
  231. package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
  232. package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
  233. package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
  234. package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
  235. package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
  236. package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
  237. package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
  238. package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
  239. package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
  240. package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
  241. package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
  242. package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
  243. package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
  244. package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
  245. package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
  246. package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
  247. package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
  248. package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
  249. package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
  250. package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
  251. package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
  252. package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
  253. package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
  254. package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
  255. package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
  256. package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
  257. package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
  258. package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
  259. package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
  260. package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
  261. package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
  262. package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
  263. package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
  264. package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
  265. package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
  266. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
  267. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
  268. package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
  269. package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
  270. package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
  271. package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
  272. package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
  273. package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
  274. package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
  275. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
  276. package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
  277. package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
  278. package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
  279. package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
  280. package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
  281. package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
  282. package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
  283. package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
  284. package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
  285. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
  286. package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
  287. package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
  288. package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
  289. package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
  290. package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
  291. package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
  292. package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
  293. package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
  294. package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
  295. package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
  296. package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
  297. package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
  298. package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
  299. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
  300. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
  301. package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
  302. package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
  303. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
  304. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
  305. package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
  306. package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
  307. package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
  308. package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
  309. package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
  310. package/pipeline/skills/shared/external/tailwind-css/SKILL.md +1 -0
  311. package/pipeline/skills/shared/external/testing-backend/SKILL.md +1 -0
  312. package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
  313. package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
  314. package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +1 -0
  315. package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
  316. package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
  317. package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
  318. package/pipeline/skills/shared/external/vue-composition/SKILL.md +1 -0
  319. package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
  320. package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
  321. package/pipeline/skills/shared/external/web-accessibility/SKILL.md +1 -0
  322. package/pipeline/skills/shared/external/web-performance/SKILL.md +1 -0
  323. package/pipeline/skills/shared/external/web-testing/SKILL.md +1 -0
  324. package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
  325. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
  326. package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
@@ -1,239 +1,199 @@
1
1
  ---
2
2
  name: musickit-audio
3
- description: "Integrate Apple Music playback, catalog search, and Now Playing metadata using MusicKit and MediaPlayer. Use when adding music search, Apple Music subscription flows, queue management, playback controls, remote command handling, or Now Playing info to iOS apps."
3
+ description: "MusicKit and MediaPlayer on iOS: Apple Music authorization, catalog search, subscription checks and offers, ApplicationMusicPlayer playback controls and queues, Now Playing info, remote commands. Use when adding Apple Music playback or Now Playing controls."
4
4
  metadata:
5
- source: "dpearson2699/swift-ios-skills (PolyForm Perimeter 1.0.0)"
5
+ source: multi-agent-pipeline
6
6
  ---
7
7
 
8
- # MusicKit
8
+ # MusicKit and Now Playing
9
9
 
10
- Search the Apple Music catalog, manage playback with `ApplicationMusicPlayer`,
11
- check subscriptions, and publish Now Playing metadata via `MPNowPlayingInfoCenter`
12
- and `MPRemoteCommandCenter`. Targets Swift 6.3 / iOS 26+.
10
+ Two frameworks cover music in an iOS app. MusicKit talks to Apple Music:
11
+ permission, catalog, subscription state, library and an app-owned player.
12
+ MediaPlayer talks to the system: the Now Playing card on the Lock Screen, in
13
+ Control Center and in CarPlay, plus the remote commands that headphones and
14
+ those surfaces send. Code here targets Swift 6.3 and iOS 26.
13
15
 
14
- ## Contents
15
-
16
- - [Setup](#setup)
17
- - [Authorization](#authorization)
18
- - [Catalog Search](#catalog-search)
19
- - [Subscription Checks](#subscription-checks)
20
- - [Playback with ApplicationMusicPlayer](#playback-with-applicationmusicplayer)
21
- - [Queue Management](#queue-management)
22
- - [Now Playing Info](#now-playing-info)
23
- - [Remote Command Center](#remote-command-center)
24
- - [Common Mistakes](#common-mistakes)
25
- - [Review Checklist](#review-checklist)
26
- - [References](#references)
16
+ Longer building blocks (an observable player model, mini player, search screen,
17
+ charts, library and playlist work, `MPNowPlayingSession`, audio session setup,
18
+ interruptions and route changes) live in
19
+ [references/musickit-patterns.md](references/musickit-patterns.md).
27
20
 
28
21
  ## Setup
29
22
 
30
- ### Project Configuration
23
+ ### Portal and Info.plist
24
+
25
+ 1. In the developer portal, open the app's explicit App ID and turn on the
26
+ **MusicKit** App Service. That is what lets the system mint developer tokens
27
+ for the app automatically; there is no token code to write.
28
+ 2. Add `NSAppleMusicUsageDescription` to Info.plist. Without it, access to the
29
+ user's media library fails wherever the system requires the string.
30
+ 3. Only if audio must keep playing in the background: add `audio` to the
31
+ `UIBackgroundModes` array.
31
32
 
32
- 1. Enable the **MusicKit App Service** for the app's explicit bundle ID in the Apple Developer portal so MusicKit can generate developer tokens automatically.
33
- 2. Add `NSAppleMusicUsageDescription` to Info.plist explaining why the app accesses the user's media library.
34
- 3. For background playback, add the `audio` background mode to `UIBackgroundModes`.
33
+ There is no `com.apple.developer.musickit` entitlement to add on iOS, and a
34
+ missing entitlement is not what makes authorization fail. The App Service and
35
+ the usage string are the two requirements.
35
36
 
36
37
  ### Imports
37
38
 
38
39
  ```swift
39
- import MusicKit // Catalog, auth, playback
40
- import MediaPlayer // MPRemoteCommandCenter, MPNowPlayingInfoCenter
40
+ import MusicKit // authorization, catalog, subscription, ApplicationMusicPlayer
41
+ import MediaPlayer // MPNowPlayingInfoCenter, MPRemoteCommandCenter
41
42
  ```
42
43
 
43
44
  ## Authorization
44
45
 
45
- Request permission before accessing the user's music data or playing Apple Music
46
- content. `request()` presents Apple's consent dialog when necessary; use
47
- `currentStatus` to read the current setting without prompting.
46
+ Ask before touching the user's music data or starting Apple Music playback.
48
47
 
49
48
  ```swift
50
- func requestMusicAccess() async -> MusicAuthorization.Status {
51
- let status = await MusicAuthorization.request()
52
- switch status {
49
+ func ensureMusicAccess() async -> Bool {
50
+ switch await MusicAuthorization.request() {
53
51
  case .authorized:
54
- // Full access to MusicKit APIs
55
- break
52
+ return true
56
53
  case .denied, .restricted:
57
- // Show guidance to enable in Settings
58
- break
54
+ // Explain the limitation and point the user at Settings.
55
+ return false
59
56
  case .notDetermined:
60
- break
57
+ return false
61
58
  @unknown default:
62
- break
59
+ return false
63
60
  }
64
- return status
65
61
  }
66
-
67
- // Check current status without prompting
68
- let current = MusicAuthorization.currentStatus
69
62
  ```
70
63
 
71
- ## Catalog Search
64
+ `request()` shows the consent prompt only when the user has not answered yet;
65
+ otherwise it returns the stored answer. To read the state without any chance of
66
+ a prompt, use `MusicAuthorization.currentStatus`.
72
67
 
73
- Use `MusicCatalogSearchRequest` to search the Apple Music catalog. Catalog lookup
74
- can fetch Apple Music resources, but playback of subscription catalog content
75
- must still be gated on `MusicSubscription.current.canPlayCatalogContent`.
68
+ ## Catalog search
76
69
 
77
- ```swift
78
- func searchCatalog(term: String) async throws -> MusicItemCollection<Song> {
79
- var request = MusicCatalogSearchRequest(term: term, types: [Song.self])
80
- request.limit = 25
70
+ Searching the catalog works for anyone who granted access. Playing what you
71
+ found is a separate question, answered by the subscription check below.
81
72
 
82
- let response = try await request.response()
83
- return response.songs
73
+ ```swift
74
+ func findTracks(matching phrase: String) async throws -> MusicItemCollection<Song> {
75
+ var search = MusicCatalogSearchRequest(term: phrase, types: [Song.self])
76
+ search.limit = 25
77
+ let result = try await search.response()
78
+ return result.songs
84
79
  }
85
80
  ```
86
81
 
87
- ### Displaying Results
82
+ For a row, read `song.title`, `song.artistName` and
83
+ `song.artwork?.url(width: 120, height: 120)`.
84
+
85
+ ## Subscription state
88
86
 
89
87
  ```swift
90
- for song in songs {
91
- print("\(song.title) by \(song.artistName)")
92
- if let artwork = song.artwork {
93
- let url = artwork.url(width: 300, height: 300)
94
- // Load artwork from url
95
- }
96
- }
88
+ let membership = try await MusicSubscription.current
89
+ let mayPlay = membership.canPlayCatalogContent
97
90
  ```
98
91
 
99
- ## Subscription Checks
100
-
101
- Check whether the user has an active Apple Music subscription before offering playback features.
92
+ Subscription state changes while the app runs. Keep the UI in step:
102
93
 
103
94
  ```swift
104
- func checkSubscription() async throws -> Bool {
105
- let subscription = try await MusicSubscription.current
106
- return subscription.canPlayCatalogContent
107
- }
108
-
109
- // Observe subscription changes
110
- func observeSubscription() async {
111
- for await subscription in MusicSubscription.subscriptionUpdates {
112
- if subscription.canPlayCatalogContent {
113
- // Enable full playback UI
114
- } else {
115
- // Show subscription offer
116
- }
95
+ .task {
96
+ for await membership in MusicSubscription.subscriptionUpdates {
97
+ showsPlayControls = membership.canPlayCatalogContent
98
+ showsJoinButton = !membership.canPlayCatalogContent && membership.canBecomeSubscriber
117
99
  }
118
100
  }
119
101
  ```
120
102
 
121
- ### Offering Apple Music
103
+ ### Presenting the Apple Music offer
122
104
 
123
- Present the Apple Music subscription offer sheet when the user is not subscribed.
124
- Check `canBecomeSubscriber` first, and pass `MusicSubscriptionOffer.Options` or
125
- `onLoadCompletion` when the sheet needs contextual metadata or load-error handling.
105
+ Only offer when `canBecomeSubscriber` is true. The sheet comes from a view
106
+ modifier:
126
107
 
127
108
  ```swift
128
- import MusicKit
129
- import SwiftUI
130
-
131
- struct MusicOfferView: View {
132
- @State private var showOffer = false
109
+ struct JoinAppleMusicButton: View {
110
+ @State private var offerVisible = false
111
+ @State private var offerOptions = MusicSubscriptionOffer.Options.default
112
+ @State private var offerError: (any Error)?
133
113
 
134
114
  var body: some View {
135
- Button("Subscribe to Apple Music") {
136
- Task {
137
- let subscription = try? await MusicSubscription.current
138
- showOffer = subscription?.canBecomeSubscriber == true
139
- }
140
- }
141
- .musicSubscriptionOffer(
142
- isPresented: $showOffer,
143
- options: .default,
144
- onLoadCompletion: { error in
145
- if let error {
146
- // Surface loading errors in app UI or diagnostics.
147
- print(error)
148
- }
149
- }
150
- )
115
+ Button("Try Apple Music") { offerVisible = true }
116
+ .musicSubscriptionOffer(
117
+ isPresented: $offerVisible,
118
+ options: offerOptions,
119
+ onLoadCompletion: { failure in offerError = failure }
120
+ )
151
121
  }
152
122
  }
153
123
  ```
154
124
 
155
- ## Playback with ApplicationMusicPlayer
125
+ When `offerError` is non-nil the sheet did not load; show a fallback message.
156
126
 
157
- `ApplicationMusicPlayer` plays Apple Music content independently from the Music app. It does not affect the system player's state.
127
+ ## ApplicationMusicPlayer
158
128
 
159
- ```swift
160
- let player = ApplicationMusicPlayer.shared
129
+ `ApplicationMusicPlayer.shared` is the app's own player. It plays alongside the
130
+ Music app without touching the Music app's queue or state.
161
131
 
162
- func playSong(_ song: Song) async throws {
163
- player.queue = [song]
132
+ ```swift
133
+ func start(_ track: Song) async throws {
134
+ let player = ApplicationMusicPlayer.shared
135
+ player.queue = [track]
164
136
  try await player.play()
165
137
  }
166
138
 
167
- func pause() {
168
- player.pause()
169
- }
139
+ func halt() { ApplicationMusicPlayer.shared.pause() }
170
140
 
171
- func skipToNext() async throws {
172
- try await player.skipToNextEntry()
173
- }
141
+ func forward() async throws { try await ApplicationMusicPlayer.shared.skipToNextEntry() }
174
142
  ```
175
143
 
176
- ### Observing Playback State
144
+ The player is not `Sendable`. Read `.shared` where it is used; a global
145
+ `let player`, or a property on a main-actor type, fails Swift 6 checking once
146
+ an async method is called on it. The snippets below use `player` for
147
+ `ApplicationMusicPlayer.shared`.
148
+
149
+ `player.state` is observable, so SwiftUI redraws when it changes. Branch on
150
+ `playbackStatus`:
177
151
 
178
152
  ```swift
179
- func observePlayback() {
180
- // player.state is an @Observable property
181
- let state = player.state
182
- switch state.playbackStatus {
183
- case .playing:
184
- break
185
- case .paused:
186
- break
187
- case .stopped, .interrupted, .seekingForward, .seekingBackward:
188
- break
189
- @unknown default:
190
- break
191
- }
153
+ switch player.state.playbackStatus {
154
+ case .playing: label = "Playing"
155
+ case .paused: label = "Paused"
156
+ case .stopped: label = "Stopped"
157
+ case .interrupted: label = "Interrupted"
158
+ case .seekingForward,
159
+ .seekingBackward: label = "Seeking"
160
+ @unknown default: label = ""
192
161
  }
193
162
  ```
194
163
 
195
- ## Queue Management
164
+ ## Queue management
196
165
 
197
- Build and manipulate the playback queue using `ApplicationMusicPlayer.Queue`.
166
+ `player.queue` is an `ApplicationMusicPlayer.Queue`. Assigning a collection
167
+ replaces it, and an album or playlist works as well as songs:
198
168
 
199
169
  ```swift
200
- // Initialize with multiple items
201
- func playAlbum(_ album: Album) async throws {
202
- player.queue = [album]
203
- try await player.play()
204
- }
170
+ player.queue = [albumToPlay]
171
+ ```
205
172
 
206
- // Append songs to the existing queue
207
- func appendToQueue(_ songs: [Song]) async throws {
208
- try await player.queue.insert(songs, position: .tail)
209
- }
173
+ To add without replacing:
210
174
 
211
- // Insert song to play next
212
- func playNext(_ song: Song) async throws {
213
- try await player.queue.insert(song, position: .afterCurrentEntry)
214
- }
175
+ ```swift
176
+ try await player.queue.insert(extraTracks, position: .tail) // at the end
177
+ try await player.queue.insert(nextUp, position: .afterCurrentEntry) // play next
215
178
  ```
216
179
 
217
- ## Now Playing Info
180
+ ## Now Playing info
218
181
 
219
- Update `MPNowPlayingInfoCenter` so the Lock Screen, Control Center, and CarPlay
220
- display current track metadata. This is essential when playing custom audio
221
- (non-MusicKit sources). `ApplicationMusicPlayer` handles this automatically for
222
- Apple Music content.
182
+ `MPNowPlayingInfoCenter` feeds the Lock Screen, Control Center and CarPlay.
183
+ When `ApplicationMusicPlayer` plays Apple Music content, the system fills this
184
+ in for you. Write it yourself only for audio the app plays some other way, such
185
+ as an `AVPlayer` streaming podcasts.
223
186
 
224
187
  ```swift
225
- import MediaPlayer
226
-
227
- func updateNowPlaying(title: String, artist: String, duration: TimeInterval, elapsed: TimeInterval) {
228
- var info = [String: Any]()
229
- info[MPMediaItemPropertyTitle] = title
230
- info[MPMediaItemPropertyArtist] = artist
231
- info[MPMediaItemPropertyPlaybackDuration] = duration
232
- info[MPNowPlayingInfoPropertyElapsedPlaybackTime] = elapsed
233
- info[MPNowPlayingInfoPropertyPlaybackRate] = 1.0
234
- info[MPNowPlayingInfoPropertyMediaType] = MPNowPlayingInfoMediaType.audio.rawValue
235
-
236
- MPNowPlayingInfoCenter.default().nowPlayingInfo = info
188
+ func publishNowPlaying(for episode: Episode, position: TimeInterval) {
189
+ MPNowPlayingInfoCenter.default().nowPlayingInfo = [
190
+ MPMediaItemPropertyTitle: episode.title,
191
+ MPMediaItemPropertyArtist: episode.showName,
192
+ MPMediaItemPropertyPlaybackDuration: episode.length,
193
+ MPNowPlayingInfoPropertyElapsedPlaybackTime: position,
194
+ MPNowPlayingInfoPropertyPlaybackRate: 1.0,
195
+ MPNowPlayingInfoPropertyMediaType: MPNowPlayingInfoMediaType.audio.rawValue
196
+ ]
237
197
  }
238
198
 
239
199
  func clearNowPlaying() {
@@ -241,184 +201,98 @@ func clearNowPlaying() {
241
201
  }
242
202
  ```
243
203
 
244
- ### Adding Artwork
204
+ Artwork goes in under `MPMediaItemPropertyArtwork`. Merge it into the existing
205
+ dictionary rather than replacing the whole thing:
245
206
 
246
207
  ```swift
247
- func setArtwork(_ image: UIImage) {
248
- let artwork = MPMediaItemArtwork(boundsSize: image.size) { _ in image }
208
+ func attachCover(_ cover: UIImage) {
209
+ let art = MPMediaItemArtwork(boundsSize: cover.size) { _ in cover }
249
210
  var info = MPNowPlayingInfoCenter.default().nowPlayingInfo ?? [:]
250
- info[MPMediaItemPropertyArtwork] = artwork
211
+ info[MPMediaItemPropertyArtwork] = art
251
212
  MPNowPlayingInfoCenter.default().nowPlayingInfo = info
252
213
  }
253
214
  ```
254
215
 
255
- ## Remote Command Center
256
-
257
- Register handlers for `MPRemoteCommandCenter` to respond to Lock Screen controls,
258
- AirPods tap gestures, and CarPlay buttons.
216
+ Refresh the elapsed time on a timer or at each seek, so the Lock Screen
217
+ scrubber stays accurate.
259
218
 
260
- ```swift
261
- func setupRemoteCommands() {
262
- let center = MPRemoteCommandCenter.shared()
263
-
264
- center.playCommand.addTarget { _ in
265
- resumePlayback()
266
- return .success
267
- }
268
-
269
- center.pauseCommand.addTarget { _ in
270
- pausePlayback()
271
- return .success
272
- }
219
+ ## Remote commands
273
220
 
274
- center.nextTrackCommand.addTarget { _ in
275
- skipToNext()
276
- return .success
277
- }
221
+ `MPRemoteCommandCenter.shared()` receives Lock Screen buttons, AirPods taps and
222
+ CarPlay controls. Register the handlers from the main actor so they can call a
223
+ main-actor engine directly; `EpisodeEngine` stands for that type.
278
224
 
279
- center.previousTrackCommand.addTarget { _ in
280
- skipToPrevious()
281
- return .success
282
- }
225
+ ```swift
226
+ @MainActor
227
+ func wireRemoteControls(to engine: EpisodeEngine) {
228
+ let commands = MPRemoteCommandCenter.shared()
283
229
 
284
- // Disable commands you do not support
285
- center.seekForwardCommand.isEnabled = false
286
- center.seekBackwardCommand.isEnabled = false
287
- }
288
- ```
230
+ commands.playCommand.addTarget { _ in engine.resume(); return .success }
231
+ commands.pauseCommand.addTarget { _ in engine.suspend(); return .success }
232
+ commands.nextTrackCommand.addTarget { _ in engine.advance(); return .success }
233
+ commands.previousTrackCommand.addTarget { _ in engine.rewind(); return .success }
289
234
 
290
- ### Scrubbing Support
235
+ commands.seekForwardCommand.isEnabled = false
236
+ commands.seekBackwardCommand.isEnabled = false
291
237
 
292
- ```swift
293
- func enableScrubbing() {
294
- let center = MPRemoteCommandCenter.shared()
295
- center.changePlaybackPositionCommand.addTarget { event in
296
- guard let positionEvent = event as? MPChangePlaybackPositionCommandEvent else {
238
+ commands.changePlaybackPositionCommand.addTarget { event in
239
+ guard let jump = event as? MPChangePlaybackPositionCommandEvent else {
297
240
  return .commandFailed
298
241
  }
299
- seek(to: positionEvent.positionTime)
242
+ engine.move(to: jump.positionTime)
300
243
  return .success
301
244
  }
302
245
  }
303
246
  ```
304
247
 
305
- ## Common Mistakes
306
-
307
- ### DON'T: Skip MusicKit App Service setup or usage description
308
-
309
- Without the MusicKit App Service on the app's explicit bundle ID, automatic
310
- developer token generation for Apple Music API requests is not configured.
311
- Without `NSAppleMusicUsageDescription`, the app cannot access the user's media
312
- library on Apple platforms that require the purpose string.
313
-
314
- ```swift
315
- // WRONG: MusicKit App Service not enabled for this bundle ID
316
-
317
- // CORRECT: Enable MusicKit App Service in the developer portal,
318
- // set the matching bundle ID, then add NSAppleMusicUsageDescription.
319
- let status = await MusicAuthorization.request()
320
- ```
321
-
322
- ### DON'T: Forget to check subscription before playback
323
-
324
- Attempting to play catalog content without a subscription silently fails or throws.
325
-
326
- ```swift
327
- // WRONG
328
- func play(_ song: Song) async throws {
329
- player.queue = [song]
330
- try await player.play() // Fails if no subscription
331
- }
332
-
333
- // CORRECT
334
- func play(_ song: Song) async throws {
335
- let sub = try await MusicSubscription.current
336
- guard sub.canPlayCatalogContent else {
337
- showSubscriptionOffer()
338
- return
339
- }
340
- player.queue = [song]
341
- try await player.play()
342
- }
343
- ```
344
-
345
- ### DON'T: Use SystemMusicPlayer when you mean ApplicationMusicPlayer
346
-
347
- `SystemMusicPlayer` controls the global Music app queue. Changes affect the user's
348
- Music app state. Use `ApplicationMusicPlayer` for app-scoped playback.
349
-
350
- ```swift
351
- // WRONG: Modifies the user's Music app queue
352
- let player = SystemMusicPlayer.shared
353
-
354
- // CORRECT: App-scoped playback
355
- let player = ApplicationMusicPlayer.shared
356
- ```
357
-
358
- ### DON'T: Forget to update Now Playing info when track changes
359
-
360
- Stale metadata on the Lock Screen confuses users. Update Now Playing info
361
- every time the current track changes.
362
-
363
- ```swift
364
- // WRONG: Set once and forget
365
- updateNowPlaying(title: firstSong.title, ...)
366
-
367
- // CORRECT: Update on every track change
368
- func onTrackChanged(_ song: Song) {
369
- updateNowPlaying(
370
- title: song.title,
371
- artist: song.artistName,
372
- duration: song.duration ?? 0,
373
- elapsed: 0
374
- )
375
- }
376
- ```
377
-
378
- ### DON'T: Register remote commands without handling them
379
-
380
- Registering a command but returning `.commandFailed` breaks Lock Screen controls.
381
- Disable commands you do not support instead.
382
-
383
- ```swift
384
- // WRONG
385
- center.skipForwardCommand.addTarget { _ in .commandFailed }
386
-
387
- // CORRECT
388
- center.skipForwardCommand.isEnabled = false
389
- ```
390
-
391
- ## Review Checklist
392
-
393
- - [ ] MusicKit App Service enabled for the app's explicit bundle ID
394
- - [ ] `NSAppleMusicUsageDescription` added to Info.plist
395
- - [ ] `MusicAuthorization.request()` called before any MusicKit access
396
- - [ ] Subscription checked before attempting catalog playback
397
- - [ ] `canBecomeSubscriber` checked before presenting a subscription offer
248
+ ## Common mistakes
249
+
250
+ - **Skipping portal or plist setup.** Without the MusicKit App Service there is
251
+ no automatic developer token; without `NSAppleMusicUsageDescription`, library
252
+ access fails where it is required.
253
+ - **Playing catalog items without a subscription.** Playback fails quietly or
254
+ throws. Check `canPlayCatalogContent` first and show the offer when it is
255
+ false.
256
+ - **Reaching for `SystemMusicPlayer`.** It drives the Music app's global queue
257
+ and changes the user's own listening state. App-scoped playback belongs in
258
+ `ApplicationMusicPlayer`.
259
+ - **Stale Now Playing data.** For custom audio, rewrite the dictionary on every
260
+ track change: title, artist, duration (use `track.duration ?? 0` when it is
261
+ optional) and an elapsed time reset to 0.
262
+ - **Registering commands you cannot honor.** A handler that returns
263
+ `.commandFailed` leaves a dead button on the Lock Screen. Turn the command off
264
+ instead, for example `MPRemoteCommandCenter.shared().skipForwardCommand.isEnabled = false`.
265
+
266
+ ## Review checklist
267
+
268
+ - [ ] MusicKit App Service enabled on the explicit App ID
269
+ - [ ] `NSAppleMusicUsageDescription` present
270
+ - [ ] `MusicAuthorization.request()` runs before any MusicKit access
271
+ - [ ] Subscription checked before catalog playback
272
+ - [ ] `canBecomeSubscriber` checked before the offer is shown
273
+ - [ ] Offer shown when the user is not subscribed
398
274
  - [ ] `hasCloudLibraryEnabled` checked before library writes
399
- - [ ] `ApplicationMusicPlayer` used (not `SystemMusicPlayer`) for app-scoped playback
400
- - [ ] Background audio mode enabled if music plays in background
401
- - [ ] Now Playing info updated on every track change (for custom audio)
402
- - [ ] Remote command handlers return `.success` for supported commands
403
- - [ ] Unsupported remote commands disabled with `isEnabled = false`
404
- - [ ] Artwork provided in Now Playing info for Lock Screen display
405
- - [ ] Elapsed playback time updated periodically for scrubber accuracy
406
- - [ ] Subscription offer presented when user lacks Apple Music subscription
275
+ - [ ] `ApplicationMusicPlayer` used, not `SystemMusicPlayer`
276
+ - [ ] `audio` background mode set if playback continues in the background
277
+ - [ ] Now Playing updated on each track change (custom audio)
278
+ - [ ] Artwork supplied for the Lock Screen
279
+ - [ ] Elapsed time refreshed so the scrubber is accurate
280
+ - [ ] Supported remote commands return `.success`; unsupported ones are disabled
407
281
 
408
282
  ## References
409
283
 
410
- - Extended patterns (SwiftUI integration, genre browsing, playlist management): [references/musickit-patterns.md](references/musickit-patterns.md)
411
- - [MusicKit framework](https://sosumi.ai/documentation/musickit)
412
- - [Using automatic developer token generation for Apple Music API](https://sosumi.ai/documentation/musickit/using-automatic-token-generation-for-apple-music-api)
413
- - [MusicAuthorization](https://sosumi.ai/documentation/musickit/musicauthorization)
414
- - [ApplicationMusicPlayer](https://sosumi.ai/documentation/musickit/applicationmusicplayer)
415
- - [MusicCatalogSearchRequest](https://sosumi.ai/documentation/musickit/musiccatalogsearchrequest)
416
- - [MusicSubscription](https://sosumi.ai/documentation/musickit/musicsubscription)
417
- - [canPlayCatalogContent](https://sosumi.ai/documentation/musickit/musicsubscription/canplaycatalogcontent)
418
- - [canBecomeSubscriber](https://sosumi.ai/documentation/musickit/musicsubscription/canbecomesubscriber)
419
- - [hasCloudLibraryEnabled](https://sosumi.ai/documentation/musickit/musicsubscription/hascloudlibraryenabled)
420
- - [MusicCatalogChartsRequest initializer](https://sosumi.ai/documentation/musickit/musiccatalogchartsrequest/init(genre:kinds:types:))
421
- - [musicSubscriptionOffer(isPresented:options:onLoadCompletion:)](https://sosumi.ai/documentation/swiftui/view/musicsubscriptionoffer(ispresented:options:onloadcompletion:))
422
- - [MPRemoteCommandCenter](https://sosumi.ai/documentation/mediaplayer/mpremotecommandcenter)
423
- - [MPNowPlayingInfoCenter](https://sosumi.ai/documentation/mediaplayer/mpnowplayinginfocenter)
424
- - [NSAppleMusicUsageDescription](https://sosumi.ai/documentation/bundleresources/information-property-list/nsapplemusicusagedescription)
284
+ - [references/musickit-patterns.md](references/musickit-patterns.md)
285
+ - [MusicKit](https://developer.apple.com/documentation/musickit)
286
+ - [Using automatic developer token generation](https://developer.apple.com/documentation/musickit/using-automatic-developer-token-generation-for-apple-music-api)
287
+ - [MusicAuthorization](https://developer.apple.com/documentation/musickit/musicauthorization)
288
+ - [ApplicationMusicPlayer](https://developer.apple.com/documentation/musickit/applicationmusicplayer)
289
+ - [MusicCatalogSearchRequest](https://developer.apple.com/documentation/musickit/musiccatalogsearchrequest)
290
+ - [MusicSubscription](https://developer.apple.com/documentation/musickit/musicsubscription)
291
+ - [canPlayCatalogContent](https://developer.apple.com/documentation/musickit/musicsubscription/canplaycatalogcontent)
292
+ - [canBecomeSubscriber](https://developer.apple.com/documentation/musickit/musicsubscription/canbecomesubscriber)
293
+ - [hasCloudLibraryEnabled](https://developer.apple.com/documentation/musickit/musicsubscription/hascloudlibraryenabled)
294
+ - [MusicCatalogChartsRequest init(genre:kinds:types:)](https://developer.apple.com/documentation/musickit/musiccatalogchartsrequest/init(genre:kinds:types:))
295
+ - [musicSubscriptionOffer(isPresented:options:onLoadCompletion:)](https://developer.apple.com/documentation/swiftui/view/musicsubscriptionoffer(ispresented:options:onloadcompletion:))
296
+ - [MPRemoteCommandCenter](https://developer.apple.com/documentation/mediaplayer/mpremotecommandcenter)
297
+ - [MPNowPlayingInfoCenter](https://developer.apple.com/documentation/mediaplayer/mpnowplayinginfocenter)
298
+ - [NSAppleMusicUsageDescription](https://developer.apple.com/documentation/bundleresources/information-property-list/nsapplemusicusagedescription)