@mmerterden/multi-agent-pipeline 20.7.0 → 20.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (284) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/LICENSE +0 -10
  3. package/docs/facts.json +1 -1
  4. package/manifest.json +285 -285
  5. package/package.json +3 -3
  6. package/pipeline/lib/redact.mjs +3 -2
  7. package/pipeline/scripts/_notices.mjs +1 -1
  8. package/pipeline/scripts/gen-skills-index.mjs +13 -1
  9. package/pipeline/scripts/pre-commit-check.sh +4 -0
  10. package/pipeline/skills/.skill-manifest.json +69 -69
  11. package/pipeline/skills/shared/README.md +70 -70
  12. package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
  13. package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
  14. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
  15. package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
  16. package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
  17. package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
  18. package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
  19. package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
  20. package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
  21. package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
  22. package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
  23. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +345 -277
  24. package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
  25. package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +107 -121
  26. package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +145 -165
  27. package/pipeline/skills/shared/external/app-store-review/SKILL.md +306 -326
  28. package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
  29. package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
  30. package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
  31. package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +335 -360
  32. package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
  33. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
  34. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
  35. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
  36. package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
  37. package/pipeline/skills/shared/external/authentication/SKILL.md +277 -381
  38. package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
  39. package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +135 -178
  40. package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
  41. package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
  42. package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
  43. package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
  44. package/pipeline/skills/shared/external/background-processing/SKILL.md +274 -384
  45. package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
  46. package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +173 -321
  47. package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
  48. package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
  49. package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
  50. package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
  51. package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
  52. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
  53. package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
  54. package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
  55. package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
  56. package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +228 -376
  57. package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
  58. package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
  59. package/pipeline/skills/shared/external/core-data/SKILL.md +302 -368
  60. package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
  61. package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
  62. package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
  63. package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
  64. package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
  65. package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
  66. package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
  67. package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
  68. package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
  69. package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
  70. package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
  71. package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
  72. package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
  73. package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
  74. package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
  75. package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
  76. package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
  77. package/pipeline/skills/shared/external/device-integrity/SKILL.md +236 -353
  78. package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
  79. package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
  80. package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
  81. package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
  82. package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
  83. package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
  84. package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
  85. package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
  86. package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
  87. package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
  88. package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
  89. package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
  90. package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
  91. package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
  92. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
  93. package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
  94. package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
  95. package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
  96. package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
  97. package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
  98. package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
  99. package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
  100. package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
  101. package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
  102. package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
  103. package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
  104. package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
  105. package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
  106. package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
  107. package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
  108. package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
  109. package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
  110. package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
  111. package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
  112. package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
  113. package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
  114. package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +3 -3
  115. package/pipeline/skills/shared/external/localization-reuse-map/example-mapping.json +1 -1
  116. package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +8 -7
  117. package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +2 -2
  118. package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +5 -2
  119. package/pipeline/skills/shared/external/localization-reuse-map/scripts/_shared.py +100 -0
  120. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +45 -26
  121. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +14 -16
  122. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +12 -5
  123. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +2 -1
  124. package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +6 -5
  125. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +44 -18
  126. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +5 -2
  127. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +10 -11
  128. package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +4 -33
  129. package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +12 -59
  130. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +297 -267
  131. package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
  132. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
  133. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
  134. package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
  135. package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
  136. package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
  137. package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
  138. package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
  139. package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
  140. package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
  141. package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
  142. package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
  143. package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
  144. package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
  145. package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
  146. package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
  147. package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
  148. package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
  149. package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
  150. package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
  151. package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
  152. package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
  153. package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
  154. package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
  155. package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
  156. package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
  157. package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
  158. package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
  159. package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
  160. package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
  161. package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
  162. package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
  163. package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
  164. package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
  165. package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
  166. package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
  167. package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
  168. package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
  169. package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
  170. package/pipeline/skills/shared/external/skill-creator/template.md +7 -1
  171. package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
  172. package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
  173. package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
  174. package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
  175. package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
  176. package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
  177. package/pipeline/skills/shared/external/storekit/references/core-patterns.md +302 -241
  178. package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
  179. package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
  180. package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
  181. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
  182. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
  183. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
  184. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
  185. package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
  186. package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
  187. package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
  188. package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
  189. package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
  190. package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
  191. package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
  192. package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +304 -351
  193. package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
  194. package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
  195. package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
  196. package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
  197. package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
  198. package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
  199. package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
  200. package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
  201. package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
  202. package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
  203. package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
  204. package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
  205. package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
  206. package/pipeline/skills/shared/external/swift-security/SKILL.md +183 -162
  207. package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
  208. package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
  209. package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +411 -476
  210. package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
  211. package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
  212. package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
  213. package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
  214. package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
  215. package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
  216. package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +375 -491
  217. package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
  218. package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
  219. package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
  220. package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +397 -457
  221. package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
  222. package/pipeline/skills/shared/external/swift-testing/SKILL.md +191 -175
  223. package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
  224. package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +81 -84
  225. package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
  226. package/pipeline/skills/shared/external/swiftdata/SKILL.md +394 -256
  227. package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
  228. package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
  229. package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
  230. package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
  231. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
  232. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
  233. package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
  234. package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
  235. package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
  236. package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
  237. package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
  238. package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
  239. package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
  240. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
  241. package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
  242. package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
  243. package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
  244. package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
  245. package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
  246. package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
  247. package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
  248. package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
  249. package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
  250. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
  251. package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +201 -168
  252. package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
  253. package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +134 -133
  254. package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
  255. package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +111 -138
  256. package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
  257. package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
  258. package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
  259. package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
  260. package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
  261. package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
  262. package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
  263. package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
  264. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
  265. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
  266. package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
  267. package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
  268. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
  269. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
  270. package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
  271. package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
  272. package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
  273. package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
  274. package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
  275. package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
  276. package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
  277. package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
  278. package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
  279. package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
  280. package/pipeline/skills/shared/external/weatherkit/SKILL.md +160 -315
  281. package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
  282. package/pipeline/skills/shared/external/widgetkit/SKILL.md +224 -288
  283. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +416 -719
  284. package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
