@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,499 +1,459 @@
1
1
  ---
2
2
  name: swift-language
3
- description: "Modern Swift language patterns for code outside concurrency and SwiftUI: if/switch expressions, typed throws, result builders, property wrappers, some vs any, guard patterns, Never, Regex builders, modern collection APIs and string interpolation. Use when writing core Swift with generics, protocols, enums, closures or new language features; for deep Codable use swift-codable, for formatting swift-formatstyle, for API naming swift-api-design-guidelines."
3
+ description: "Core Swift 6.3 outside concurrency and SwiftUI: if and switch expressions, typed throws, result builders, property wrappers, some vs any, guard, Never, Regex builders, collection APIs, string interpolation, @c interop, module selectors, performance attributes. Use when writing or reviewing plain Swift with generics, protocols, enums, closures or newer language features. Not for deep Codable, formatting, API naming, concurrency or SwiftUI."
4
4
  metadata:
5
- source: "dpearson2699/swift-ios-skills (PolyForm Perimeter 1.0.0)"
5
+ source: multi-agent-pipeline
6
6
  ---
7
7
 
8
- # Swift Language Patterns
8
+ # Swift Language (Swift 6.3)
9
9
 
10
- Core Swift language features and modern syntax patterns targeting Swift 6.3. Covers language constructs, type system features, basic Codable,
11
- string and collection APIs, basic formatting, C interop (`@c`), module disambiguation (`ModuleName::symbol`), and performance attributes (`@specialized`, `@inline(always)`). For `@c` corrections, enumerate invalid Swift-only signature types: `String`, `Array`, `UnsafeBufferPointer`, closures, and generic placeholders. Route deeper Codable/API decoding to `swift-codable`, detailed formatting/localization to `swift-formatstyle`, API naming to `swift-api-design-guidelines`, concurrency to `swift-concurrency`, and SwiftUI state/view work to `swiftui-patterns`.
10
+ This skill owns the language itself: expressions, the type system, error
11
+ typing, DSL-building features, pattern matching and the standard library
12
+ surface that everyday code touches. It also carries the basics of Codable,
13
+ string and collection APIs, simple formatting, C interop through `@c`, module
14
+ disambiguation with `ModuleName::symbol`, and the performance attributes
15
+ `@specialized` and `@inline(always)`. The attribute details live in
16
+ [references/swift-attributes-interop.md](references/swift-attributes-interop.md).
12
17
 
13
- ## Contents
18
+ When a reviewer asks for a `@c` fix, list the Swift-only types that cannot
19
+ appear in the signature: `String`, `Array`, `UnsafeBufferPointer`, closures and
20
+ generic placeholders. Saying "use C types" is not enough.
14
21
 
