@mmerterden/multi-agent-pipeline 20.7.0 → 20.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +0 -10
  3. package/docs/facts.json +1 -1
  4. package/manifest.json +266 -267
  5. package/package.json +2 -2
  6. package/pipeline/scripts/_notices.mjs +1 -1
  7. package/pipeline/skills/.skill-manifest.json +68 -68
  8. package/pipeline/skills/shared/README.md +70 -70
  9. package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
  10. package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
  11. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
  12. package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
  13. package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
  14. package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
  15. package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
  16. package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
  17. package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
  18. package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
  19. package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
  20. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
  21. package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
  22. package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
  23. package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
  24. package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
  25. package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
  26. package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
  27. package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
  28. package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
  29. package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
  30. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
  31. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
  32. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
  33. package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
  34. package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
  35. package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
  36. package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
  37. package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
  38. package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
  39. package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
  40. package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
  41. package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
  42. package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
  43. package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
  44. package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
  45. package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
  46. package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
  47. package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
  48. package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
  49. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
  50. package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
  51. package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
  52. package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
  53. package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
  54. package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
  55. package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
  56. package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
  57. package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
  58. package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
  59. package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
  60. package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
  61. package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
  62. package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
  63. package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
  64. package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
  65. package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
  66. package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
  67. package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
  68. package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
  69. package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
  70. package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
  71. package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
  72. package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
  73. package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
  74. package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
  75. package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
  76. package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
  77. package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
  78. package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
  79. package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
  80. package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
  81. package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
  82. package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
  83. package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
  84. package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
  85. package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
  86. package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
  87. package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
  88. package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
  89. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
  90. package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
  91. package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
  92. package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
  93. package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
  94. package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
  95. package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
  96. package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
  97. package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
  98. package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
  99. package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
  100. package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
  101. package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
  102. package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
  103. package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
  104. package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
  105. package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
  106. package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
  107. package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
  108. package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
  109. package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
  110. package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
  111. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
  112. package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
  113. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
  114. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
  115. package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
  116. package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
  117. package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
  118. package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
  119. package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
  120. package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
  121. package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
  122. package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
  123. package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
  124. package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
  125. package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
  126. package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
  127. package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
  128. package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
  129. package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
  130. package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
  131. package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
  132. package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
  133. package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
  134. package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
  135. package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
  136. package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
  137. package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
  138. package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
  139. package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
  140. package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
  141. package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
  142. package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
  143. package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
  144. package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
  145. package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
  146. package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
  147. package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
  148. package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
  149. package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
  150. package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
  151. package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
  152. package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
  153. package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
  154. package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
  155. package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
  156. package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
  157. package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
  158. package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
  159. package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
  160. package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
  161. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
  162. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
  163. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
  164. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
  165. package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
  166. package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
  167. package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
  168. package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
  169. package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
  170. package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
  171. package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
  172. package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
  173. package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
  174. package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
  175. package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
  176. package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
  177. package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
  178. package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
  179. package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
  180. package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
  181. package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
  182. package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
  183. package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
  184. package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
  185. package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
  186. package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
  187. package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
  188. package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
  189. package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
  190. package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
  191. package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
  192. package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
  193. package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
  194. package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
  195. package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
  196. package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
  197. package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
  198. package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
  199. package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
  200. package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
  201. package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
  202. package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
  203. package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
  204. package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
  205. package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
  206. package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
  207. package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
  208. package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
  209. package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
  210. package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
  211. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
  212. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
  213. package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
  214. package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
  215. package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
  216. package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
  217. package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
  218. package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
  219. package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
  220. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
  221. package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
  222. package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
  223. package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
  224. package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
  225. package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
  226. package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
  227. package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
  228. package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
  229. package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
  230. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
  231. package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
  232. package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
  233. package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
  234. package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
  235. package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
  236. package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
  237. package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
  238. package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
  239. package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
  240. package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
  241. package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
  242. package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
  243. package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
  244. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
  245. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
  246. package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
  247. package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
  248. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
  249. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
  250. package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
  251. package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
  252. package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
  253. package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
  254. package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
  255. package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
  256. package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
  257. package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
  258. package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
  259. package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
  260. package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
  261. package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
  262. package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
  263. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
  264. package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
@@ -1,700 +1,618 @@
1
- # Platform And Sharing
1
+ # Platform and Sharing
2
2
 