@@ -1,9 +1,9 @@
1
- # Network.framework
1
+ # Network Framework
2
2
 
3
- Low-level networking with the Network framework. Use when you need TCP/UDP
4
- connections, WebSockets, Bonjour service discovery, local servers, or network
5
- path monitoring beyond what URLSession provides. All examples target
6
- Swift 6.3 / iOS 26+.
3
+ Reach for Network.framework when URLSession is the wrong layer: raw TCP or
4
+ UDP, a WebSocket at the protocol level, Bonjour discovery, a local server, or
5
+ detailed path monitoring. Ordinary HTTP APIs stay on URLSession. Examples
6
+ assume Swift 6.3 and iOS 26.
7
7
 
8
8
  ## Contents
9
9
 
@@ -14,575 +14,350 @@ Swift 6.3 / iOS 26+.
14
14
  - [NWParameters Configuration](#nwparameters-configuration)
15
15
  - [TLS Configuration](#tls-configuration)
16
16
  - [WebSocket Support](#websocket-support)
17
- - [NetworkConnection (iOS 26+)](#networkconnection-ios-26)
17
+ - [The iOS 26 NetworkConnection API](#the-ios-26-networkconnection-api)
18
18
 
19
19
  ## NWConnection
20
20
 
21
- A bidirectional data connection between a local and remote endpoint. Supports
22
- TCP, UDP, TLS, DTLS, QUIC, and WebSocket protocols.
23
-
24
- **Documentation:**
25
- [sosumi.ai/documentation/network/nwconnection](https://sosumi.ai/documentation/network/nwconnection)
26
-
27
- ### TCP Connection
21
+ `NWConnection` is one bidirectional connection. It speaks TCP, UDP, TLS,
22
+ DTLS, QUIC and WebSocket depending on its parameters.
23
+ API reference: [NWConnection docs](https://developer.apple.com/documentation/network/nwconnection).
28
24
 
29
25
  ```swift
26
+ import Foundation
30
27
  import Network
28
+ import OSLog
31
29
 
32
- let connection = NWConnection(
33
- host: "api.example.com",
34
- port: 443,
35
- using: .tls
36
- )
30
+ extension Logger { static let net = Logger(subsystem: "app.networking", category: "net") }
37
31
 
38
- connection.stateUpdateHandler = { state in
32
+ let link = NWConnection(host: "telemetry.example.net", port: 443, using: .tls)
33
+ link.stateUpdateHandler = { state in
39
34
  switch state {
40
- case .ready:
41
- print("Connected")
42
- case .waiting(let error):
43
- print("Waiting: \(error.localizedDescription)")
44
- case .failed(let error):
45
- print("Failed: \(error.localizedDescription)")
46
- case .cancelled:
47
- print("Cancelled")
48
- default:
49
- break
35
+ case .ready: Logger.net.info("connected")
36
+ case .waiting(let error): Logger.net.notice("waiting for a path: \(error.localizedDescription)")
37
+ case .failed(let error): Logger.net.error("failed: \(error.localizedDescription)"); link.cancel()
38
+ case .cancelled: Logger.net.info("closed")
39
+ default: break
50
40
  }
51
41
  }
52
-
53
- connection.start(queue: .main)
54
- ```
55
-
56
- ### Sending Data
57
-
58
- ```swift
59
- func send(_ data: Data, on connection: NWConnection) {
60
- connection.send(
61
- content: data,
62
- contentContext: .defaultMessage,
63
- isComplete: true,
64
- completion: .contentProcessed { error in
65
- if let error {
66
- print("Send error: \(error)")
67
- }
68
- }
69
- )
70
- }
71
- ```
72
-
73
- ### Receiving Data
74
-
75
- ```swift
76
- func receive(on connection: NWConnection) {
77
- connection.receive(
78
- minimumIncompleteLength: 1,
79
- maximumLength: 65536
80
- ) { content, contentContext, isComplete, error in
81
- if let data = content {
82
- handleData(data)
83
- }
84
- if isComplete {
85
- connection.cancel()
86
- } else if let error {
87
- print("Receive error: \(error)")
88
- } else {
89
- // Continue receiving
90
- receive(on: connection)
42
+ link.start(queue: .main)
43
+
44
+ link.send(content: Data("HELLO\n".utf8), contentContext: .defaultMessage, isComplete: true,
45
+ completion: .contentProcessed { error in
46
+ if let error { Logger.net.error("send failed: \(error.localizedDescription)") }
47
+ })
48
+
49
+ func readLoop(on connection: NWConnection) {
50
+ connection.receive(minimumIncompleteLength: 1, maximumLength: 65_536) { data, _, isComplete, error in
51
+ if let data, !data.isEmpty { consume(data) }
52
+ if let error {
53
+ Logger.net.error("receive failed: \(error.localizedDescription)")
54
+ return
91
55
  }
56
+ if isComplete { connection.cancel(); return }
57
+ readLoop(on: connection)
92
58
  }
93
59
  }
94
60
  ```
95
61
 
96
- ### UDP Connection
62
+ UDP uses the same type:
97
63
 
98
64
  ```swift
99
- let udpConnection = NWConnection(
100
- host: "239.0.0.1",
101
- port: 5000,
102
- using: .udp
103
- )
104
-
105
- udpConnection.stateUpdateHandler = { state in
65
+ let beacon = NWConnection(host: "239.255.10.20", port: 6200, using: .udp)
66
+ beacon.stateUpdateHandler = { state in
106
67
  if case .ready = state {
107
- let message = "Hello".data(using: .utf8)!
108
- udpConnection.send(
109
- content: message,
110
- completion: .contentProcessed { _ in }
111
- )
68
+ beacon.send(content: Data("ping".utf8), completion: .contentProcessed { _ in })
112
69
  }
113
70
  }
114
-
115
- udpConnection.start(queue: .main)
71
+ beacon.start(queue: .global())
116
72
  ```
117
73
 
118
- ### Connection Lifecycle
119
-
120
- States flow in order: `setup` → `preparing` → `ready` → `cancelled`/`failed`.
121
- A connection may enter `waiting(NWError)` if the network path is unavailable
122
- and retry when connectivity returns.
123
-
124
- Always cancel connections when done:
125
-
126
- ```swift
127
- connection.cancel() // Releases resources, transitions to .cancelled
128
- ```
74
+ - States run `setup`, `preparing`, `ready`, and end in `cancelled` or
75
+ `failed`.
76
+ - `waiting(NWError)` means no usable path right now. The connection tries
77
+ again by itself when the network comes back.
78
+ - Call `cancel()` when you are done. It frees the resources and moves the
79
+ connection to `cancelled`.
129
80
 
130
81
  ## NWListener
131
82
 
132
- An object that listens for incoming network connections. Use to create local
133
- TCP/UDP servers.
134
-
135
- **Documentation:**
136
- [sosumi.ai/documentation/network/nwlistener](https://sosumi.ai/documentation/network/nwlistener)
137
-
138
- ### TCP Server
83
+ `NWListener` accepts incoming connections, which is how you run a small TCP
84
+ or UDP server on the device.
85
+ API reference: [NWListener docs](https://developer.apple.com/documentation/network/nwlistener).
139
86
 
140
87
  ```swift
141
- import Network
142
-
143
- func startServer(port: UInt16) throws -> NWListener {
144
- let listener = try NWListener(using: .tcp, on: NWEndpoint.Port(rawValue: port)!)
145
-
146
- listener.stateUpdateHandler = { state in
88
+ func startServer() throws -> NWListener {
89
+ let port: NWEndpoint.Port = 8080
90
+ let server = try NWListener(using: .tcp, on: port)
91
+ server.stateUpdateHandler = { state in
147
92
  switch state {
148
- case .ready:
149
- print("Listening on port \(listener.port?.rawValue ?? 0)")
150
- case .failed(let error):
151
- print("Listener failed: \(error)")
152
- listener.cancel()
153
- default:
154
- break
93
+ case .ready: Logger.net.info("listening on \(server.port?.rawValue ?? 0)")
94
+ case .failed(let error): Logger.net.error("\(error.localizedDescription)"); server.cancel()
95
+ default: break
155
96
  }
156
97
  }
157
-
158
- listener.newConnectionHandler = { connection in
159
- print("New connection from \(connection.endpoint)")
160
- connection.stateUpdateHandler = { state in
161
- if case .ready = state {
162
- receive(on: connection)
163
- }
98
+ server.newConnectionHandler = { incoming in
99
+ incoming.stateUpdateHandler = { state in
100
+ if case .ready = state { readLoop(on: incoming) }
164
101
  }
165
- connection.start(queue: .main)
102
+ incoming.start(queue: .global())
166
103
  }
167
-
168
- listener.start(queue: .main)
169
- return listener
170
- }
171
- ```
172
-
173
- ### Advertising via Bonjour
174
-
175
- ```swift
176
- let listener = try NWListener(using: .tcp)
177
- listener.service = NWListener.Service(
178
- name: "MyApp",
179
- type: "_myapp._tcp"
180
- )
181
- listener.serviceRegistrationUpdateHandler = { change in
182
- switch change {
183
- case .add(let endpoint):
184
- print("Service registered: \(endpoint)")
185
- default:
186
- break
104
+ server.service = NWListener.Service(name: "Workbench", type: "_workbench._tcp")
105
+ server.serviceRegistrationUpdateHandler = { change in
106
+ if case .add(let endpoint) = change { Logger.net.info("advertised \(String(describing: endpoint))") }
187
107
  }
108
+ server.start(queue: .global())
109
+ return server
188
110
  }
189
- listener.start(queue: .main)
190
111
  ```
191
112
 
192
- ## NWBrowser
193
-
194
- Discovers Bonjour/mDNS services on the local network.
113
+ `NWEndpoint.Port` is expressible by an integer literal, so a fixed port
114
+ needs no optional. For a port from user input, use
115
+ `NWEndpoint.Port(rawValue:)` and handle `nil`. Setting `service` advertises
116
+ the listener over Bonjour.
195
117
 
196
- **Documentation:**
197
- [sosumi.ai/documentation/network/nwbrowser](https://sosumi.ai/documentation/network/nwbrowser)
118
+ ## NWBrowser
198
119
 
199
- ### Service Discovery
120
+ `NWBrowser` discovers peers that advertise over Bonjour (multicast DNS) on the LAN.
121
+ API reference: [NWBrowser docs](https://developer.apple.com/documentation/network/nwbrowser).
200
122
 
201
123
  ```swift
202
- import Network
203
-
204
- let browser = NWBrowser(
205
- for: .bonjour(type: "_myapp._tcp", domain: nil),
206
- using: .tcp
207
- )
208
-
209
- browser.stateUpdateHandler = { state in
210
- if case .failed(let error) = state {
211
- print("Browser failed: \(error)")
212
- }
213
- }
214
-
215
- browser.browseResultsChangedHandler = { results, changes in
216
- for result in results {
217
- switch result.endpoint {
218
- case .service(let name, let type, let domain, _):
219
- print("Found: \(name).\(type)\(domain)")
220
- default:
221
- break
222
- }
223
- }
224
-
124
+ let scanner = NWBrowser(for: .bonjour(type: "_workbench._tcp", domain: nil), using: .tcp)
125
+ scanner.browseResultsChangedHandler = { results, changes in
225
126
  for change in changes {
226
127
  switch change {
227
- case .added(let result):
228
- print("Added: \(result.endpoint)")
229
- case .removed(let result):
230
- print("Removed: \(result.endpoint)")
231
- default:
232
- break
128
+ case .added(let found):
129
+ if case .service(let name, _, _, _) = found.endpoint { Logger.net.info("found \(name)") }
130
+ case .removed(let gone):
131
+ Logger.net.info("lost \(String(describing: gone.endpoint))")
132
+ default: break
233
133
  }
234
134
  }
235
135
  }
136
+ scanner.start(queue: .main)
236
137
 
237
- browser.start(queue: .main)
138
+ func connect(to found: NWBrowser.Result) -> NWConnection {
139
+ NWConnection(to: found.endpoint, using: .tcp)
140
+ }
238
141
  ```
239
142
 
240
- ### Connecting to a Discovered Service
241
-
242
- ```swift
243
- // result is an NWBrowser.Result from browseResultsChangedHandler
244
- let connection = NWConnection(to: result.endpoint, using: .tcp)
245
- connection.start(queue: .main)
246
- ```
143
+ The handler receives the full current `results` set and the `changes`
144
+ (`.added`, `.removed`) since the last call.
247
145
 
248
146
  ## NWPathMonitor
249
147
 
250
- Monitors network path changes. Replaces the deprecated `SCNetworkReachability`
251
- API. Use to detect connectivity changes, expensive paths (cellular), and
252
- constrained paths (Low Data Mode).
253
-
254
- **Documentation:**
255
- [sosumi.ai/documentation/network/nwpathmonitor](https://sosumi.ai/documentation/network/nwpathmonitor)
256
-
257
- ### Basic Reachability with AsyncSequence
148
+ `NWPathMonitor` replaces the deprecated `SCNetworkReachability`. It reports
149
+ whether a path exists and whether it is expensive or constrained.
150
+ API reference: [NWPathMonitor docs](https://developer.apple.com/documentation/network/nwpathmonitor).
258
151
 
259
152
  ```swift
260
- import Network
261
-
262
153
  @MainActor @Observable
263
- class ConnectivityModel {
264
- var isConnected = true
265
- var isExpensive = false
266
- var isConstrained = false
267
-
268
- func startMonitoring() async {
269
- let monitor = NWPathMonitor()
270
-
271
- for await path in monitor {
272
- isConnected = path.status == .satisfied
273
- isExpensive = path.isExpensive // Cellular
274
- isConstrained = path.isConstrained // Low Data Mode
154
+ final class LinkQuality {
155
+ private(set) var online = true
156
+ private(set) var metered = false
157
+ private(set) var lowData = false
158
+
159
+ func watch() async {
160
+ for await path in NWPathMonitor() {
161
+ online = path.status == .satisfied
162
+ metered = path.isExpensive
163
+ lowData = path.isConstrained
275
164
  }
276
165
  }
166
+
167
+ var imagePolicy: ImagePolicy {
168
+ if lowData { return ImagePolicy(quality: .low, prefetch: false, preloadVideo: false) }
169
+ if metered { return ImagePolicy(quality: .standard, prefetch: true, preloadVideo: false) }
170
+ return ImagePolicy(quality: .high, prefetch: true, preloadVideo: true)
171
+ }
277
172
  }
278
173
  ```
279
174
 
280
- ### Monitor Specific Interface
175
+ Start `watch()` from a `.task` so the loop ends with the view. To watch one
176
+ interface type, or on an SDK where the monitor is not yet an async sequence,
177
+ use the handler API:
281
178
 
282
179
  ```swift
283
- // Monitor only Wi-Fi
284
- let wifiMonitor = NWPathMonitor(requiredInterfaceType: .wifi)
285
- wifiMonitor.pathUpdateHandler = { path in
286
- print("Wi-Fi: \(path.status)")
180
+ let wifiOnly = NWPathMonitor(requiredInterfaceType: .wifi)
181
+ wifiOnly.pathUpdateHandler = { path in
182
+ Logger.net.info("wifi path: \(String(describing: path.status))")
287
183
  }
288
- wifiMonitor.start(queue: .global())
184
+ wifiOnly.start(queue: .global())
289
185
  ```
290
186
 
291
- ### Key NWPath Properties
292
-
293
- | Property | Description |
187
+ | `NWPath` member | Meaning |
294
188
  |---|---|
295
- | `status` | `.satisfied`, `.unsatisfied`, or `.requiresConnection` |
296
- | `isExpensive` | `true` on cellular or personal hotspot |
297
- | `isConstrained` | `true` when Low Data Mode is enabled |
298
- | `availableInterfaces` | Array of available `NWInterface` objects |
299
- | `supportsDNS` | Whether DNS resolution is available |
300
- | `supportsIPv4` / `supportsIPv6` | Protocol family support |
189
+ | `status` | `.satisfied`, `.unsatisfied` or `.requiresConnection` |
190
+ | `isExpensive` | Cellular or a personal hotspot |
191
+ | `isConstrained` | Low Data Mode is on |
192
+ | `availableInterfaces` | The `NWInterface` values the path can use |
193
+ | `supportsDNS` | DNS resolution is available |
194
+ | `supportsIPv4`, `supportsIPv6` | Address families the path supports |
301
195
 
302
- ### Adapting Behavior
303
-
304
- ```swift
305
- let monitor = NWPathMonitor()
306
-
307
- for await path in monitor {
308
- if path.isConstrained {
309
- // Low Data Mode: reduce image quality, skip prefetch
310
- imageQuality = .low
311
- } else if path.isExpensive {
312
- // Cellular: use standard quality, skip video preload
313
- imageQuality = .standard
314
- } else {
315
- // Wi-Fi: full quality, prefetch aggressively
316
- imageQuality = .high
317
- }
318
- }
319
- ```
196
+ Adapt to the path: on a constrained path fetch low-quality images and skip
197
+ prefetching; on an expensive path keep standard quality and skip video
198
+ preloading; otherwise use high quality and prefetch freely.
320
199
 
321
200
  ## NWParameters Configuration
322
201
 
323
- `NWParameters` defines the protocols and options for connections and listeners.
202
+ `NWParameters` describes the protocol stack and path rules for a connection
203
+ or listener. Build options objects directly and pass them in, which avoids
204
+ casting them back out of the stack:
324
205
 
325
206
  ```swift
326
- import Network
327
-
328
- // TCP with custom options
329
- let tcpParams = NWParameters.tcp
330
- tcpParams.requiredInterfaceType = .wifi
331
- tcpParams.prohibitExpensivePaths = true
332
- tcpParams.prohibitConstrainedPaths = true
333
-
334
- let tcpOptions = tcpParams.defaultProtocolStack
335
- .transportProtocol as! NWProtocolTCP.Options
336
- tcpOptions.connectionTimeout = 10
337
- tcpOptions.enableKeepalive = true
338
- tcpOptions.keepaliveInterval = 30
339
-
340
- let connection = NWConnection(
341
- host: "api.example.com",
342
- port: 8080,
343
- using: tcpParams
344
- )
207
+ let tcp = NWProtocolTCP.Options()
208
+ tcp.connectionTimeout = 10
209
+ tcp.enableKeepalive = true
210
+ tcp.keepaliveInterval = 30
211
+
212
+ let lanOnly = NWParameters(tls: nil, tcp: tcp)
213
+ lanOnly.requiredInterfaceType = .wifi
214
+ lanOnly.prohibitExpensivePaths = true
215
+ lanOnly.prohibitConstrainedPaths = true
216
+
217
+ let udp = NWProtocolUDP.Options()
218
+ udp.preferNoChecksum = true
219
+ let datagrams = NWParameters(dtls: nil, udp: udp)
345
220
  ```
346
221
 
347
- ### UDP Parameters
348
-
349
- ```swift
350
- let udpParams = NWParameters.udp
351
- let udpOptions = udpParams.defaultProtocolStack
352
- .transportProtocol as! NWProtocolUDP.Options
353
- udpOptions.preferNoChecksum = true
354
-
355
- let connection = NWConnection(
356
- host: "239.0.0.1",
357
- port: 5000,
358
- using: udpParams
359
- )
360
- ```
222
+ If you must adjust a stack you did not build, use a conditional cast:
223
+ `if let tcp = params.defaultProtocolStack.transportProtocol as? NWProtocolTCP.Options`.
361
224
 
362
225
  ## TLS Configuration
363
226
 
364
- Configure TLS for secure connections using `NWProtocolTLS.Options`.
365
- Network.framework operates below the URL Loading System, so ATS does not
366
- automatically enforce URLSession-style policy here. When you use
367
- Network.framework for a secure protocol, configure TLS parameters and trust
368
- handling for that protocol stack; keep deep certificate-trust and SPKI pinning
369
- implementation in `swift-security`.
227
+ TLS is configured with `NWProtocolTLS.Options`. ATS belongs to the URL
228
+ Loading System and does not police this layer, so the TLS version, cipher
229
+ choices and trust evaluation are yours to set. Deep trust work and SPKI
230
+ pinning belong in `swift-security`.
370
231
 
371
232
  ```swift
372
- import Network
373
-
374
- let tlsParams = NWParameters(tls: NWProtocolTLS.Options())
375
-
376
- // Access TLS options for customization
377
- let tlsOptions = tlsParams.defaultProtocolStack
378
- .applicationProtocols.first as! NWProtocolTLS.Options
379
-
380
- sec_protocol_options_set_min_tls_protocol_version(
381
- tlsOptions.securityProtocolOptions,
382
- .TLSv13
383
- )
384
-
385
- let connection = NWConnection(
386
- host: "secure.example.com",
387
- port: 443,
388
- using: tlsParams
389
- )
390
- ```
391
-
392
- ### Inspecting TLS Metadata
393
-
394
- ```swift
395
- connection.stateUpdateHandler = { state in
396
- if case .ready = state {
397
- if let metadata = connection.metadata(
398
- definition: NWProtocolTLS.definition
399
- ) as? NWProtocolTLS.Metadata {
400
- let secMetadata = metadata.securityProtocolMetadata
401
- let negotiatedProtocol = sec_protocol_metadata_get_negotiated_tls_protocol_version(secMetadata)
402
- print("TLS version: \(negotiatedProtocol)")
403
- }
404
- }
233
+ let tls = NWProtocolTLS.Options()
234
+ sec_protocol_options_set_min_tls_protocol_version(tls.securityProtocolOptions, .TLSv13)
235
+ let secure = NWParameters(tls: tls)
236
+
237
+ let session = NWConnection(host: "vault.example.net", port: 8443, using: secure)
238
+ session.stateUpdateHandler = { state in
239
+ guard case .ready = state else { return }
240
+ let raw = session.metadata(definition: NWProtocolTLS.definition)
241
+ guard let meta = raw as? NWProtocolTLS.Metadata else { return }
242
+ let version = sec_protocol_metadata_get_negotiated_tls_protocol_version(meta.securityProtocolMetadata)
243
+ Logger.net.info("negotiated TLS \(version.rawValue)")
405
244
  }
245
+ session.start(queue: .global())
406
246
  ```
407
247
 
408
248
  ## WebSocket Support
409
249
 
410
- Network.framework supports WebSocket via `NWProtocolWebSocket`.
411
-
412
- ### WebSocket Client
250
+ Network.framework exposes WebSocket through `NWProtocolWebSocket`, layered on
251
+ top of TLS and TCP.
413
252
 
414
253
  ```swift
415
- import Network
416
-
417
- func createWebSocketConnection(url: String) -> NWConnection {
418
- let wsOptions = NWProtocolWebSocket.Options()
419
- wsOptions.autoReplyPing = true
420
-
421
- let params = NWParameters.tls
422
- params.defaultProtocolStack.applicationProtocols.insert(
423
- wsOptions, at: 0
424
- )
425
-
426
- let connection = NWConnection(
427
- host: NWEndpoint.Host(url),
428
- port: 443,
429
- using: params
430
- )
431
-
432
- return connection
254
+ let ws = NWProtocolWebSocket.Options()
255
+ ws.autoReplyPing = true
256
+ let params = NWParameters.tls
257
+ params.defaultProtocolStack.applicationProtocols.insert(ws, at: 0)
258
+ let socket = NWConnection(host: "stream.example.net", port: 443, using: params)
259
+
260
+ func sendText(_ message: String, over connection: NWConnection) {
261
+ let meta = NWProtocolWebSocket.Metadata(opcode: .text)
262
+ let context = NWConnection.ContentContext(identifier: "text", metadata: [meta])
263
+ connection.send(content: Data(message.utf8), contentContext: context, isComplete: true,
264
+ completion: .contentProcessed { _ in })
433
265
  }
434
- ```
435
266
 
436
- ### Sending WebSocket Messages
437
-
438
- ```swift
439
- func sendWebSocketMessage(_ text: String, on connection: NWConnection) {
440
- let metadata = NWProtocolWebSocket.Metadata(opcode: .text)
441
- let context = NWConnection.ContentContext(
442
- identifier: "textMessage",
443
- metadata: [metadata]
444
- )
445
-
446
- let data = text.data(using: .utf8)
447
- connection.send(
448
- content: data,
449
- contentContext: context,
450
- isComplete: true,
451
- completion: .contentProcessed { error in
452
- if let error {
453
- print("WebSocket send error: \(error)")
454
- }
455
- }
456
- )
457
- }
458
- ```
459
-
460
- ### Receiving WebSocket Messages
461
-
462
- ```swift
463
- func receiveWebSocketMessage(on connection: NWConnection) {
464
- connection.receiveMessage { data, context, isComplete, error in
465
- if let data,
466
- let metadata = context?.protocolMetadata(
467
- definition: NWProtocolWebSocket.definition
468
- ) as? NWProtocolWebSocket.Metadata {
469
- switch metadata.opcode {
470
- case .text:
471
- let text = String(data: data, encoding: .utf8) ?? ""
472
- print("Received text: \(text)")
473
- case .binary:
474
- print("Received binary: \(data.count) bytes")
475
- case .close:
476
- print("Connection closed")
477
- return
478
- default:
479
- break
480
- }
267
+ func listen(on connection: NWConnection) {
268
+ connection.receiveMessage { data, context, _, error in
269
+ guard error == nil else { return }
270
+ let meta = context?.protocolMetadata(definition: NWProtocolWebSocket.definition)
271
+ as? NWProtocolWebSocket.Metadata
272
+ switch meta?.opcode {
273
+ case .text?, .binary?:
274
+ if let data { consume(data) }
275
+ case .close?:
276
+ connection.cancel()
277
+ return
278
+ default:
279
+ break
481
280
  }
482
- // Continue receiving
483
- receiveWebSocketMessage(on: connection)
281
+ listen(on: connection)
484
282
  }
485
283
  }
486
284
  ```
487
285
 
488
- ## NetworkConnection (iOS 26+)
489
-
490
- `NetworkConnection` is a new Swift-native API introduced in iOS 26 that
491
- provides a modern, type-safe alternative to `NWConnection`. It uses generics
492
- over protocol stacks, supports structured concurrency patterns, and integrates
493
- with async/await via closure-based state handlers.
286
+ With `autoReplyPing` the framework answers pings for you. For app-level
287
+ WebSockets, `URLSessionWebSocketTask` (see
288
+ [background-websocket.md](background-websocket.md#urlsessionwebsockettask))
289
+ is usually simpler.
494
290
 
495
- **Documentation:**
496
- [sosumi.ai/documentation/network/networkconnection](https://sosumi.ai/documentation/network/networkconnection)
291
+ ## The iOS 26 NetworkConnection API
497
292
 
498
- ### Key Differences from NWConnection
293
+ `NetworkConnection` is the Swift-first connection type added in iOS 26. It is
294
+ generic over its protocol stack, uses async/await, and reports state through
295
+ closures. API reference: [NetworkConnection docs](https://developer.apple.com/documentation/network/networkconnection).
499
296
 
500
297
  | | `NWConnection` | `NetworkConnection` |
501
298
  |---|---|---|
502
- | **Availability** | iOS 12+ | iOS 26+ |
503
- | **Type safety** | Untyped protocol stack | Generic `ApplicationProtocol` parameter |
504
- | **Streams** | Single connection | Built-in QUIC stream multiplexing |
505
- | **State updates** | `stateUpdateHandler` callback | `onStateUpdate`, `onPathUpdate` closures |
506
- | **Wi-Fi Aware** | Not supported | `wifiAware` property |
507
- | **API style** | Callback-based | Closure-based with `Sendable` support |
508
-
509
- ### Basic Usage Shape
299
+ | Availability | iOS 12+ | iOS 26+ |
300
+ | Stack typing | Untyped parameters | Generic `ApplicationProtocol` |
301
+ | Streams | One connection | Many QUIC streams share one connection |
302
+ | State | `stateUpdateHandler` | `onStateUpdate` and `onPathUpdate` closures |
303
+ | Wi-Fi Aware | Not available | `wifiAware` property |
304
+ | Style | Callbacks on a queue | Async calls, `Sendable`-aware closures |
510
305
 
511
306
  ```swift
512
- import Network
513
-
514
- let endpoint = NWEndpoint.hostPort(host: "api.example.com", port: 443)
515
- ```
516
-
517
- Use the initializer variant that matches your protocol stack. The documented
518
- forms are:
307
+ let endpoint = NWEndpoint.hostPort(host: "relay.example.net", port: 9443)
519
308
 
520
- ```swift
521
- // Protocol-stack builder form.
522
- NetworkConnection(to: endpoint) {
523
- // ProtocolStackBuilder<ApplicationProtocol>
309
+ let relay = NetworkConnection(to: endpoint) {
310
+ TLS()
524
311
  }
525
312
 
526
- // Parameters-builder form.
527
- NetworkConnection(to: endpoint, using: builder)
528
- ```
529
-
530
- After constructing a concrete connection for your app's protocol stack, install
531
- state handlers and start it:
532
-
533
- ```swift
534
- func startConnection<ApplicationProtocol>(
535
- _ connection: NetworkConnection<ApplicationProtocol>
536
- ) where ApplicationProtocol: NetworkProtocolOptions {
537
- connection.onStateUpdate { state in
313
+ func logStates(of connection: NetworkConnection<TLS>) {
314
+ connection.onStateUpdate { _, state in
538
315
  switch state {
539
- case .ready:
540
- print("Connected")
541
- case .failed(let error):
542
- print("Failed: \(error)")
543
- case .cancelled:
544
- print("Cancelled")
545
- default:
546
- break
316
+ case .ready: Logger.net.info("ready")
317
+ case .failed(let error): Logger.net.error("failed: \(error.localizedDescription)")
318
+ case .cancelled: Logger.net.info("cancelled")
319
+ default: break
547
320
  }
548
321
  }
549
-
550
- connection.start()
551
322
  }
323
+
324
+ logStates(of: relay)
325
+ try await relay.send(Data("status".utf8))
552
326
  ```
553
327
 
554
- `NetworkConnection` is for lower-level protocol stacks and QUIC-style transport
555
- work. Keep ordinary HTTP APIs on `URLSession` unless you need capabilities that
556
- the URL Loading System does not provide.
328
+ The stack can also be built separately and passed with
329
+ `NetworkConnection(to:using:)`. The connection establishes itself when it is
330
+ first used, so the first `send` or `receive` drives it to `ready`.
331
+
332
+ Keep HTTP on URLSession; `NetworkConnection` is for custom protocol stacks
333
+ and QUIC transport.
557
334
 
558
335
  ### QUIC Multiplexed Streams
559
336
 
560
- `NetworkConnection<QUIC>` supports QUIC stream multiplexing natively.
561
- Opening and accepting streams are asynchronous and throwing operations.
337
+ A `NetworkConnection<QUIC>` carries many independent QUIC streams over one
338
+ connection. Opening and accepting streams are both `async throws`. Here `quic` is such a
339
+ connection:
562
340
 
563
341
  ```swift
564
- func openBidirectionalStream(
565
- on connection: NetworkConnection<QUIC>
566
- ) async throws -> QUIC.Stream<QUICStream> {
567
- try await connection.openStream(directionality: .bidirectional)
568
- }
342
+ let outbound = try await quic.openStream(directionality: .bidirectional)
343
+ try await outbound.send(Data("subscribe prices".utf8))
569
344
 
570
- func handleInboundStreams(
571
- on connection: NetworkConnection<QUIC>
572
- ) async throws {
573
- try await connection.inboundStreams { stream in
574
- // Process each incoming QUIC stream.
575
- }
345
+ try await quic.inboundStreams { stream in
346
+ let chunk = try await stream.receive(exactly: 64).content
347
+ route(chunk)
576
348
  }
577
349
  ```
578
350
 
351
+ `openStream` returns a `QUIC.Stream`; `inboundStreams` calls the closure for
352
+ every stream the peer opens. Treat both as fallible suspension points, never
353
+ as synchronous callbacks.
354
+
579
355
  ### Migration Guidance
580
356
 
581
- For new iOS 26+ low-level networking work, evaluate `NetworkConnection` before
582
- adding new `NWConnection` code:
583
- - It provides stronger type safety through its generic `ApplicationProtocol`.
584
- - Stream multiplexing is a first-class concept for QUIC.
585
- - The API is designed for modern Swift with `Sendable` conformance.
357
+ - New low-level code that can require iOS 26: evaluate `NetworkConnection`
358
+ first for typed stacks, first-class QUIC streams and `Sendable`-aware
359
+ design.
360
+ - Apps that still support earlier releases keep `NWConnection`. It is not
361
+ deprecated, and the two can live in the same app.
586
362
 
587
- For projects supporting iOS versions before 26, continue using `NWConnection`.
588
- Both APIs coexist and `NWConnection` is not deprecated.
363
+ The snippets log through `extension Logger { static let net = Logger(subsystem: "app.networking", category: "net") }`.