15
- - [If/Switch Expressions](#ifswitch-expressions)
16
- - [Typed Throws](#typed-throws)
17
- - [Result Builders](#result-builders)
18
- - [Property Wrappers](#property-wrappers)
19
- - [Opaque and Existential Types](#opaque-and-existential-types)
20
- - [Guard Patterns](#guard-patterns)
21
- - [Never Type](#never-type)
22
- - [Regex Builders](#regex-builders)
23
- - [Codable Best Practices](#codable-best-practices)
24
- - [Modern Collection APIs](#modern-collection-apis)
25
- - [FormatStyle](#formatstyle)
26
- - [String Interpolation](#string-interpolation)
27
- - [Common Mistakes](#common-mistakes)
28
- - [Review Checklist](#review-checklist)
29
- - [References](#references)
22
+ Hand-offs:
30
23
 
31
- ## If/Switch Expressions
24
+ | Topic | Skill |
25
+ |---|---|
26
+ | Codable models, key strategies, date decoding, API payloads | `swift-codable` |
27
+ | Format styles, locale behaviour, localized display | `swift-formatstyle` (with `ios-localization` for market QA) |
28
+ | Naming and argument labels | `swift-api-design-guidelines` |
29
+ | Actors, tasks, isolation, Sendable | `swift-concurrency` |
30
+ | SwiftUI state and view structure | `swiftui-patterns` |
31
+
32
+ ## if and switch as expressions
32
33
 
33
- Swift 5.9+ allows `if` and `switch` as expressions that return values. Use them
34
- to assign, return, or initialize directly.
34
+ Since Swift 5.9, `if` and `switch` can produce a value directly for an
35
+ assignment, a `return` or an initializer.
35
36
 
36
37
  ```swift
37
- // Assign from if expression
38
- let icon = if isComplete { "checkmark.circle.fill" } else { "circle" }
39
-
40
- // Assign from switch expression
41
- let label = switch status {
42
- case .draft: "Draft"
43
- case .published: "Published"
44
- case .archived: "Archived"
38
+ enum Tier { case free, plus, pro }
39
+
40
+ func badge(for tier: Tier, trial: Bool) -> String {
41
+ let base = if trial { "Trial" } else { "Member" }
42
+ let suffix = switch tier {
43
+ case .free: ""
44
+ case .plus: " +"
45
+ case .pro: " Pro"
46
+ }
47
+ return base + suffix
45
48
  }
46
49
 
47
- // Works in return position
48
- func color(for priority: Priority) -> Color {
49
- switch priority {
50
- case .high: .red
51
- case .medium: .orange
52
- case .low: .green
50
+ func seatLimit(_ tier: Tier) -> Int {
51
+ switch tier {
52
+ case .free: 1
53
+ case .plus: 5
54
+ case .pro: 50
53
55
  }
54
56
  }
55
57
  ```
56
58
 
57
- **Rules:**
58
- - Every branch must produce a value of the same type.
59
- - Multi-statement branches are not allowed -- each branch is a single expression.
60
- - Wrap in parentheses when used as a function argument to avoid ambiguity.
59
+ Rules to remember:
61
60
 
62
- ## Typed Throws
61
+ - All branches produce one common type.
62
+ - A branch holds exactly one expression. Several statements in a branch are not
63
+ allowed; fall back to a statement form.
64
+ - Wrap the expression in parentheses when it is passed as a function argument,
65
+ so the parser does not misread it.
63
66
 
64
- Swift 6+ allows specifying the error type a function throws.
67
+ ## Typed throws
65
68
 
66
- ```swift
67
- enum ValidationError: Error {
68
- case tooShort, invalidCharacters, alreadyTaken
69
- }
69
+ Swift 6 lets a function name its error type: `throws(ParseFailure)`. Inside,
70
+ `throw .emptyInput` works as shorthand, and a `catch` block at the call site
71
+ gets `error` already typed as `ParseFailure`, so a `switch` over it can be
72
+ exhaustive with no `as?` cast.
70
73
 
71
- func validate(username: String) throws(ValidationError) -> String {
72
- guard username.count >= 3 else { throw .tooShort }
73
- guard username.allSatisfy(\.isLetterOrDigit) else { throw .invalidCharacters }
74
- return username.lowercased()
74
+ ```swift
75
+ enum ParseFailure: Error { case emptyInput, badDigit(Character) }
76
+
77
+ func parseCode(_ text: String) throws(ParseFailure) -> Int {
78
+ guard !text.isEmpty else { throw .emptyInput }
79
+ var value = 0
80
+ for ch in text {
81
+ guard let d = ch.wholeNumberValue else { throw .badDigit(ch) }
82
+ value = value * 10 + d
83
+ }
84
+ return value
75
85
  }
76
86
 
77
- // Caller gets typed error -- no cast needed
78
- do {
79
- let name = try validate(username: input)
80
- } catch {
81
- // error is ValidationError, not any Error
82
- switch error {
83
- case .tooShort: print("Too short")
84
- case .invalidCharacters: print("Invalid characters")
85
- case .alreadyTaken: print("Taken")
87
+ func show(_ text: String) -> String {
88
+ do {
89
+ return String(try parseCode(text))
90
+ } catch {
91
+ switch error {
92
+ case .emptyInput: return "missing"
93
+ case .badDigit(let c): return "bad \(c)"
94
+ }
86
95
  }
87
96
  }
88
97
  ```
89
98
 
90
- **Rules:**
91
- - Use `throws(SomeError)` only when callers benefit from exhaustive error
92
- handling. For mixed error sources, use untyped `throws`.
93
- - `throws(Never)` marks a function that syntactically throws but never actually
94
- does -- useful in generic contexts.
95
- - Typed throws propagate: a function calling `throws(A)` and `throws(B)` must
96
- itself throw a type that covers both (or use untyped `throws`).
99
+ Guidance:
97
100
 
98
- ## Result Builders
101
+ - Reach for `throws(E)` when there is one clear error type and callers gain
102
+ from handling every case. Code that forwards errors from several unrelated
103
+ sources stays with plain `throws`.
104
+ - `throws(Never)` spells a function that is declared throwing but cannot
105
+ throw; it matters mostly in generic code that is parameterised over the
106
+ error type.
107
+ - Calling a `throws(A)` function and a `throws(B)` function from one body means
108
+ the outer function must throw a type that covers both, or be untyped.
99
109
 
100
- `@resultBuilder` enables DSL-style syntax. SwiftUI's `@ViewBuilder` is the most
101
- common example, but you can create custom builders for any domain.
110
+ ## Result builders
111
+
112
+ `@resultBuilder` turns a closure of plain statements into a built value.
113
+ `@ViewBuilder` is the one most people meet first.
102
114
 
103
115
  ```swift
104
116
  @resultBuilder
105
- struct ArrayBuilder<Element> {
106
- static func buildBlock(_ components: [Element]...) -> [Element] {
107
- components.flatMap { $0 }
108
- }
109
- static func buildExpression(_ expression: Element) -> [Element] { [expression] }
110
- static func buildOptional(_ component: [Element]?) -> [Element] { component ?? [] }
111
- static func buildEither(first component: [Element]) -> [Element] { component }
112
- static func buildEither(second component: [Element]) -> [Element] { component }
113
- static func buildArray(_ components: [[Element]]) -> [Element] { components.flatMap { $0 } }
117
+ enum LinesBuilder {
118
+ static func buildExpression(_ line: String) -> [String] { [line] }
119
+ static func buildBlock(_ parts: [String]...) -> [String] { parts.flatMap { $0 } }
120
+ static func buildOptional(_ part: [String]?) -> [String] { part ?? [] }
121
+ static func buildEither(first part: [String]) -> [String] { part }
122
+ static func buildEither(second part: [String]) -> [String] { part }
123
+ static func buildArray(_ parts: [[String]]) -> [String] { parts.flatMap { $0 } }
114
124
  }
115
125
 
116
- func makeItems(@ArrayBuilder<String> content: () -> [String]) -> [String] { content() }
126
+ func receipt(@LinesBuilder _ body: () -> [String]) -> String {
127
+ body().joined(separator: "\n")
128
+ }
117
129
 
118
- let items = makeItems {
119
- "Always included"
120
- if showExtra { "Conditional" }
121
- for name in names { name.uppercased() }
130
+ let items = ["tea", "scone"]
131
+ let printed = receipt {
132
+ "Corner Cafe"
133
+ for item in items { "- \(item)" }
134
+ if items.count > 1 { "multi-item order" } else { "single item" }
122
135
  }
123
136
  ```
124
137
 
125
- **Builder methods:** `buildBlock` (combine statements), `buildExpression` (single value), `buildOptional` (`if` without `else`), `buildEither` (`if/else`), `buildArray` (`for..in`), `buildFinalResult` (optional post-processing).
138
+ What each hook handles:
139
+
140
+ | Method | Called for |
141
+ |---|---|
142
+ | `buildBlock` | combining the statements of a block |
143
+ | `buildExpression` | lifting one expression into the component type |
144
+ | `buildOptional` | `if` with no `else` |
145
+ | `buildEither(first:)` / `buildEither(second:)` | the two arms of `if`/`else` (and `switch`) |
146
+ | `buildArray` | `for ... in` loops |
147
+ | `buildFinalResult` | optional last step that converts the result |
126
148
 
127
- ## Property Wrappers
149
+ More builders: [references/swift-patterns-extended.md](references/swift-patterns-extended.md#result-builders).
128
150
 
129
- Custom `@propertyWrapper` types encapsulate storage and access patterns.
151
+ ## Property wrappers
130
152
 
131
153
  ```swift
132
154
  @propertyWrapper
133
- struct Clamped<Value: Comparable> {
134
- private var value: Value
135
- let range: ClosedRange<Value>
155
+ struct Bounded<Value: Comparable> {
156
+ private var stored: Value
157
+ let limits: ClosedRange<Value>
136
158
 
137
- var wrappedValue: Value {
138
- get { value }
139
- set { value = min(max(newValue, range.lowerBound), range.upperBound) }
159
+ init(wrappedValue: Value, _ limits: ClosedRange<Value>) {
160
+ self.limits = limits
161
+ stored = min(max(wrappedValue, limits.lowerBound), limits.upperBound)
140
162
  }
141
163
 
142
- var projectedValue: ClosedRange<Value> { range }
143
-
144
- init(wrappedValue: Value, _ range: ClosedRange<Value>) {
145
- self.range = range
146
- self.value = min(max(wrappedValue, range.lowerBound), range.upperBound)
164
+ var wrappedValue: Value {
165
+ get { stored }
166
+ set { stored = min(max(newValue, limits.lowerBound), limits.upperBound) }
147
167
  }
148
- }
149
168
 
150
- // Usage
151
- struct Volume {
152
- @Clamped(0...100) var level: Int = 50
169
+ var projectedValue: ClosedRange<Value> { limits }
153
170
  }
154
171
 
155
- var v = Volume()
156
- v.level = 150 // clamped to 100
157
- print(v.$level) // projected value: 0...100
158
- ```
159
-
160
- **Design rules:**
161
- - `wrappedValue` is the primary getter/setter.
162
- - `projectedValue` (accessed via `$property`) provides metadata or bindings.
163
- - Property wrappers can be composed: `@A @B var x` applies outer wrapper first.
164
- - Do not use property wrappers when a simple computed property suffices.
165
-
166
- ## Opaque and Existential Types
167
-
168
- ### `some Protocol` (Opaque Type)
169
-
170
- The caller does not know the concrete type, but the compiler does. The
171
- underlying type is fixed for a given scope.
172
-
173
- ```swift
174
- func makeCollection() -> some Collection<Int> {
175
- [1, 2, 3] // Always returns Array<Int> -- compiler knows the concrete type
172
+ struct Thermostat {
173
+ @Bounded(10...30) var target: Double = 21
176
174
  }
177
- ```
178
175
 
179
- Use `some` for:
180
- - Return types when you want to hide implementation but preserve type identity.
181
- - Parameter types (Swift 5.7+): `some P` is shorthand for an unnamed generic
182
- parameter such as `<T: P>`.
183
-
184
- ### `any Protocol` (Existential Type)
185
-
186
- An existential box that can hold any conforming type at runtime. It uses dynamic
187
- dispatch and may allocate when the value does not fit in the inline buffer.
188
-
189
- ```swift
190
- func process(items: [any StringProtocol]) {
191
- for item in items {
192
- print(item.uppercased())
193
- }
194
- }
176
+ var unit = Thermostat()
177
+ unit.target = 45
178
+ let clamped = unit.target
179
+ let window = unit.$target
195
180
  ```
196
181
 
197
- ### When to choose
198
-
199
- | Use `some` | Use `any` |
182
+ - `wrappedValue` is the getter and setter the property exposes.
183
+ - `projectedValue` is what `$name` returns: metadata, a binding, a validity
184
+ flag.
185
+ - Wrappers stack. With `@Outer @Inner var x`, the outer one wraps the inner
186
+ one and is applied first.
187
+ - If a computed property would do the job, write the computed property. A
188
+ wrapper earns its place through reuse or a useful projection.
189
+
190
+ ## some and any
191
+
192
+ - `some Shape` is an opaque type: the compiler knows the concrete type, the
193
+ caller does not, and the type stays the same for every return from that
194
+ scope. `func evens() -> some Collection<Int> { [2, 4, 6] }` hides the array.
195
+ - In parameter position (Swift 5.7+), `some Shape` is shorthand for an
196
+ anonymous generic parameter `<T: Shape>`.
197
+ - `any Shape` is an existential box. It can hold any conforming value at
198
+ runtime, calls go through dynamic dispatch, and a value too large for the
199
+ box's inline storage is heap allocated.
200
+
201
+ | Pick `some` for | Pick `any` for |
200
202
  |---|---|
201
- | Return type hiding concrete type | Heterogeneous collections |
202
- | Function parameters (replaces simple generics) | Dynamic type erasure needed |
203
- | Better performance (static dispatch) | Protocol has `Self` or associated type requirements you need to erase |
203
+ | hiding a return type | mixed-type collections such as `[any Shape]` |
204
+ | simple generic parameters | erasing a type chosen at runtime |
205
+ | static dispatch and speed | working past `Self` or associated-type constraints |
204
206
 
205
- **Rule of thumb:** Default to `some`. Use `any` only when you need a
206
- heterogeneous collection or runtime type flexibility.
207
+ Start from `some`. Move to `any` only when values of different concrete types
208
+ really have to share one container or the type is decided at runtime.
207
209
 
208
- ## Guard Patterns
210
+ ## guard
209
211
 
210
- `guard` enforces preconditions and enables early exit. It keeps the happy path
211
- left-aligned and reduces nesting.
212
+ `guard` states a precondition and leaves early when it fails, so the main path
213
+ stays at the left margin.
212
214
 
213
215
  ```swift
214
- func processOrder(_ order: Order?) throws -> Receipt {
215
- // Unwrap optionals
216
- guard let order else { throw OrderError.missing }
217
-
218
- // Validate conditions
219
- guard order.items.isEmpty == false else { throw OrderError.empty }
220
- guard order.total > 0 else { throw OrderError.invalidTotal }
221
-
222
- // Boolean checks
223
- guard order.isPaid else { throw OrderError.unpaid }
224
-
225
- // Pattern matching
226
- guard case .confirmed(let date) = order.status else {
227
- throw OrderError.notConfirmed
216
+ enum Shipment { case pending, dispatched(on: Date), lost }
217
+ struct Parcel { var weight: Double; var status: Shipment }
218
+ enum ParcelError: Error { case none, tooHeavy, notDispatched }
219
+
220
+ func dispatchDate(_ parcel: Parcel?, express: Bool) throws -> Date {
221
+ guard let parcel else { throw ParcelError.none }
222
+ guard parcel.weight <= 30 else { throw ParcelError.tooHeavy }
223
+ guard express else { return .distantFuture }
224
+ guard case .dispatched(let date) = parcel.status else {
225
+ throw ParcelError.notDispatched
228
226
  }
229
-
230
- return Receipt(order: order, confirmedAt: date)
227
+ return date
231
228
  }
232
229
  ```
233
230
 
234
- **Best practices:**
235
- - Use `guard` for preconditions, `if` for branching logic.
236
- - Combine related guards: `guard let a, let b else { return }`.
237
- - The `else` block must exit scope: `return`, `throw`, `continue`, `break`, or
238
- `fatalError()`.
239
- - Use shorthand unwrap: `guard let value else { ... }` (Swift 5.7+).
231
+ - `guard` for preconditions, `if` for genuine branches.
232
+ - Several bindings fit one statement: `guard let host, let port else { return }`.
233
+ - The `else` body has to leave the scope: `return`, `throw`, `continue`,
234
+ `break`, or a `Never` call such as `fatalError()`.
235
+ - The shorthand `guard let value else` needs Swift 5.7 or later.
240
236
 
241
- ## Never Type
237
+ ## Never
242
238
 
243
- `Never` is an uninhabited type for code paths that never produce a value. It
244
- works as Swift's bottom type in expression contexts, but it does not implicitly
245
- conform to arbitrary protocols or satisfy a generic `T: SomeProtocol`
246
- constraint. When recommending `Result<T, Never>` or `throws(Never)`, explicitly
247
- state all three points: uninhabited, bottom-like, and no universal protocol
248
- conformance.
239
+ When `Never` comes up, say all three things, because each changes what code
240
+ compiles:
249
241
 
250
- ```swift
251
- // Function that terminates the program
252
- func crashWithDiagnostics(_ message: String) -> Never {
253
- let diagnostics = gatherDiagnostics()
254
- logger.critical("\(message): \(diagnostics)")
255
- fatalError(message)
256
- }
242
+ 1. It is uninhabited: no value of type `Never` can exist.
243
+ 2. It behaves like a bottom type in expressions: a call returning `Never` can
244
+ stand where any type is expected.
245
+ 3. It does not conform to arbitrary protocols, so it does not satisfy an
246
+ arbitrary `T: SomeProtocol` constraint on its own.
247
+
248
+ This applies whenever you recommend `Result<T, Never>` or `throws(Never)`.
257
249
 
258
- enum Result<Success, Failure: Error> {
259
- case success(Success)
260
- case failure(Failure)
250
+ ```swift
251
+ func halt(_ reason: String, context: [String: String]) -> Never {
252
+ let summary = context.map { "\($0.key)=\($0.value)" }.sorted().joined(separator: " ")
253
+ print("fatal: \(reason) \(summary)")
254
+ fatalError(reason)
261
255
  }
262
- // Result<String, Never> -- a result that can never fail
263
256
 
264
- // Exhaustive switch: no default needed since Never has no cases
265
- func handle(_ result: Result<String, Never>) {
266
- switch result {
267
- case .success(let value): print(value)
268
- // No .failure case needed -- compiler knows it's impossible
269
- }
257
+ let greeting: Result<String, Never> = .success("hello")
258
+ switch greeting {
259
+ case .success(let text): print(text)
270
260
  }
271
261
  ```
272
262
 
273
- ## Regex Builders
263
+ A function returning `Never` does not come back. A `Result` whose failure type
264
+ is `Never` cannot fail, so the `switch` needs only `.success` and no `default`.
265
+
266
+ ## Regex builders
274
267
 
275
- Swift 5.7+ Regex builder DSL provides compile-time checked, readable patterns.
268
+ `RegexBuilder` (Swift 5.7+, imported next to Foundation) writes patterns as
269
+ readable, compiler-checked Swift with typed captures.
276
270
 
277
271
  ```swift
278
272
  import Foundation
279
273
  import RegexBuilder
280
274
 
281
- // Parse "2024-03-15" into components
282
- let dateRegex = Regex {
283
- Capture { /\d{4}/ }; "-"; Capture { /\d{2}/ }; "-"; Capture { /\d{2}/ }
275
+ let clock = Regex {
276
+ Capture { /\d{2}/ }
277
+ ":"
278
+ Capture { /\d{2}/ }
284
279
  }
285
-
286
- if let match = "2024-03-15".firstMatch(of: dateRegex) {
287
- let (_, year, month, day) = match.output
288
- _ = (year, month, day)
280
+ if let hit = "Doors open 19:45".firstMatch(of: clock) {
281
+ let (_, hour, minute) = hit.output
282
+ print(hour, minute)
289
283
  }
290
284
 
291
- // TryCapture with transform
292
- let priceRegex = Regex {
293
- "$"
294
- TryCapture { OneOrMore(.digit); "."; Repeat(.digit, count: 2) }
295
- transform: { Decimal(string: String($0)) }
285
+ let price = Regex {
286
+ "EUR "
287
+ TryCapture {
288
+ OneOrMore(.digit)
289
+ "."
290
+ Repeat(.digit, count: 2)
291
+ } transform: { Decimal(string: String($0)) }
296
292
  }
297
293
  ```
298
294
 
299
- **When to use builder vs. literal:**
300
- - Builder: complex patterns, reusable components, strong typing on captures.
301
- - Literal (`/pattern/`): simple patterns, familiarity with regex syntax.
302
- - Both can be mixed: embed `/.../` literals inside builder blocks.
303
-
304
- ## Codable Best Practices
295
+ Use the builder when a pattern is long, reused, or needs typed captures. A
296
+ short one-off pattern reads better as a literal such as `/\d+/`, and literals
297
+ can be dropped into a builder where that helps. More in
298
+ [references/swift-patterns-extended.md](references/swift-patterns-extended.md#advanced-regex).
305
299
 
306
- ### Custom CodingKeys
307
-
308
- Rename keys without writing a custom decoder:
300
+ ## Codable basics
309
301
 
310
302
  ```swift
311
- struct User: Codable {
312
- let id: Int
313
- let displayName: String
314
- let avatarURL: URL
303
+ struct Venue: Codable {
304
+ var venueName: String
305
+ var seatCount: Int
306
+ var isOutdoor: Bool
307
+ var city: String
315
308
 
316
309
  enum CodingKeys: String, CodingKey {
317
- case id
318
- case displayName = "display_name"
319
- case avatarURL = "avatar_url"
310
+ case venueName = "venue_name", seatCount = "seat_count", isOutdoor = "is_outdoor", location
320
311
  }
321
- }
322
- ```
323
-
324
- ### Custom Decoding
325
-
326
- Handle mismatched types, defaults, and transformations:
327
-
328
- ```swift
329
- struct Item: Decodable {
330
- let name: String
331
- let quantity: Int
332
- let isActive: Bool
312
+ enum LocationKeys: String, CodingKey { case city }
333
313
 
334
314
  init(from decoder: Decoder) throws {
335
- let container = try decoder.container(keyedBy: CodingKeys.self)
336
- name = try container.decode(String.self, forKey: .name)
337
- quantity = try container.decodeIfPresent(Int.self, forKey: .quantity) ?? 0
338
- if let boolValue = try? container.decode(Bool.self, forKey: .isActive) {
339
- isActive = boolValue
315
+ let c = try decoder.container(keyedBy: CodingKeys.self)
316
+ venueName = try c.decode(String.self, forKey: .venueName)
317
+ seatCount = try c.decodeIfPresent(Int.self, forKey: .seatCount) ?? 0
318
+ if let flag = try? c.decode(Bool.self, forKey: .isOutdoor) {
319
+ isOutdoor = flag
340
320
  } else {
341
- isActive = (try container.decode(String.self, forKey: .isActive)).lowercased() == "true"
321
+ isOutdoor = (try c.decodeIfPresent(String.self, forKey: .isOutdoor)) == "true"
342
322
  }
343
- }
344
- enum CodingKeys: String, CodingKey { case name, quantity; case isActive = "is_active" }
345
- }
346
- ```
347
-
348
- ### Nested Containers
349
-
350
- Flatten nested JSON into a flat Swift struct:
351
-
352
- ```swift
353
- // JSON: { "id": 1, "metadata": { "created_at": "...", "tags": [...] } }
354
- struct Record: Decodable {
355
- let id: Int
356
- let createdAt: String
357
- let tags: [String]
358
-
359
- enum CodingKeys: String, CodingKey {
360
- case id, metadata
323
+ let place = try c.nestedContainer(keyedBy: LocationKeys.self, forKey: .location)
324
+ city = try place.decode(String.self, forKey: .city)
361
325
  }
362
326
 
363
- enum MetadataKeys: String, CodingKey {
364
- case createdAt = "created_at"
365
- case tags
366
- }
367
-
368
- init(from decoder: Decoder) throws {
369
- let container = try decoder.container(keyedBy: CodingKeys.self)
370
- id = try container.decode(Int.self, forKey: .id)
371
- let metadata = try container.nestedContainer(
372
- keyedBy: MetadataKeys.self, forKey: .metadata)
373
- createdAt = try metadata.decode(String.self, forKey: .createdAt)
374
- tags = try metadata.decode([String].self, forKey: .tags)
327
+ func encode(to encoder: Encoder) throws {
328
+ var c = encoder.container(keyedBy: CodingKeys.self)
329
+ try c.encode(venueName, forKey: .venueName)
330
+ try c.encode(seatCount, forKey: .seatCount)
331
+ try c.encode(isOutdoor, forKey: .isOutdoor)
332
+ var place = c.nestedContainer(keyedBy: LocationKeys.self, forKey: .location)
333
+ try place.encode(city, forKey: .city)
375
334
  }
376
335
  }
377
336
  ```
378
337
 
379
- See [references/swift-patterns-extended.md](references/swift-patterns-extended.md) for additional Codable patterns
380
- (enums with associated values, date strategies, unkeyed containers).
338
+ - A `CodingKeys: String, CodingKey` enum renames snake_case keys without a
339
+ custom decoder.
340
+ - A custom `init(from:)` covers defaults (`decodeIfPresent(...) ?? value`) and
341
+ type mismatches, here a flag that sometimes arrives as the string `"true"`.
342
+ - `nestedContainer(keyedBy:forKey:)` flattens a nested JSON object into flat
343
+ properties using a second key enum.
381
344
 
382
- ## Modern Collection APIs
345
+ Enums with associated values, date strategies and unkeyed containers are in
346
+ [references/swift-patterns-extended.md](references/swift-patterns-extended.md#codable).
347
+ Anything beyond this goes to `swift-codable`.
383
348
 
384
- Prefer these modern APIs over manual loops:
349
+ ## Collection APIs
385
350
 
386
351
  ```swift
387
- let numbers = [1, 2, 3, 4, 5, 6, 7, 8]
388
-
389
- // count(where:) -- use instead of .filter { }.count
390
- let evenCount = numbers.count(where: { $0.isMultiple(of: 2) })
391
-
392
- // contains(where:) -- short-circuits on first match
393
- let hasNegative = numbers.contains(where: { $0 < 0 })
394
-
395
- // first(where:) / last(where:)
396
- let firstEven = numbers.first(where: { $0.isMultiple(of: 2) })
397
-
398
- // String replacing() -- Swift 5.7+, returns new string
399
- let cleaned = rawText.replacing(/\s+/, with: " ")
400
- let snakeCase = name.replacing("_", with: " ")
401
-
402
- // compactMap -- unwrap optionals from a transform
403
- let ids = strings.compactMap { Int($0) }
404
-
405
- // flatMap -- flatten nested collections
406
- let allTags = articles.flatMap(\.tags)
407
-
408
- // Dictionary(grouping:by:)
409
- let byCategory = Dictionary(grouping: items, by: \.category)
410
-
411
- // reduce(into:) -- efficient accumulation
412
- let freq = words.reduce(into: [:]) { counts, word in
413
- counts[word, default: 0] += 1
414
- }
352
+ let scores = [72, 95, 40, 88]
353
+ let passed = scores.count(where: { $0 >= 50 })
354
+ let hasPerfect = scores.contains(where: { $0 == 100 })
355
+ let firstFail = scores.first(where: { $0 < 50 })
356
+ let lastHigh = scores.last(where: { $0 > 80 })
357
+
358
+ let slug = "Summer Sale 2026".replacing(" ", with: "-")
359
+ let digitsHidden = "PIN 4821".replacing(/\d/, with: "*")
360
+
361
+ struct Post { var tags: [String]; var author: String? }
362
+ let posts = [Post(tags: ["swift"], author: "ana"), Post(tags: ["ios", "swift"], author: nil)]
363
+ let authors = posts.compactMap(\.author)
364
+ let allTags = posts.flatMap(\.tags)
365
+ let byFirstTag = Dictionary(grouping: posts, by: { $0.tags.first ?? "" })
366
+ let tagCounts = allTags.reduce(into: [:]) { tally, tag in tally[tag, default: 0] += 1 }
415
367
  ```
416
368
 
417
- ## FormatStyle
369
+ - `count(where:)` replaces `filter { }.count` without building an array.
370
+ - `contains(where:)` stops at the first match.
371
+ - `String.replacing(_:with:)` (Swift 5.7+) returns a new string and takes a
372
+ string or a regex.
373
+ - `compactMap` drops `nil`; `flatMap(\.tags)` flattens nested arrays.
374
+ - `Dictionary(grouping:by:)` buckets values by a key.
375
+ - `reduce(into:)` mutates one accumulator instead of copying on every step.
418
376
 
419
- Use `.formatted()` instead of `DateFormatter`/`NumberFormatter`. It is
420
- type-safe, localized, and concise.
377
+ ## Formatting basics
421
378
 
422
- ```swift
423
- // Dates
424
- let now = Date.now
425
- now.formatted() // "3/15/2024, 2:30 PM"
426
- now.formatted(date: .abbreviated, time: .shortened) // "Mar 15, 2024, 2:30 PM"
427
- now.formatted(.dateTime.year().month().day()) // "Mar 15, 2024"
428
- now.formatted(.relative(presentation: .named)) // "yesterday"
429
-
430
- // Numbers
431
- let price = 42.5
432
- price.formatted(.currency(code: "USD")) // "$42.50"
433
- price.formatted(.percent) // "4,250%"
434
- (1_000_000).formatted(.number.notation(.compactName)) // "1M"
435
-
436
- // Measurements
437
- let distance = Measurement(value: 5, unit: UnitLength.kilometers)
438
- distance.formatted(.measurement(width: .abbreviated)) // "5 km"
439
-
440
- // Duration (Swift 5.7+)
441
- let duration = Duration.seconds(3661)
442
- duration.formatted(.time(pattern: .hourMinuteSecond)) // "1:01:01"
443
-
444
- // Byte counts
445
- Int64(1_500_000).formatted(.byteCount(style: .file)) // "1.5 MB"
446
-
447
- // Lists
448
- ["Alice", "Bob", "Carol"].formatted(.list(type: .and)) // "Alice, Bob, and Carol"
449
- ```
379
+ Prefer `.formatted()` to `DateFormatter` and `NumberFormatter`: it is typed,
380
+ localized and short.
450
381
 
451
- **Parsing:** `FormatStyle` also supports parsing:
452
382
  ```swift
453
- let value = try Decimal("$42.50", format: .currency(code: "USD"))
454
- let date = try Date("Mar 15, 2024", strategy: .dateTime.month().day().year())
383
+ import Foundation
384
+
385
+ let now = Date()
386
+ now.formatted()
387
+ now.formatted(date: .abbreviated, time: .shortened)
388
+ now.formatted(.dateTime.year().month().day())
389
+ now.addingTimeInterval(-3600).formatted(.relative(presentation: .named))
390
+
391
+ 19.99.formatted(.currency(code: "EUR"))
392
+ 0.425.formatted(.percent)
393
+ 42.5.formatted(.percent)
394
+ 2_400_000.formatted(.number.notation(.compactName))
395
+ Measurement(value: 12, unit: UnitLength.kilometers).formatted(.measurement(width: .abbreviated))
396
+ Duration.seconds(4000).formatted(.time(pattern: .hourMinuteSecond))
397
+ Int64(5_300_000).formatted(.byteCount(style: .file))
398
+ ["oat", "rye", "spelt"].formatted(.list(type: .and))
399
+
400
+ let cost = try Decimal("EUR 42.50", format: .currency(code: "EUR"))
401
+ let day = try Date("Mar 4, 2026", strategy: .dateTime.month().day().year())
455
402
  ```
456
403
 
457
- ## String Interpolation
458
-
459
- Extend `DefaultStringInterpolation` for domain-specific formatting. Use `"""` for multi-line strings (indentation is relative to the closing `"""`). See [references/swift-patterns-extended.md](references/swift-patterns-extended.md) for custom interpolation examples.
460
-
461
- ## Common Mistakes
462
-
463
- 1. **Using `any` when `some` works.** Default to `some` for return types and
464
- parameters. `any` has runtime overhead and loses type information.
465
- 2. **Manual loops instead of collection APIs.** Use `count(where:)`,
466
- `contains(where:)`, `compactMap`, `flatMap` instead of manual iteration.
467
- 3. **`DateFormatter` instead of FormatStyle.** `.formatted()` is simpler,
468
- type-safe, and handles localization automatically.
469
- 4. **Force-unwrapping Codable decodes.** Use `decodeIfPresent` with defaults
470
- for optional or missing keys.
471
- 5. **Nested if-let chains.** Use `guard let` for preconditions to keep the
472
- happy path at the top level.
473
- 6. **Invalid `@c` signatures.** Name valid C types and explicitly reject:
474
- `String`, `Array`, `UnsafeBufferPointer`, closures, generic placeholders.
475
- 7. **Ignoring typed throws.** When a function has a single, clear error type,
476
- typed throws give callers exhaustive switch without casting.
477
- 8. **Overusing property wrappers.** A computed property is simpler when there
478
- is no reuse or projected value needed.
479
- 9. **Underspecifying `Never`.** For `Result<T, Never>` or `throws(Never)`, say:
480
- uninhabited, bottom-like, and not arbitrary `T: P` protocol conformance.
481
- 10. **Owning deep formatting/localization.** Use `swift-formatstyle` for detailed
482
- formatting and `ios-localization` for market/localized-display QA.
483
-
484
- ## Review Checklist
485
-
486
- - [ ] `some` used for opaque returns and Swift 5.7+ generic-parameter shorthand
404
+ `.percent` multiplies by 100, so `42.5` prints as `4,250%`; pass `0.425` for
405
+ 42.5%. `.compactName` turns 2,400,000 into `2.4M`. `Duration.formatted` needs
406
+ Swift 5.7+. Everything past these basics, including locale behaviour and
407
+ custom styles in depth, belongs to `swift-formatstyle`.
408
+
409
+ ## String interpolation
410
+
411
+ Extending `DefaultStringInterpolation` gives domain-specific `\(...)` forms;
412
+ see [references/swift-patterns-extended.md](references/swift-patterns-extended.md#string-interpolation).
413
+ In a `"""` multi-line string, indentation is measured from the closing
414
+ delimiter, so align the closing quotes with the text you want flush left.
415
+
416
+ ## Common mistakes
417
+
418
+ 1. `any` where `some` would do: adds boxing and dynamic dispatch and throws
419
+ away type information.
420
+ 2. Hand-written loops where `count(where:)`, `contains(where:)`, `compactMap`
421
+ or `flatMap` say it directly.
422
+ 3. New `DateFormatter` code instead of format styles.
423
+ 4. Force-unwrapping decoded values; use `decodeIfPresent` with a default.
424
+ 5. Nested `if let` pyramids; use `guard let`.
425
+ 6. Accepting an invalid `@c` signature. Name the C-compatible types that are
426
+ allowed and reject `String`, `Array`, `UnsafeBufferPointer`, closures and
427
+ generic placeholders.
428
+ 7. Plain `throws` when a single error type exists and callers would switch on
429
+ it.
430
+ 8. A property wrapper with no reuse and no projection.
431
+ 9. Describing `Never` loosely; state uninhabited, bottom-like and no universal
432
+ conformance.
433
+ 10. Taking over deep formatting or localization work that belongs to
434
+ `swift-formatstyle` and `ios-localization`.
435
+
436
+ ## Review checklist
437
+
438
+ - [ ] `some` used for opaque returns and as parameter shorthand
487
439
  - [ ] `guard` for preconditions; collection APIs instead of manual loops
488
- - [ ] `.formatted()` used instead of `DateFormatter`/`NumberFormatter`
489
- - [ ] Codable types use `CodingKeys` for API mapping; `decodeIfPresent` with defaults for optional fields
490
- - [ ] if/switch expressions for conditional assignment; property wrappers have clear reuse justification
491
- - [ ] Regex builder used for complex patterns (literal OK for simple ones)
492
- - [ ] Typed throws used when callers benefit from exhaustive error handling
493
- - [ ] `@c` corrections enumerate rejected Swift-only types by name
494
- - [ ] `Never` guidance says uninhabited, bottom-like, and not arbitrary `T: P` protocol conformance
495
- - [ ] deep Codable, formatting/localization, naming, concurrency, and SwiftUI work routed to sibling skills
440
+ - [ ] `.formatted()` instead of formatter objects
441
+ - [ ] `CodingKeys` for renames; `decodeIfPresent` with defaults
442
+ - [ ] `if`/`switch` expressions for conditional assignment; wrappers justified
443
+ by reuse
444
+ - [ ] Regex builder for complex patterns, literals for simple ones
445
+ - [ ] typed throws where exhaustive handling helps callers
446
+ - [ ] `@c` corrections list the rejected Swift-only types
447
+ - [ ] `Never` guidance states all three properties
448
+ - [ ] deep Codable, formatting and localization, naming, concurrency and
449
+ SwiftUI work sent to the sibling skills
450
+
496
451
  ## References
497
452
 
498
- - Extended patterns and Codable examples: [references/swift-patterns-extended.md](references/swift-patterns-extended.md)
499
- - Attributes and C interop: [references/swift-attributes-interop.md](references/swift-attributes-interop.md)
453
+ - [references/swift-patterns-extended.md](references/swift-patterns-extended.md):
454
+ Codable edge cases, builders, wrappers, advanced Regex, custom format
455
+ styles, Swift Algorithms, complex `guard`, typed throws in protocols, custom
456
+ interpolation, advanced `Never`.
457
+ - [references/swift-attributes-interop.md](references/swift-attributes-interop.md):
458
+ `@c`, module selectors, `@specialized`, `@inline(always)`, `@export`,
459
+ `@section` and `@used`.