3
- ## Contents
4
- - [Transferable, Drag & Drop, and ShareLink](#transferable-drag-drop-and-sharelink)
5
- - [Media Patterns](#media-patterns)
6
- - [Top Bar Overlays](#top-bar-overlays)
7
- - [Title Menus](#title-menus)
8
- - [Input Toolbar](#input-toolbar)
9
- - [Menu Bar Commands](#menu-bar-commands)
10
- - [macOS Settings](#macos-settings)
11
-
12
- ## Transferable, Drag & Drop, and ShareLink
13
-
14
- ### Intent
3
+ Moving data in and out of the app (`Transferable`, `ShareLink`, drag and drop,
4
+ the pasteboard), media previews, top bar overlays, title menus, input bars,
5
+ menu bar commands and the macOS Settings window.
15
6
 
16
- Adopt the `Transferable` protocol to enable sharing, drag and drop, copy/paste, and `ShareLink` with a unified API. Available iOS 16+.
7
+ ## Contents
17
8
 
18
- > **Docs:** [Transferable](https://sosumi.ai/documentation/coretransferable/transferable) · [Choosing a transfer representation](https://sosumi.ai/documentation/coretransferable/choosing-a-transfer-representation-for-a-model-type)
9
+ 1. [Transferable](#1-transferable)
10
+ 2. [ShareLink](#2-sharelink)
11
+ 3. [Drag and Drop](#3-drag-and-drop)
12
+ 4. [Pasteboard](#4-pasteboard)
13
+ 5. [Transferable Recipes](#5-transferable-recipes)
14
+ 6. [Transferable Pitfalls](#6-transferable-pitfalls)
15
+ 7. [Media Previews and Viewer](#7-media-previews-and-viewer)
16
+ 8. [Top Bar Overlays](#8-top-bar-overlays)
17
+ 9. [Title Menus](#9-title-menus)
18
+ 10. [Input Toolbar](#10-input-toolbar)
19
+ 11. [Menu Bar Commands](#11-menu-bar-commands)
20
+ 12. [macOS Settings](#12-macos-settings)
21
+
22
+ ## 1. Transferable
23
+
24
+ `Transferable` (iOS 16+) is one protocol behind sharing, drag and drop, copy
25
+ and paste, and `ShareLink`. Apple docs:
26
+ [Transferable](https://developer.apple.com/documentation/coretransferable/transferable),
27
+ the [representation guide](https://developer.apple.com/documentation/coretransferable/choosing-a-transfer-representation-for-a-model-type).
28
+
29
+ A type conforms by providing
30
+ `static var transferRepresentation: some TransferRepresentation`.
19
31
 
20
- ### Transferable protocol overview
32
+ ```swift
33
+ import CoreTransferable
34
+ import UniformTypeIdentifiers
21
35
 
22
- `Transferable` describes how a type converts to and from transfer representations (clipboard, drag, share sheet). Conform by implementing a static `transferRepresentation` property.
36
+ struct Recipe: Codable, Identifiable {
37
+ var id = UUID()
38
+ var name: String
39
+ var steps: String
40
+ }
23
41
 
24
- ```swift
25
- struct Note: Codable, Identifiable {
26
- let id: UUID
27
- var title: String
28
- var body: String
42
+ extension UTType {
43
+ static let recipe = UTType(exportedAs: "com.example.cookbook.recipe")
29
44
  }
30
45
 
31
- extension Note: Transferable {
46
+ extension Recipe: Transferable {
32
47
  static var transferRepresentation: some TransferRepresentation {
33
- CodableRepresentation(contentType: .note)
34
- ProxyRepresentation(exporting: \.body) // fallback: plain text
48
+ CodableRepresentation(contentType: .recipe)
49
+ ProxyRepresentation(exporting: \.steps)
35
50
  }
36
51
  }
37
-
38
- extension UTType {
39
- static let note = UTType(exportedAs: "com.example.note")
40
- }
41
52
  ```
42
53
 
43
- Representation order matters - place the most specific first, with broader fallbacks after.
54
+ Order matters. The receiver takes the first representation it understands, so
55
+ list the richest format first and broader fallbacks (plain text here) after it.
44
56
 
45
- ### Built-in conformances
57
+ ### Types that already conform
46
58
 
47
- These types already conform to `Transferable` out of the box:
48
-
49
- | Type | Content type |
50
- |------|-------------|
59
+ | Type | Content types |
60
+ |---|---|
51
61
  | `String` | `.plainText`, `.utf8PlainText` |
52
62
  | `Data` | `.data` |
53
63
  | `URL` | `.url` |
54
- | `AttributedString` | `.rtf` |
55
- | `Image` (SwiftUI) | `.image` |
56
- | `Color` (SwiftUI) | `.color` |
57
-
58
- ### TransferRepresentation types
64
+ | `AttributedString` | rich text |
65
+ | SwiftUI `Image` | `.image` |
66
+ | SwiftUI `Color` | `.color` |
59
67
 
60
- #### CodableRepresentation
68
+ ### Representation kinds
61
69
 
62
- For types conforming to `Codable`. Serializes to JSON by default:
70
+ - `CodableRepresentation(contentType:)` for `Codable` types. It encodes as
71
+ JSON unless you pass another encoder.
72
+ - `ProxyRepresentation` hands off to another `Transferable` type. Good for a
73
+ quick text or URL fallback. `ProxyRepresentation(exporting: \.name)` only
74
+ exports; `ProxyRepresentation(exporting: \.link, importing: { Bookmark(link: $0) })`
75
+ works in both directions through a URL.
76
+ - `DataRepresentation(contentType:exporting:importing:)` gives full control of
77
+ the bytes:
63
78
 
64
79
  ```swift
65
- static var transferRepresentation: some TransferRepresentation {
66
- CodableRepresentation(contentType: .myType)
67
- }
68
- ```
69
-
70
- #### ProxyRepresentation
71
-
72
- Delegate to another `Transferable` type. Ideal for quick text or URL fallbacks:
73
-
74
- ```swift
75
- ProxyRepresentation(exporting: \.title) // export only
76
- ProxyRepresentation(\.url) // import + export via URL
77
- ```
78
-
79
- #### DataRepresentation
80
-
81
- Full control over binary serialization:
82
-
83
- ```swift
84
- DataRepresentation(contentType: .png) { image in
85
- try image.pngData()
86
- } importing: { data in
87
- try MyImage(data: data)
80
+ extension Sticker: Transferable {
81
+ static var transferRepresentation: some TransferRepresentation {
82
+ DataRepresentation(contentType: .png) { sticker in
83
+ try sticker.encodedPNG()
84
+ } importing: { data in
85
+ try Sticker(pngData: data)
86
+ }
87
+ }
88
88
  }
89
89
  ```
90
90
 
91
- Use `DataRepresentation(exportedContentType:)` for export-only representations.
92
-
93
- #### FileRepresentation
94
-
95
- For large content best transferred as files:
91
+ - `DataRepresentation(exportedContentType:exporting:)` is the export-only
92
+ version.
93
+ - `FileRepresentation(contentType:exporting:importing:)` moves large content as
94
+ files. The received file is temporary, so copy it before using it:
96
95
 
97
96
  ```swift
98
- FileRepresentation(contentType: .movie) { video in
99
- SentTransferredFile(video.fileURL)
100
- } importing: { receivedFile in
101
- let dest = FileManager.default.temporaryDirectory.appendingPathComponent(receivedFile.file.lastPathComponent)
102
- try FileManager.default.copyItem(at: receivedFile.file, to: dest)
103
- return Video(url: dest)
97
+ extension Recording: Transferable {
98
+ static var transferRepresentation: some TransferRepresentation {
99
+ FileRepresentation(contentType: .mpeg4Audio) { recording in
100
+ SentTransferredFile(recording.fileURL)
101
+ } importing: { received in
102
+ let target = FileManager.default.temporaryDirectory
103
+ .appending(path: received.file.lastPathComponent)
104
+ let files = FileManager.default
105
+ try? files.removeItem(at: target)
106
+ try files.copyItem(at: received.file, to: target)
107
+ return Recording(fileURL: target)
108
+ }
109
+ }
104
110
  }
105
111
  ```
106
112
 
107
- ### ShareLink
113
+ ## 2. ShareLink
108
114
 
109
- Present the system share sheet with a `Transferable` item:
115
+ `ShareLink` presents the system share sheet. Its item must be `Transferable`.
116
+ `SharePreview` supplies a title and, optionally, an image and an icon.
110
117
 
111
118
  ```swift
112
- ShareLink(item: note, preview: SharePreview(note.title)) {
113
- Label("Share", systemImage: "square.and.arrow.up")
119
+ ShareLink(item: recipe, preview: SharePreview(recipe.name)) {
120
+ Label("Share recipe", systemImage: "square.and.arrow.up")
114
121
  }
115
122
 
116
- // Multiple items
117
- ShareLink(items: selectedNotes) { note in
118
- SharePreview(note.title)
123
+ ShareLink(items: selectedRecipes) { recipe in
124
+ SharePreview(recipe.name)
119
125
  }
120
126
 
121
- // Simple string sharing
122
- ShareLink(item: "Check out this app!", subject: Text("Cool App"))
127
+ ShareLink(item: "Dinner at 8", subject: Text("Tonight"))
123
128
  ```
124
129
 
125
- `ShareLink` requires the item to conform to `Transferable`. The preview provides a title, optional image, and optional icon for the share sheet.
126
-
127
- ### Drag and drop
130
+ ## 3. Drag and Drop
128
131
 
129
- #### Making views draggable
132
+ - `.draggable(value)` makes a view a drag source; the value must be
133
+ `Transferable`.
134
+ - `.draggable(value) { preview }` supplies a custom drag preview.
130
135
 
131
136
  ```swift
132
- struct NoteCard: View {
133
- let note: Note
134
-
135
- var body: some View {
136
- Text(note.title)
137
- .draggable(note) // Note must be Transferable
138
- }
139
- }
140
- ```
141
-
142
- Use `.draggable(note) { DragPreview(note) }` to provide a custom drag preview.
143
-
144
- #### Drop destination
145
-
146
- ```swift
147
- struct NoteBoard: View {
148
- @State private var notes: [Note] = []
137
+ struct RecipeBoard: View {
138
+ @State private var pinned: [Recipe] = []
139
+ @State private var isHovering = false
149
140
 
150
141
  var body: some View {
151
142
  VStack {
152
- ForEach(notes) { NoteCard(note: $0) }
143
+ ForEach(pinned) { Text($0.name) }
153
144
  }
154
- .dropDestination(for: Note.self) { droppedNotes, location in
155
- notes.append(contentsOf: droppedNotes)
145
+ .frame(maxWidth: .infinity, minHeight: 200)
146
+ .background(isHovering ? Color.accentColor.opacity(0.15) : Color.clear)
147
+ .dropDestination(for: Recipe.self) { recipes, _ in
148
+ pinned.append(contentsOf: recipes)
156
149
  return true
157
- } isTargeted: { isOver in
158
- // Highlight drop zone
150
+ } isTargeted: { hovering in
151
+ isHovering = hovering
159
152
  }
160
153
  }
161
154
  }
162
155
  ```
163
156
 
164
- For reordering within a list, combine `.draggable` with `.dropDestination` or use `onMove` on `ForEach` inside `List`.
165
-
166
- #### Handling multiple types
167
-
168
- Accept multiple content types with separate `.dropDestination` modifiers or use `DropDelegate` for advanced logic:
157
+ - To reorder rows, either pair `.draggable` and `.dropDestination` yourself,
158
+ or let a `List` do it through `onMove` on its `ForEach`.
159
+ - Several accepted types: add one `.dropDestination` per type, or use a
160
+ `DropDelegate` for more complex rules.
169
161
 
170
162
  ```swift
171
- .dropDestination(for: String.self) { strings, _ in
172
- notes.append(contentsOf: strings.map { Note(id: UUID(), title: $0, body: "") })
163
+ .dropDestination(for: String.self) { texts, _ in
164
+ pinned.append(contentsOf: texts.map { Recipe(name: $0, steps: "") })
173
165
  return true
174
166
  }
175
167
  ```
176
168
 
177
- ### Pasteboard integration
169
+ ## 4. Pasteboard
178
170
 
179
- For direct clipboard access outside SwiftUI's drag/drop system, use `UIPasteboard`:
171
+ Outside drag and drop, iOS code can use `UIPasteboard` directly:
180
172
 
181
173
  ```swift
182
- // Copy
183
- UIPasteboard.general.string = note.title
184
-
185
- // Paste
186
- if let text = UIPasteboard.general.string {
187
- // use text
188
- }
174
+ UIPasteboard.general.string = recipe.steps
175
+ let pasted: String? = UIPasteboard.general.string
189
176
  ```
190
177
 
191
- For `Transferable` types with custom content types, export to `Data` first:
178
+ For a custom `Transferable` type, export the data first:
192
179
 
193
180
  ```swift
194
- let data = try await note.exported(as: .note)
195
- UIPasteboard.general.setData(data, forPasteboardType: UTType.note.identifier)
181
+ let data = try await recipe.exported(as: .recipe)
182
+ let board = UIPasteboard.general
183
+ board.setData(data, forPasteboardType: UTType.recipe.identifier)
196
184
  ```
197
185
 
198
- Prefer SwiftUI's `.copyable`, `.cuttable`, and `.pasteDestination` modifiers (iOS 16+) over direct `UIPasteboard` usage when possible - they integrate with the Edit menu and keyboard shortcuts automatically.
186
+ On iOS, `PasteButton(payloadType:onPaste:)` (iOS 16+) pastes without the
187
+ system permission prompt. On macOS, the SwiftUI modifiers `.copyable(_:)`,
188
+ `.cuttable(for:action:)` and `.pasteDestination(for:action:validator:)`
189
+ (macOS 13+) connect to the Edit menu and its keyboard shortcuts; prefer them
190
+ there over `NSPasteboard`. These three modifiers are not available on iOS.
199
191
 
200
- ### Common patterns
192
+ ## 5. Transferable Recipes
201
193
 
202
- #### Transferable enum with multiple representations
194
+ One enum, one plain-text representation:
203
195
 
204
196
  ```swift
205
- enum SharedContent: Transferable {
206
- case text(String)
207
- case url(URL)
197
+ enum Clip: Transferable {
198
+ case note(String)
199
+ case link(URL)
208
200
 
209
201
  static var transferRepresentation: some TransferRepresentation {
210
- ProxyRepresentation { content in
211
- switch content {
212
- case .text(let s): return s
213
- case .url(let u): return u.absoluteString
202
+ ProxyRepresentation { clip in
203
+ switch clip {
204
+ case .note(let text): text
205
+ case .link(let url): url.absoluteString
214
206
  }
215
207
  }
216
208
  }
217
209
  }
218
210
  ```
219
211
 
220
- #### Export-only conformance
221
-
222
- When your type should be sharable but not importable:
212
+ Export only, as a PDF:
223
213
 
224
214
  ```swift
225
- extension Report: Transferable {
215
+ extension Statement: Transferable {
226
216
  static var transferRepresentation: some TransferRepresentation {
227
- DataRepresentation(exportedContentType: .pdf) { report in
228
- try report.renderPDF()
217
+ DataRepresentation(exportedContentType: .pdf) { statement in
218
+ try await statement.renderPDF()
229
219
  }
230
220
  }
231
221
  }
232
222
  ```
233
223
 
234
- ### Pitfalls
235
-
236
- - Always declare custom `UTType` identifiers in Info.plist under Exported/Imported Type Identifiers.
237
- - Representation order matters - the first matching representation wins. Put the richest format first.
238
- - `FileRepresentation` files are temporary; copy them if you need to persist.
239
- - `Transferable` conformance must be on the main type, not an extension in a different module, to avoid linker issues.
240
- - Test drag and drop on device - Simulator haptics and drop targeting differ from hardware.
241
-
242
- ## Media Patterns
224
+ ## 6. Transferable Pitfalls
243
225
 
244
- ### Intent
226
+ - Every custom `UTType` needs an Info.plist entry: Exported Type Identifiers
227
+ for types the app defines, Imported Type Identifiers for types it only
228
+ reads.
229
+ - Files delivered through `FileRepresentation` are temporary. Copy them to keep
230
+ them.
231
+ - Declare the conformance in the module that defines the type. A conformance
232
+ added from another module is retroactive and can clash with one the owner
233
+ adds later.
234
+ - Test drag and drop on a device. The Simulator does not match hardware for
235
+ haptics and drop targeting.
245
236
 
246
- Use consistent patterns for loading images, previewing media, and presenting a full-screen viewer.
237
+ ## 7. Media Previews and Viewer
247
238
 
248
- ### Core patterns
239
+ Goal: one consistent way to load images, show inline previews and open a
240
+ full-screen viewer.
249
241
 
250
- - Use `AsyncImage` for simple remote images. `LazyImage` is from the third-party Nuke library if you need advanced caching and prefetching.
251
- - Prefer a lightweight preview component for inline media.
252
- - Use a shared viewer state (e.g., `QuickLook`) to present a full-screen media viewer.
253
- - Use `openWindow` for desktop/visionOS and a sheet for iOS.
254
-
255
- ### Example: inline media preview
242
+ - `AsyncImage` covers simple remote images. For caching and prefetching, a
243
+ library such as Nuke provides `LazyImage`.
244
+ - Inline media uses a light preview component.
245
+ - The full-screen viewer is driven by shared viewer state, for example a
246
+ `MediaViewer` object in the environment.
247
+ - On macOS and visionOS open the viewer with `openWindow`; on iOS use a sheet.
256
248
 
257
249
  ```swift
258
- struct MediaPreviewRow: View {
259
- @Environment(QuickLook.self) private var quickLook
260
-
261
- let attachments: [MediaAttachment]
262
-
263
- var body: some View {
264
- ScrollView(.horizontal, showsIndicators: false) {
265
- HStack {
266
- ForEach(attachments) { attachment in
267
- Button {
268
- quickLook.prepareFor(
269
- selectedMediaAttachment: attachment,
270
- mediaAttachments: attachments
271
- )
272
- } label: {
273
- LazyImage(url: attachment.previewURL) { state in
274
- if let image = state.image {
275
- image.resizable().aspectRatio(contentMode: .fill)
276
- } else {
277
- ProgressView()
278
- }
250
+ struct AttachmentStrip: View {
251
+ @Environment(MediaViewer.self) private var viewer
252
+ let attachments: [Attachment]
253
+
254
+ var body: some View {
255
+ ScrollView(.horizontal, showsIndicators: false) {
256
+ HStack {
257
+ ForEach(attachments) { item in
258
+ Button {
259
+ viewer.open(item, among: attachments)
260
+ } label: {
261
+ AsyncImage(url: item.thumbnailURL) { image in
262
+ image.resizable().aspectRatio(contentMode: .fill)
263
+ } placeholder: {
264
+ ProgressView()
265
+ }
266
+ .frame(width: 120, height: 120)
267
+ .clipped()
268
+ }
269
+ .buttonStyle(.plain)
270
+ }
279
271
  }
280
- .frame(width: 120, height: 120)
281
- .clipped()
282
- }
283
- .buttonStyle(.plain)
284
272
  }
285
- }
286
273
  }
287
- }
288
274
  }
289
- ```
290
275
 
291
- ### Example: global media viewer sheet
292
-
293
- ```swift
294
- struct AppRoot: View {
295
- @State private var quickLook = QuickLook.shared
296
-
297
- var body: some View {
298
- content
299
- .environment(quickLook)
300
- .sheet(item: $quickLook.selectedMediaAttachment) { selected in
301
- MediaUIView(selectedAttachment: selected, attachments: quickLook.mediaAttachments)
302
- }
303
- }
276
+ @main
277
+ struct AlbumApp: App {
278
+ @State private var viewer = MediaViewer.shared
279
+
280
+ var body: some Scene {
281
+ WindowGroup {
282
+ LibraryView()
283
+ .environment(viewer)
284
+ .sheet(item: Bindable(viewer).current) { item in
285
+ FullScreenMedia(item: item)
286
+ }
287
+ }
288
+ }
304
289
  }
305
290
  ```
306
291
 
307
- ### Design choices to keep
308
-
309
- - Keep previews lightweight; load full media in the viewer.
310
- - Use shared viewer state so any view can open media without prop-drilling.
311
- - Use a single entry point for the viewer (sheet/window) to avoid duplicates.
312
-
313
- ### Pitfalls
314
-
315
- - Avoid loading full-size images in list rows; use resized previews.
316
- - Don't present multiple viewer sheets at once; keep a single source of truth.
292
+ Guidelines:
317
293
 
318
- ## Top Bar Overlays
294
+ - Keep previews light; load full-resolution media only inside the viewer.
295
+ - Shared viewer state lets any view open media without passing it down
296
+ through every layer.
297
+ - One entry point (a sheet or a window) avoids duplicate viewers.
319
298
 
320
- ### Intent
299
+ Pitfalls:
321
300
 
322
- Provide a custom top selector or pill row that sits above scroll content, using `safeAreaBar(.top)` on iOS 26 and a compatible fallback on earlier OS versions.
301
+ - Rows that decode original-resolution images. Downscale for the preview.
302
+ - Two viewer sheets open together because two views each own one. One state
303
+ object, one presenter.
323
304
 
324
- ### iOS 26+ approach
305
+ ## 8. Top Bar Overlays
325
306
 
326
- Use `safeAreaBar(edge: .top)` to attach the view to the safe area bar.
307
+ Goal: a custom selector or pill row above scrolling content. On iOS 26 use
308
+ `safeAreaBar`; earlier releases need a fallback.
327
309
 
328
310
  ```swift
329
- if #available(iOS 26.0, *) {
330
- content
331
- .safeAreaBar(edge: .top) {
332
- TopSelectorView()
333
- .padding(.horizontal, .layoutPadding)
311
+ struct FeedScreen: View {
312
+ @State private var section: FeedSection = .following
313
+
314
+ var body: some View {
315
+ feedList
316
+ .modifier(TopSelector(section: $section))
334
317
  }
335
318
  }
336
- ```
337
-
338
- ### Fallback for earlier iOS
339
319
 
340
- Use `.safeAreaInset(edge: .top)` and hide the toolbar background to avoid double layers.
320
+ struct TopSelector: ViewModifier {
321
+ @Binding var section: FeedSection
341
322
 
342
- ```swift
343
- content
344
- .toolbarBackground(.hidden, for: .navigationBar)
345
- .safeAreaInset(edge: .top, spacing: 0) {
346
- VStack(spacing: 0) {
347
- TopSelectorView()
348
- .padding(.vertical)
349
- .padding(.horizontal, .layoutPadding)
350
- .background(Color.primary.opacity(0.06))
351
- .background(Material.ultraThin)
352
- Divider()
323
+ func body(content: Self.Content) -> some View {
324
+ if #available(iOS 26.0, *) {
325
+ content.safeAreaBar(edge: .top) {
326
+ SectionPicker(section: $section)
327
+ .padding(.horizontal, Spacing.medium)
328
+ }
329
+ } else {
330
+ content
331
+ .toolbarBackground(.hidden, for: .navigationBar)
332
+ .safeAreaInset(edge: .top, spacing: 0) {
333
+ VStack(spacing: 0) {
334
+ SectionPicker(section: $section)
335
+ .padding(.vertical, 8)
336
+ .background(Color.primary.opacity(0.05))
337
+ .background(Material.ultraThin)
338
+ Divider()
339
+ }
340
+ }
341
+ }
353
342
  }
354
- }
343
+ }
355
344
  ```
356
345
 
357
- ### Design choices to keep
358
-
359
- - Use `safeAreaBar` when available; it integrates better with the navigation bar.
360
- - Use a subtle background + divider in the fallback to keep separation from content.
361
- - Keep the selector height compact to avoid pushing content too far down.
346
+ Hiding the toolbar background in the fallback prevents two stacked
347
+ backgrounds.
362
348
 
363
- ### Pitfalls
349
+ Guidelines:
364
350
 
365
- - Don't stack multiple top insets; it can create extra padding.
366
- - Avoid heavy, opaque backgrounds that fight the navigation bar.
351
+ - Prefer `safeAreaBar` where available; it blends with the navigation bar.
352
+ - The fallback separates itself from content with a faint background and a
353
+ divider.
354
+ - Keep the selector short so content does not move far down.
367
355
 
368
- ## Title Menus
356
+ Pitfalls:
369
357
 
370
- ### Intent
358
+ - Several top insets stacked on each other add extra padding.
359
+ - Heavy, opaque backgrounds that clash with the navigation bar.
371
360
 
372
- Use a title menu in the navigation bar to provide context‑specific filtering or quick actions without adding extra chrome.
361
+ ## 9. Title Menus
373
362
 
374
- ### Core patterns
363
+ Goal: a menu on the navigation title for filtering or quick context actions,
364
+ with no extra chrome.
375
365
 
376
- - Use `ToolbarTitleMenu` to attach a menu to the navigation title.
377
- - Keep the menu content compact and grouped with dividers.
378
-
379
- ### Example: title menu for filters
366
+ - `ToolbarTitleMenu` (iOS 16+) attaches a menu to the title.
367
+ - Keep its content short and group it with `Divider()`.
380
368
 
381
369
  ```swift
382
- @ToolbarContentBuilder
383
- private var toolbarView: some ToolbarContent {
384
- ToolbarTitleMenu {
385
- Button("Latest") { timeline = .latest }
386
- Button("Resume") { timeline = .resume }
387
- Divider()
388
- Button("Local") { timeline = .local }
389
- Button("Federated") { timeline = .federated }
390
- }
391
- }
392
- ```
393
-
394
- ### Example: attach to a view
370
+ struct TasksScreen: View {
371
+ @State private var filter: TaskFilter = .open
395
372
 
396
- ```swift
397
- NavigationStack {
398
- TimelineView()
399
- .toolbar {
400
- toolbarView
373
+ var body: some View {
374
+ NavigationStack {
375
+ TaskList(filter: filter)
376
+ .navigationTitle(filter.title)
377
+ .toolbar { titleMenu }
378
+ }
401
379
  }
402
- }
403
- ```
404
-
405
- ### Example: title + menu together
406
380
 
407
- ```swift
408
- struct TimelineScreen: View {
409
- @State private var timeline: TimelineFilter = .home
410
-
411
- var body: some View {
412
- NavigationStack {
413
- TimelineView()
414
- .toolbar {
415
- ToolbarItem(placement: .principal) {
416
- VStack(spacing: 2) {
417
- Text(timeline.title)
418
- .font(.headline)
419
- Text(timeline.subtitle)
420
- .font(.caption)
421
- .foregroundStyle(.secondary)
422
- }
423
- }
424
-
425
- ToolbarTitleMenu {
426
- Button("Home") { timeline = .home }
427
- Button("Local") { timeline = .local }
428
- Button("Federated") { timeline = .federated }
429
- }
381
+ @ToolbarContentBuilder
382
+ private var titleMenu: some ToolbarContent {
383
+ ToolbarTitleMenu {
384
+ Button("Open") { filter = .open }
385
+ Button("Done") { filter = .done }
386
+ Divider()
387
+ Button("Everything") { filter = .all }
430
388
  }
431
- .navigationBarTitleDisplayMode(.inline)
432
389
  }
433
- }
434
390
  }
435
391
  ```
436
392
 
437
- ### Example: title + subtitle with menu
393
+ A title with a subtitle under it:
438
394
 
439
395
  ```swift
440
- ToolbarItem(placement: .principal) {
441
- VStack(spacing: 2) {
442
- Text(title)
443
- .font(.headline)
444
- Text(subtitle)
445
- .font(.caption)
446
- .foregroundStyle(.secondary)
447
- }
396
+ .toolbar {
397
+ ToolbarItem(placement: .principal) {
398
+ VStack(spacing: 2) {
399
+ Text(project.name).font(.headline)
400
+ Text("\(project.openCount) open").font(.caption).foregroundStyle(.secondary)
401
+ }
402
+ }
403
+ titleMenu
448
404
  }
405
+ .navigationBarTitleDisplayMode(.inline)
449
406
  ```
450
407
 
451
- ### Design choices to keep
452
-
453
- - Only show the title menu when filtering or context switching is available.
454
- - Keep the title readable; avoid long labels that truncate.
455
- - Use secondary text below the title if extra context is needed.
408
+ Guidelines:
456
409
 
457
- ### Pitfalls
410
+ - Show the title menu only when there is something to filter or switch.
411
+ - Keep the title short enough that it is not truncated.
412
+ - Put extra context in the secondary line under the title.
458
413
 
459
- - Don't overload the menu with too many options.
460
- - Avoid using title menus for destructive actions.
414
+ Pitfalls:
461
415
 
462
- ## Input Toolbar
416
+ - Too many options in the menu.
417
+ - Destructive actions in a title menu.
463
418
 
464
- ### Intent
419
+ ## 10. Input Toolbar
465
420
 
466
- Use a bottom-anchored input bar for chat, composer, or quick actions without fighting the keyboard.
421
+ Goal: an input bar pinned to the bottom (chat, composer, quick actions) that
422
+ moves with the keyboard.
467
423
 
468
- ### Core patterns
469
-
470
- - Use `.safeAreaInset(edge: .bottom)` to anchor the toolbar above the keyboard.
471
- - Keep the main content in a `ScrollView` or `List`.
472
- - Drive focus with `@FocusState` and set initial focus when needed.
473
- - Avoid embedding the input bar inside the scroll content; keep it separate.
474
-
475
- ### Example: scroll view + bottom input
424
+ - Anchor it with `.safeAreaInset(edge: .bottom)` so it sits above the keyboard.
425
+ - The messages or items scroll in a `ScrollView` or `List`.
426
+ - `@FocusState` decides when the field is active; focusing it on appear is
427
+ often right for a composer.
428
+ - Keep the bar out of the scrolling content.
476
429
 
477
430
  ```swift
478
431
  @MainActor
479
- struct ConversationView: View {
480
- @FocusState private var isInputFocused: Bool
481
- @State private var scrollPosition = ScrollPosition(edge: .bottom)
482
- @State private var draft = ""
483
-
484
- var body: some View {
485
- ScrollView {
486
- LazyVStack {
487
- ForEach(messages) { message in
488
- MessageRow(message: message)
432
+ struct ChatThread: View {
433
+ @State private var draft = ""
434
+ @State private var position = ScrollPosition(edge: .bottom)
435
+ @FocusState private var isComposing: Bool
436
+ let messages: [Message]
437
+ let onSend: (String) -> Void
438
+
439
+ var body: some View {
440
+ ScrollView {
441
+ LazyVStack {
442
+ ForEach(messages) { MessageBubble(message: $0) }
443
+ }
444
+ .scrollTargetLayout()
445
+ }
446
+ .scrollPosition($position)
447
+ .scrollDismissesKeyboard(.interactively)
448
+ .safeAreaInset(edge: .bottom) {
449
+ HStack {
450
+ TextField("Message", text: $draft)
451
+ .focused($isComposing)
452
+ .onSubmit(send)
453
+ Button("Send", systemImage: "arrow.up.circle.fill", action: send)
454
+ }
455
+ .padding()
456
+ .background(.bar)
489
457
  }
490
- }
491
- .scrollTargetLayout()
492
- .padding(.horizontal, .layoutPadding)
458
+ .onAppear { isComposing = true }
493
459
  }
494
- .scrollPosition($scrollPosition)
495
- .safeAreaInset(edge: .bottom) {
496
- InputBar(text: $draft)
497
- .focused($isInputFocused)
460
+
461
+ private func send() {
462
+ onSend(draft)
463
+ draft = ""
498
464
  }
499
- .scrollDismissesKeyboard(.interactively)
500
- .onAppear { isInputFocused = true }
501
- }
502
465
  }
503
466
  ```
504
467
 
505
- ### Design choices to keep
506
-
507
- - Keep the input bar visually separated from the scrollable content.
508
- - Use `.scrollDismissesKeyboard(.interactively)` for chat-like screens.
509
- - Ensure send actions are reachable via keyboard return or a clear button.
510
-
511
- ### Pitfalls
512
-
513
- - Avoid placing the input view inside the scroll stack; it will jump with content.
514
- - Avoid nested scroll views that fight for drag gestures.
515
-
516
- ## Menu Bar Commands
468
+ `ScrollPosition` and `scrollPosition(_:)` with it need iOS 18.
517
469
 
518
- ### Contents
470
+ Guidelines:
519
471
 
520
- - [Intent](#intent)
521
- - [Core patterns](#core-patterns)
522
- - [Example: basic command menu](#example-basic-command-menu)
523
- - [Example: insert and replace groups](#example-insert-and-replace-groups)
524
- - [Example: focused menu state](#example-focused-menu-state)
525
- - [Menu bar and Settings](#menu-bar-and-settings)
526
- - [Pitfalls](#pitfalls)
472
+ - Keep the bar visually distinct from the scrolling content.
473
+ - Chat-style screens use `.scrollDismissesKeyboard(.interactively)`.
474
+ - Sending must work from the return key and from a clear button.
527
475
 
528
- ### Intent
476
+ Pitfalls:
529
477
 
530
- Use this when adding or customizing the macOS/iPadOS menu bar with SwiftUI commands.
478
+ - An input field placed inside the scroll stack moves with the content.
479
+ - Nested scroll views fighting over the drag gesture.
531
480
 
532
- ### Core patterns
481
+ ## 11. Menu Bar Commands
533
482
 
534
- - Add commands at the `Scene` level with `.commands { ... }`.
535
- - Use `SidebarCommands()` when your UI includes a navigation sidebar.
536
- - Use `CommandMenu` for app-specific menus and group related actions.
537
- - Use `CommandGroup` to insert items before/after system groups or replace them.
538
- - Use `FocusedValue` for context-sensitive menu items that depend on the active scene.
483
+ Applies when adding to or customising the menu bar on macOS and iPadOS with
484
+ SwiftUI commands.
539
485
 
540
- ### Example: basic command menu
541
-
542
- ```swift
543
- @main
544
- struct MyApp: App {
545
- var body: some Scene {
546
- WindowGroup {
547
- ContentView()
548
- }
549
- .commands {
550
- CommandMenu("Actions") {
551
- Button("Run", action: run)
552
- .keyboardShortcut("R")
553
- Button("Stop", action: stop)
554
- .keyboardShortcut(".")
555
- }
556
- }
557
- }
558
-
559
- private func run() {}
560
- private func stop() {}
561
- }
562
- ```
563
-
564
- ### Example: insert and replace groups
486
+ - Attach commands to a `Scene` with `.commands { }`.
487
+ - Add `SidebarCommands()` when the UI has a navigation sidebar.
488
+ - `CommandMenu` creates an app-specific menu of related actions.
489
+ - `CommandGroup` inserts items before or after a system group, or replaces it.
490
+ - `FocusedValue` makes items depend on the active scene.
565
491
 
566
492
  ```swift
567
493
  WindowGroup {
568
- ContentView()
494
+ ContentView()
569
495
  }
570
496
  .commands {
571
- CommandGroup(before: .systemServices) {
572
- Button("Check for Updates") { /* open updater */ }
573
- }
574
-
575
- CommandGroup(after: .newItem) {
576
- Button("New from Clipboard") { /* create item */ }
577
- }
578
-
579
- CommandGroup(replacing: .help) {
580
- Button("User Manual") { /* open docs */ }
581
- }
497
+ SidebarCommands()
498
+ CommandMenu("Library") {
499
+ Button("Rescan", action: rescan).keyboardShortcut("R")
500
+ Button("Stop Scan", action: stopScan).keyboardShortcut(".")
501
+ }
502
+ CommandGroup(before: .systemServices) {
503
+ Button("Diagnostics", action: showDiagnostics)
504
+ }
505
+ CommandGroup(after: .newItem) {
506
+ Button("New Playlist", action: newPlaylist)
507
+ }
508
+ CommandGroup(replacing: .help) {
509
+ Button("Library Guide", action: openGuide)
510
+ }
582
511
  }
583
512
  ```
584
513
 
585
- ### Example: focused menu state
514
+ Context-sensitive commands read a focused value that the active scene
515
+ publishes:
586
516
 
587
517
  ```swift
588
- @Observable
589
- final class DataModel {
590
- var items: [String] = []
518
+ @MainActor @Observable
519
+ final class LibraryModel {
520
+ func addPlaylist() { }
591
521
  }
592
522
 
593
- struct ContentView: View {
594
- @State private var model = DataModel()
523
+ struct LibraryWindow: View {
524
+ @State private var model = LibraryModel()
595
525
 
596
- var body: some View {
597
- List(model.items, id: \.self) { item in
598
- Text(item)
526
+ var body: some View {
527
+ LibraryView(model: model)
528
+ .focusedSceneValue(model)
599
529
  }
600
- .focusedSceneValue(model)
601
- }
602
530
  }
603
531
 
604
- struct ItemCommands: Commands {
605
- @FocusedValue(DataModel.self) private var model: DataModel?
532
+ struct LibraryCommands: Commands {
533
+ @FocusedValue(LibraryModel.self) private var model: LibraryModel?
606
534
 
607
- var body: some Commands {
608
- CommandGroup(after: .newItem) {
609
- Button("New Item") {
610
- model?.items.append("Untitled")
611
- }
612
- .disabled(model == nil)
535
+ var body: some Commands {
536
+ CommandGroup(after: .newItem) {
537
+ Button("Add Playlist") { model?.addPlaylist() }
538
+ .disabled(model == nil)
539
+ }
613
540
  }
614
- }
615
541
  }
616
542
  ```
617
543
 
618
- ### Menu bar and Settings
619
-
620
- - Defining a `Settings` scene adds the Settings menu item on macOS automatically.
621
- - If you need a custom entry point inside the app, use `OpenSettingsAction` or `SettingsLink`.
544
+ On macOS, the app menu gains its Settings item as soon as the `App` declares a
545
+ `Settings` scene. To open settings from inside the app, use `SettingsLink` or the
546
+ `openSettings` environment action (`OpenSettingsAction`).
622
547
 
623
- ### Pitfalls
548
+ Pitfalls:
624
549
 
625
- - Avoid registering the same keyboard shortcut in multiple command groups.
626
- - Don't use menu items as the only discoverable entry point for critical features.
550
+ - The same shortcut assigned in several command groups.
551
+ - A critical feature reachable only through a menu item.
627
552
 
628
- ## macOS Settings
553
+ ## 12. macOS Settings
629
554
 
630
- ### Intent
555
+ Applies when building the macOS Settings window with the SwiftUI `Settings`
556
+ scene.
631
557
 
632
- Use this when building a macOS Settings window backed by SwiftUI's `Settings` scene.
633
-
634
- ### Core patterns
635
-
636
- - Declare the Settings scene in the `App` and compile it only for macOS.
637
- - Keep settings content in a dedicated root view (`SettingsView`) and drive values with `@AppStorage`.
638
- - Use `TabView` to group settings sections when you have more than one category.
639
- - Use `Form` inside each tab to keep controls aligned and accessible.
640
- - Use `OpenSettingsAction` or `SettingsLink` for in-app entry points to the Settings window.
641
-
642
- ### Example: settings scene
558
+ - Declare `Settings { PreferencesView() }` in the `App`, wrapped in
559
+ `#if os(macOS)` so it compiles only for macOS.
560
+ - Give settings their own root view and back values with `@AppStorage`.
561
+ - More than one category: group them with a `TabView`.
562
+ - Use a `Form` inside each tab for aligned, accessible controls.
563
+ - Open settings from the app with `SettingsLink` or `OpenSettingsAction`.
643
564
 
644
565
  ```swift
645
566
  @main
646
- struct MyApp: App {
647
- var body: some Scene {
648
- WindowGroup {
649
- ContentView()
650
- }
651
- #if os(macOS)
652
- Settings {
653
- SettingsView()
567
+ struct ReaderApp: App {
568
+ var body: some Scene {
569
+ WindowGroup { LibraryView() }
570
+ #if os(macOS)
571
+ Settings { PreferencesView() }
572
+ #endif
654
573
  }
655
- #endif
656
- }
657
574
  }
658
- ```
659
-
660
- ### Example: tabbed settings view
661
575
 
662
- ```swift
663
576
  @MainActor
664
- struct SettingsView: View {
665
- @AppStorage("showPreviews") private var showPreviews = true
666
- @AppStorage("fontSize") private var fontSize = 12.0
667
-
668
- var body: some View {
669
- TabView {
670
- Tab("General", systemImage: "gear") {
671
- Form {
672
- Toggle("Show Previews", isOn: $showPreviews)
673
- Slider(value: $fontSize, in: 9...96) {
674
- Text("Font Size (\(fontSize, specifier: "%.0f") pts)")
675
- }
676
- }
677
- }
577
+ struct PreferencesView: View {
578
+ @AppStorage("showThumbnails") private var showThumbnails = true
579
+ @AppStorage("readerTextSize") private var readerTextSize = 14.0
678
580
 
679
- Tab("Advanced", systemImage: "star") {
680
- Form {
681
- Toggle("Enable Advanced Mode", isOn: .constant(false))
581
+ var body: some View {
582
+ TabView {
583
+ Tab("General", systemImage: "gearshape") {
584
+ Form {
585
+ Toggle("Show thumbnails", isOn: $showThumbnails)
586
+ }
587
+ }
588
+ Tab("Reading", systemImage: "textformat.size") {
589
+ Form {
590
+ Slider(value: $readerTextSize, in: 9...96) {
591
+ Text("Text size: \(readerTextSize, specifier: "%.0f")")
592
+ }
593
+ }
594
+ }
682
595
  }
683
- }
596
+ .scenePadding()
597
+ .frame(maxWidth: 420, minHeight: 240)
684
598
  }
685
- .scenePadding()
686
- .frame(maxWidth: 420, minHeight: 240)
687
- }
688
599
  }
689
600
  ```
690
601
 
691
- ### Skip navigation
602
+ `Tab` inside the settings `TabView` needs macOS 15; for macOS 14 use
603
+ `.tabItem { Label(...) }` on each child instead.
604
+
605
+ Guidelines:
692
606
 
693
- - Avoid wrapping `SettingsView` in a `NavigationStack` unless you truly need deep push navigation.
694
- - Prefer tabs or sections; Settings is already presented as a separate window and should feel flat.
695
- - If you must show hierarchical settings, use a single `NavigationSplitView` with a sidebar list of categories.
607
+ - Do not wrap the settings view in a `NavigationStack` unless deep push
608
+ navigation is genuinely needed.
609
+ - Settings is its own window and should feel flat: tabs or sections.
610
+ - For hierarchical settings, use one `NavigationSplitView` with a sidebar of
611
+ categories.
696
612
 
697
- ### Pitfalls
613
+ Pitfalls:
698
614
 
699
- - Don't reuse iOS-only settings layouts (full-screen stacks, toolbar-heavy flows).
700
- - Avoid large custom view hierarchies inside `Form`; keep rows focused and accessible.
615
+ - Reusing iOS settings layouts on the Mac (full-screen stacks, toolbar-heavy
616
+ flows).
617
+ - Deep custom hierarchies stuffed into a `Form`. Each row should hold one
618
+ simple, accessible control.