@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,444 +1,276 @@
1
- # CallKit + PushKit Extended Patterns
1
+ # CallKit Patterns
2
2
 
3
- Overflow reference for the `callkit` skill. Contains advanced patterns that exceed the main skill file's scope.
3
+ Longer examples that back the `callkit-voip` skill. Read its SKILL.md first;
4
+ this file assumes the provider setup, push rules and audio rules described
5
+ there.
4
6
 
5
- ## Contents
7
+ ## An observable call manager
6
8
 
7
- - [Full Call Manager](#full-call-manager)
8
- - [Hold and Mute Actions](#hold-and-mute-actions)
9
- - [Multiple Concurrent Calls](#multiple-concurrent-calls)
10
- - [Call State Tracking](#call-state-tracking)
11
- - [Encrypted VoIP Push Filtering](#encrypted-voip-push-filtering)
12
- - [Call Directory Incremental Updates](#call-directory-incremental-updates)
13
- - [Testing VoIP Locally](#testing-voip-locally)
14
-
15
- ## Full Call Manager
9
+ A `@MainActor` model that SwiftUI can watch. It owns the provider and the
10
+ controller and keeps a table of live calls.
16
11
 
17
12
  ```swift
18
13
  import CallKit
19
- import AVFoundation
20
- import PushKit
21
-
22
- @Observable
23
- @MainActor
24
- final class VoIPCallManager: NSObject {
25
- let provider: CXProvider
26
- let callController = CXCallController()
27
-
28
- private(set) var activeCalls: [UUID: CallInfo] = [:]
29
-
30
- struct CallInfo {
31
- let uuid: UUID
32
- let handle: String
33
- let isOutgoing: Bool
34
- var isOnHold: Bool = false
35
- var isMuted: Bool = false
36
- var isConnected: Bool = false
37
- }
14
+ import Observation
15
+
16
+ struct LiveCall: Identifiable, Sendable {
17
+ let id: UUID
18
+ let address: String
19
+ let outgoing: Bool
20
+ var held = false
21
+ var muted = false
22
+ var connected = false
23
+ }
24
+
25
+ @Observable @MainActor
26
+ final class Switchboard: NSObject {
27
+ @ObservationIgnored let provider: CXProvider
28
+ @ObservationIgnored let controller = CXCallController()
29
+ private(set) var calls: [UUID: LiveCall] = [:]
38
30
 
39
31
  override init() {
40
- let config = CXProviderConfiguration()
41
- config.localizedName = "My VoIP"
42
- config.supportsVideo = true
43
- config.maximumCallGroups = 2
44
- config.maximumCallsPerCallGroup = 1
45
- config.supportedHandleTypes = [.phoneNumber]
46
- config.includesCallsInRecents = true
47
-
48
- provider = CXProvider(configuration: config)
32
+ let setup = CXProviderConfiguration()
33
+ setup.supportedHandleTypes = [.phoneNumber]
34
+ setup.includesCallsInRecents = true
35
+ setup.maximumCallsPerCallGroup = 1
36
+ setup.maximumCallGroups = 2
37
+ setup.supportsVideo = true
38
+ provider = CXProvider(configuration: setup)
49
39
  super.init()
50
40
  provider.setDelegate(self, queue: nil)
51
41
  }
52
42
 
53
- // MARK: - Incoming
54
-
55
- func reportIncoming(
56
- uuid: UUID,
57
- handle: String,
58
- callerName: String,
59
- hasVideo: Bool
60
- ) async throws {
61
- let update = CXCallUpdate()
62
- update.remoteHandle = CXHandle(type: .phoneNumber, value: handle)
63
- update.localizedCallerName = callerName
64
- update.hasVideo = hasVideo
65
- update.supportsHolding = true
66
- update.supportsDTMF = true
67
- update.supportsGrouping = false
68
- update.supportsUngrouping = false
69
-
70
- try await withCheckedThrowingContinuation {
71
- (continuation: CheckedContinuation<Void, Error>) in
72
- provider.reportNewIncomingCall(
73
- with: uuid, update: update
74
- ) { error in
75
- if let error {
76
- continuation.resume(throwing: error)
77
- } else {
78
- continuation.resume()
79
- }
80
- }
81
- }
82
-
83
- activeCalls[uuid] = CallInfo(
84
- uuid: uuid, handle: handle, isOutgoing: false
85
- )
43
+ func reportIncoming(id: UUID, address: String, name: String) async throws {
44
+ let info = CXCallUpdate()
45
+ info.localizedCallerName = name
46
+ info.remoteHandle = CXHandle(type: .generic, value: address)
47
+ info.supportsDTMF = true
48
+ info.supportsHolding = true
49
+ info.supportsUngrouping = false
50
+ info.supportsGrouping = false
51
+ try await provider.reportNewIncomingCall(with: id, update: info)
52
+ calls[id] = LiveCall(id: id, address: address, outgoing: false)
86
53
  }
87
54
 
88
- // MARK: - Outgoing
89
-
90
- func startCall(handle: String, hasVideo: Bool) {
91
- let uuid = UUID()
92
- let cxHandle = CXHandle(type: .phoneNumber, value: handle)
93
- let action = CXStartCallAction(call: uuid, handle: cxHandle)
94
- action.isVideo = hasVideo
95
-
96
- callController.request(
97
- CXTransaction(action: action)
98
- ) { error in
99
- if let error {
100
- print("Start call failed: \(error)")
101
- }
102
- }
103
-
104
- activeCalls[uuid] = CallInfo(
105
- uuid: uuid, handle: handle, isOutgoing: true
106
- )
55
+ func startCall(to address: String) async throws {
56
+ let id = UUID()
57
+ let action = CXStartCallAction(call: id, handle: CXHandle(type: .phoneNumber, value: address))
58
+ try await controller.request(CXTransaction(action: action))
59
+ calls[id] = LiveCall(id: id, address: address, outgoing: true)
107
60
  }
108
61
 
109
- // MARK: - Actions
110
-
111
- func endCall(uuid: UUID) {
112
- let action = CXEndCallAction(call: uuid)
113
- callController.request(CXTransaction(action: action)) { error in
114
- if let error { print("End call failed: \(error)") }
115
- }
62
+ func hangUp(_ id: UUID) async throws {
63
+ try await controller.request(CXTransaction(action: CXEndCallAction(call: id)))
116
64
  }
117
65
 
118
- func setHeld(uuid: UUID, onHold: Bool) {
119
- let action = CXSetHeldCallAction(call: uuid, onHold: onHold)
120
- callController.request(CXTransaction(action: action)) { error in
121
- if let error { print("Hold failed: \(error)") }
122
- }
66
+ func setHeld(_ id: UUID, _ held: Bool) async throws {
67
+ try await controller.request(CXTransaction(action: CXSetHeldCallAction(call: id, onHold: held)))
123
68
  }
124
69
 
125
- func setMuted(uuid: UUID, muted: Bool) {
126
- let action = CXSetMutedCallAction(call: uuid, muted: muted)
127
- callController.request(CXTransaction(action: action)) { error in
128
- if let error { print("Mute failed: \(error)") }
129
- }
70
+ func setMuted(_ id: UUID, _ muted: Bool) async throws {
71
+ try await controller.request(CXTransaction(action: CXSetMutedCallAction(call: id, muted: muted)))
130
72
  }
131
73
  }
132
74
  ```
133
75
 
134
- ## Hold and Mute Actions
76
+ A call enters `calls` only after its incoming report succeeds; an outgoing call
77
+ enters after the start transaction was accepted. Hanging up, holding and muting
78
+ all follow the same shape: build the action, wrap it in a `CXTransaction`, send
79
+ it with `request`.
135
80
 
136
- ```swift
137
- extension VoIPCallManager: CXProviderDelegate {
138
- nonisolated func providerDidReset(_ provider: CXProvider) {
139
- Task { @MainActor in
140
- for uuid in activeCalls.keys {
141
- disconnectCall(uuid)
142
- }
143
- activeCalls.removeAll()
144
- }
145
- }
146
-
147
- nonisolated func provider(
148
- _ provider: CXProvider,
149
- perform action: CXSetHeldCallAction
150
- ) {
151
- Task { @MainActor in
152
- activeCalls[action.callUUID]?.isOnHold = action.isOnHold
153
- if action.isOnHold {
154
- pauseAudio(for: action.callUUID)
155
- } else {
156
- resumeAudio(for: action.callUUID)
157
- }
158
- action.fulfill()
159
- }
160
- }
81
+ ## Hold and mute in the delegate
161
82
 
162
- nonisolated func provider(
163
- _ provider: CXProvider,
164
- perform action: CXSetMutedCallAction
165
- ) {
166
- Task { @MainActor in
167
- activeCalls[action.callUUID]?.isMuted = action.isMuted
168
- // If call translation is active, mute app input without deactivating
169
- // upstream audio that translated audio may need.
170
- setMicrophoneMuted(action.isMuted)
171
- action.fulfill()
172
- }
173
- }
83
+ The provider calls its delegate on the main queue here (`queue: nil`), so the
84
+ conformance is `@preconcurrency`: the methods stay main-actor isolated and
85
+ touch `calls` directly. Marking them `nonisolated` and hopping back with
86
+ `Task { @MainActor in ... }` does not compile under Swift 6, because the task
87
+ would carry the non-`Sendable` `CXAction` off the delegate call ("sending
88
+ 'hold' risks causing data races").
174
89
 
175
- nonisolated func provider(
176
- _ provider: CXProvider,
177
- perform action: CXAnswerCallAction
178
- ) {
179
- Task { @MainActor in
180
- configureAudioSession()
181
- connectToServer(callUUID: action.callUUID) { success in
182
- if success {
183
- activeCalls[action.callUUID]?.isConnected = true
184
- action.fulfill()
185
- } else {
186
- provider.reportCall(
187
- with: action.callUUID,
188
- endedAt: Date(),
189
- reason: .failed
190
- )
191
- action.fail()
192
- }
193
- }
194
- }
195
- }
196
-
197
- nonisolated func provider(
198
- _ provider: CXProvider,
199
- perform action: CXStartCallAction
200
- ) {
201
- Task { @MainActor in
202
- configureAudioSession()
203
- provider.reportOutgoingCall(
204
- with: action.callUUID,
205
- startedConnectingAt: Date()
206
- )
207
- connectToServer(callUUID: action.callUUID)
208
- provider.reportOutgoingCall(
209
- with: action.callUUID,
210
- connectedAt: Date()
211
- )
212
- activeCalls[action.callUUID]?.isConnected = true
213
- action.fulfill()
214
- }
215
- }
216
-
217
- nonisolated func provider(
218
- _ provider: CXProvider,
219
- perform action: CXEndCallAction
220
- ) {
221
- Task { @MainActor in
222
- disconnectCall(action.callUUID)
223
- activeCalls.removeValue(forKey: action.callUUID)
224
- action.fulfill()
90
+ ```swift
91
+ extension Switchboard: @preconcurrency CXProviderDelegate {
92
+ func providerDidReset(_ cx: CXProvider) {
93
+ Task {
94
+ for id in calls.keys { await CallMedia.shared.disconnect(id) }
95
+ calls.removeAll()
225
96
  }
226
97
  }
227
98
 
228
- nonisolated func provider(
229
- _ provider: CXProvider,
230
- didActivate audioSession: AVAudioSession
231
- ) {
232
- Task { @MainActor in
233
- startAudioEngine()
234
- }
99
+ func provider(_ cx: CXProvider, perform hold: CXSetHeldCallAction) {
100
+ let id = hold.callUUID
101
+ calls[id]?.held = hold.isOnHold
102
+ if hold.isOnHold { CallMedia.shared.pause(id) } else { CallMedia.shared.resume(id) }
103
+ hold.fulfill()
235
104
  }
236
105
 
237
- nonisolated func provider(
238
- _ provider: CXProvider,
239
- didDeactivate audioSession: AVAudioSession
240
- ) {
241
- Task { @MainActor in
242
- stopAudioEngine()
243
- }
106
+ func provider(_ cx: CXProvider, perform mute: CXSetMutedCallAction) {
107
+ calls[mute.callUUID]?.muted = mute.isMuted
108
+ CallMedia.shared.setMicrophoneMuted(mute.isMuted)
109
+ mute.fulfill()
244
110
  }
245
111
  }
246
112
  ```
247
113
 
248
- ## Multiple Concurrent Calls
114
+ Muting only silences the microphone input. Upstream audio keeps flowing,
115
+ because iOS 26 call translation depends on it.
249
116
 
250
- When a second call arrives while one is active, CallKit automatically puts
251
- the first call on hold. Handle the hold action to pause your audio stream:
117
+ The answer, start, end, `didActivate` and `didDeactivate` handlers are the same
118
+ as in SKILL.md, with bookkeeping added: set `connected = true` once media
119
+ connects, and remove the entry when the call ends.
252
120
 
253
- ```swift
254
- nonisolated func provider(
255
- _ provider: CXProvider,
256
- perform action: CXSetHeldCallAction
257
- ) {
258
- Task { @MainActor in
259
- if action.isOnHold {
260
- // Pause the RTP stream for this call
261
- pauseMediaStream(for: action.callUUID)
262
- } else {
263
- // Resume the RTP stream
264
- resumeMediaStream(for: action.callUUID)
265
- }
266
- activeCalls[action.callUUID]?.isOnHold = action.isOnHold
267
- action.fulfill()
268
- }
269
- }
270
- ```
121
+ ## Several calls at once
271
122
 
272
- Configure `maximumCallGroups` and `maximumCallsPerCallGroup` in
273
- `CXProviderConfiguration` to control how many concurrent calls your app
274
- supports.
123
+ When a second call rings while one is active and the user accepts it, CallKit
124
+ holds the first call on its own. The app sees a `CXSetHeldCallAction` for the
125
+ first call and must pause or resume its media stream (for example the RTP
126
+ session) in response. How many calls may coexist is set by
127
+ `maximumCallGroups` and `maximumCallsPerCallGroup` in the configuration.
275
128
 
276
- ## Call State Tracking
129
+ ## Watching call state
277
130
 
278
- Use `CXCallObserver` to monitor call state changes from outside the provider
279
- delegate:
131
+ `CXCallObserver` reports every call on the device, which is useful outside the
132
+ provider delegate, for example in a status view.
280
133
 
281
134
  ```swift
282
135
  import CallKit
283
136
 
284
- final class CallStateObserver: NSObject, CXCallObserverDelegate {
285
- let observer = CXCallObserver()
137
+ final class CallWatcher: NSObject, CXCallObserverDelegate {
138
+ private let monitor = CXCallObserver()
286
139
 
287
140
  override init() {
288
141
  super.init()
289
- observer.setDelegate(self, queue: nil)
142
+ monitor.setDelegate(self, queue: .main)
290
143
  }
291
144
 
292
- func callObserver(
293
- _ callObserver: CXCallObserver,
294
- callChanged call: CXCall
295
- ) {
145
+ func callObserver(_ watcher: CXCallObserver, callChanged call: CXCall) {
146
+ let phase: String
296
147
  if call.hasEnded {
297
- print("Call \(call.uuid) ended")
148
+ phase = "ended"
298
149
  } else if call.hasConnected {
299
- print("Call \(call.uuid) connected")
150
+ phase = "connected"
300
151
  } else if call.isOutgoing {
301
- print("Outgoing call \(call.uuid) ringing")
152
+ phase = "dialing"
302
153
  } else {
303
- print("Incoming call \(call.uuid) ringing")
154
+ phase = "ringing"
304
155
  }
156
+ Log.calls.info("\(call.uuid) is \(phase)")
305
157
  }
306
158
  }
307
159
  ```
308
160
 
309
- ## Encrypted VoIP Push Filtering
161
+ ## Filtering encrypted VoIP pushes
310
162
 
311
- Use a notification service extension with
312
- `CXProvider.reportNewIncomingVoIPPushPayload` only when server-side metadata
313
- encryption means the server cannot determine whether the outgoing notification
314
- is a VoIP call request or some other data. If the server knows the content is
315
- a VoIP call, send a normal PushKit VoIP push instead.
163
+ When the server sends end-to-end encrypted content and cannot tell whether it
164
+ is a call, a notification service extension decrypts it and hands call
165
+ payloads to CallKit.
316
166
 
317
167
  ```swift
318
- import UserNotifications
319
168
  import CallKit
169
+ import UserNotifications
320
170
 
321
- final class NotificationService: UNNotificationServiceExtension {
322
- override func didReceive(
323
- _ request: UNNotificationRequest,
324
- withContentHandler contentHandler:
325
- @escaping (UNNotificationContent) -> Void
326
- ) {
327
- guard let encryptedPayload = request.content
328
- .userInfo["encrypted"] as? [AnyHashable: Any] else {
329
- contentHandler(request.content)
171
+ final class PushFilter: UNNotificationServiceExtension {
172
+ override func didReceive(_ incoming: UNNotificationRequest,
173
+ withContentHandler deliver: @escaping (UNNotificationContent) -> Void) {
174
+ guard let sealed = incoming.content.userInfo["sealed"] as? String,
175
+ let opened = Envelope.open(sealed) else {
176
+ deliver(incoming.content)
330
177
  return
331
178
  }
332
-
333
- let decryptedPayload = decryptPayload(encryptedPayload)
334
-
335
- CXProvider.reportNewIncomingVoIPPushPayload(
336
- decryptedPayload
337
- ) { error in
338
- if let error {
339
- // Show a missed-call notification instead
340
- let content = UNMutableNotificationContent()
341
- content.title = "Missed Call"
342
- content.body = decryptedPayload["callerName"] as? String ?? ""
343
- contentHandler(content)
344
- } else {
345
- // Call was reported; suppress the notification
346
- contentHandler(UNNotificationContent())
179
+ nonisolated(unsafe) let deliver = deliver
180
+ CXProvider.reportNewIncomingVoIPPushPayload(opened) { failure in
181
+ guard failure != nil else {
182
+ deliver(UNNotificationContent())
183
+ return
347
184
  }
185
+ let missed = UNMutableNotificationContent()
186
+ missed.title = String(localized: "Missed call")
187
+ deliver(missed)
348
188
  }
349
189
  }
350
190
  }
351
191
  ```
352
192
 
353
- This requires the `com.apple.developer.usernotifications.filtering` entitlement.
193
+ Content that was not encrypted passes through untouched. The content handler
194
+ is not `Sendable`, and both forms of `reportNewIncomingVoIPPushPayload` need it
195
+ somewhere concurrent: the completion form runs its callback as `@Sendable`, and
196
+ the async form needs a `Task` whose closure Swift 6 rejects for capturing the
197
+ handler. The `nonisolated(unsafe)` copy lets the `@Sendable` callback hold it. A failed report turns
198
+ into a missed-call notification; a successful one is suppressed with empty
199
+ content. If the server does know the push is a call, skip all of this and use
200
+ an ordinary PushKit VoIP push. Entitlement required for the extension:
201
+ `com.apple.developer.usernotifications.filtering`.
354
202
 
355
- ## Call Directory Incremental Updates
203
+ ## Incremental Call Directory updates
356
204
 
357
- After the first full load, use incremental updates to add or remove entries
358
- without reloading the entire dataset:
205
+ Once the initial complete load has run, the extension can add and remove individual numbers
206
+ instead of rebuilding everything.
359
207
 
360
208
  ```swift
361
- private func addOrRemoveIncrementalEntries(
362
- to context: CXCallDirectoryExtensionContext
363
- ) {
364
- let removedNumbers: [CXCallDirectoryPhoneNumber] = fetchRemovedNumbers()
365
- for number in removedNumbers {
366
- context.removeBlockingEntry(withPhoneNumber: number)
367
- context.removeIdentificationEntry(withPhoneNumber: number)
368
- }
369
-
370
- let newBlocked: [CXCallDirectoryPhoneNumber] = fetchNewBlockedNumbers()
371
- for number in newBlocked.sorted() {
372
- context.addBlockingEntry(withNextSequentialPhoneNumber: number)
373
- }
374
-
375
- let newIdentified: [(CXCallDirectoryPhoneNumber, String)] = fetchNewIdentified()
376
- for (number, label) in newIdentified.sorted(by: { $0.0 < $1.0 }) {
377
- context.addIdentificationEntry(
378
- withNextSequentialPhoneNumber: number,
379
- label: label
380
- )
209
+ extension SpamListProvider {
210
+ func applyChanges(to context: CXCallDirectoryExtensionContext) {
211
+ let delta = SharedStore.pendingDelta()
212
+ for number in delta.unblocked {
213
+ context.removeBlockingEntry(withPhoneNumber: number)
214
+ }
215
+ for number in delta.unlabeled {
216
+ context.removeIdentificationEntry(withPhoneNumber: number)
217
+ }
218
+ for number in delta.blocked.sorted() {
219
+ context.addBlockingEntry(withNextSequentialPhoneNumber: number)
220
+ }
221
+ for pair in delta.labeled.sorted(by: { $0.key < $1.key }) {
222
+ context.addIdentificationEntry(withNextSequentialPhoneNumber: pair.key, label: pair.value)
223
+ }
224
+ SharedStore.clearDelta()
381
225
  }
382
226
  }
383
227
  ```
384
228
 
385
- Call Directory data is bulk data. The system calls `beginRequest(with:)` when
386
- loading the extension, not for each individual incoming call, so keep web
387
- lookups and dataset sync in the containing app before reloading the extension.
388
-
389
- ## Testing VoIP Locally
229
+ Additions are sorted before they are added. The system runs
230
+ `beginRequest(with:)` when it loads the extension, never per incoming call, so
231
+ any web lookup and dataset sync happens in the containing app before it calls
232
+ `reloadExtension(withIdentifier:)`.
390
233
 
391
- ### Simulating VoIP Pushes
234
+ ## Testing VoIP locally
392
235
 
393
- Use the Push Notifications Console or a command-line tool to send test pushes.
394
- The payload must target the VoIP topic (`<bundle-id>.voip`):
236
+ - Fire test pushes with the Push Notifications Console, or with any APNs
237
+ client you run from a terminal. The topic is the bundle identifier with `.voip` appended, for example
238
+ `com.example.dialer.voip`.
239
+ - A test payload needs only an empty `aps` plus your own keys:
395
240
 
396
241
  ```json
397
242
  {
398
- "aps": {},
399
- "handle": "+15551234567",
400
- "callerName": "Test Caller",
401
- "hasVideo": false
243
+ "aps": {},
244
+ "from": "+14155550123",
245
+ "display": "Test Caller",
246
+ "video": false
402
247
  }
403
248
  ```
404
249
 
405
- ### Testing Without a Server
406
-
407
- For development, you can bypass PushKit and directly call the incoming call
408
- reporting method:
250
+ - Without a server, a debug-only helper can call the incoming report directly:
409
251
 
410
252
  ```swift
411
253
  #if DEBUG
412
- func simulateIncomingCall() {
413
- let uuid = UUID()
414
- Task {
415
- try? await CallManager.shared.reportIncomingCall(
416
- uuid: uuid,
417
- handle: "+15551234567",
418
- hasVideo: false
419
- )
254
+ extension Switchboard {
255
+ func simulateIncomingCall() async {
256
+ try? await reportIncoming(id: UUID(), address: "+14155550123", name: "Test Caller")
420
257
  }
421
258
  }
422
259
  #endif
423
260
  ```
424
261
 
425
- ### Checking Extension Status
426
-
427
- Verify that the Call Directory extension is enabled:
262
+ - Check the Call Directory extension state from the app:
428
263
 
429
264
  ```swift
430
- CXCallDirectoryManager.sharedInstance.getEnabledStatusForExtension(
431
- withIdentifier: "com.example.app.CallDirectory"
432
- ) { status, error in
433
- switch status {
434
- case .enabled:
435
- print("Extension is enabled")
436
- case .disabled:
437
- print("Extension is disabled -- prompt user to enable in Settings")
438
- case .unknown:
439
- print("Status unknown")
440
- @unknown default:
441
- break
265
+ func checkBlockerStatus() {
266
+ let manager = CXCallDirectoryManager.sharedInstance
267
+ manager.getEnabledStatusForExtension(withIdentifier: "org.sample.dialer.blocker") { state, failure in
268
+ switch state {
269
+ case .enabled: Log.calls.info("blocker active")
270
+ case .disabled: Log.calls.info("ask the user to enable it in Settings")
271
+ case .unknown: Log.calls.info("status unknown: \(String(describing: failure))")
272
+ @unknown default: break
273
+ }
442
274
  }
443
275
  }
444
276
  ```