@mmerterden/multi-agent-pipeline 20.6.0 → 20.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (326) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/LICENSE +0 -10
  3. package/docs/facts.json +1 -1
  4. package/manifest.json +328 -329
  5. package/package.json +2 -2
  6. package/pipeline/multi-agent-refs/features/design-conformance.md +62 -64
  7. package/pipeline/scripts/_notices.mjs +12 -1
  8. package/pipeline/scripts/gen-skills-index.mjs +1 -1
  9. package/pipeline/skills/.skill-manifest.json +106 -106
  10. package/pipeline/skills/shared/README.md +71 -71
  11. package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +1 -0
  12. package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
  13. package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
  14. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
  15. package/pipeline/skills/shared/external/android-architecture/SKILL.md +2 -0
  16. package/pipeline/skills/shared/external/android-performance/SKILL.md +2 -0
  17. package/pipeline/skills/shared/external/android-security/SKILL.md +2 -0
  18. package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
  19. package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
  20. package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
  21. package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
  22. package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
  23. package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
  24. package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
  25. package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
  26. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
  27. package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
  28. package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
  29. package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
  30. package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
  31. package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
  32. package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
  33. package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
  34. package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
  35. package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
  36. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
  37. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
  38. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
  39. package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
  40. package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
  41. package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
  42. package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
  43. package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
  44. package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
  45. package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
  46. package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
  47. package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
  48. package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
  49. package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
  50. package/pipeline/skills/shared/external/backlog/BACKLOG.md +1 -1
  51. package/pipeline/skills/shared/external/backlog/SKILL.md +56 -33
  52. package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
  53. package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
  54. package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
  55. package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +1 -0
  56. package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
  57. package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
  58. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
  59. package/pipeline/skills/shared/external/compose-components/SKILL.md +2 -0
  60. package/pipeline/skills/shared/external/compose-navigation/SKILL.md +3 -2
  61. package/pipeline/skills/shared/external/compose-testing/SKILL.md +2 -0
  62. package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
  63. package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
  64. package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
  65. package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
  66. package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
  67. package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
  68. package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
  69. package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
  70. package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
  71. package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
  72. package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
  73. package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
  74. package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
  75. package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
  76. package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
  77. package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
  78. package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
  79. package/pipeline/skills/shared/external/council/SKILL.md +1 -0
  80. package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
  81. package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
  82. package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
  83. package/pipeline/skills/shared/external/css-modern/SKILL.md +1 -0
  84. package/pipeline/skills/shared/external/database-patterns/SKILL.md +1 -0
  85. package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
  86. package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
  87. package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
  88. package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
  89. package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
  90. package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
  91. package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
  92. package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
  93. package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
  94. package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
  95. package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
  96. package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
  97. package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
  98. package/pipeline/skills/shared/external/evidence-github/SKILL.md +2 -0
  99. package/pipeline/skills/shared/external/evidence-registry/SKILL.md +2 -0
  100. package/pipeline/skills/shared/external/gradle-kotlin-dsl/SKILL.md +2 -0
  101. package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
  102. package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
  103. package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
  104. package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
  105. package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
  106. package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
  107. package/pipeline/skills/shared/external/html-semantic/SKILL.md +1 -0
  108. package/pipeline/skills/shared/external/humanizer/SKILL.md +1 -0
  109. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
  110. package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
  111. package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
  112. package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
  113. package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
  114. package/pipeline/skills/shared/external/ios-coding-standard/SKILL.md +1 -0
  115. package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
  116. package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
  117. package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
  118. package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
  119. package/pipeline/skills/shared/external/ios-module-structure/SKILL.md +1 -0
  120. package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
  121. package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
  122. package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
  123. package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
  124. package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
  125. package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
  126. package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
  127. package/pipeline/skills/shared/external/ios-security/SKILL.md +2 -0
  128. package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
  129. package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
  130. package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
  131. package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
  132. package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
  133. package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
  134. package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +91 -283
  135. package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +119 -151
  136. package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +60 -90
  137. package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +119 -156
  138. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +726 -787
  139. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +253 -288
  140. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +243 -304
  141. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +88 -104
  142. package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +181 -235
  143. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-key-shots.py +198 -263
  144. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +461 -466
  145. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +145 -151
  146. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +123 -141
  147. package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +146 -157
  148. package/pipeline/skills/shared/external/localization-reuse-map/scripts/snapshot-resources.sh +22 -19
  149. package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +156 -140
  150. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
  151. package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
  152. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
  153. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
  154. package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
  155. package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
  156. package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
  157. package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
  158. package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
  159. package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
  160. package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
  161. package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
  162. package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
  163. package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +1 -0
  164. package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
  165. package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
  166. package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
  167. package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
  168. package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
  169. package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
  170. package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
  171. package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
  172. package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
  173. package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
  174. package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
  175. package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
  176. package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
  177. package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
  178. package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
  179. package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
  180. package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
  181. package/pipeline/skills/shared/external/play-store-review/SKILL.md +2 -0
  182. package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
  183. package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
  184. package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
  185. package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
  186. package/pipeline/skills/shared/external/python-patterns/SKILL.md +1 -0
  187. package/pipeline/skills/shared/external/react-best-practices/SKILL.md +1 -0
  188. package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
  189. package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
  190. package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
  191. package/pipeline/skills/shared/external/rest-api-design/SKILL.md +1 -0
  192. package/pipeline/skills/shared/external/retrofit-networking/SKILL.md +2 -0
  193. package/pipeline/skills/shared/external/room-database/SKILL.md +2 -0
  194. package/pipeline/skills/shared/external/search-first/SKILL.md +1 -0
  195. package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
  196. package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
  197. package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
  198. package/pipeline/skills/shared/external/signal-community/SKILL.md +2 -0
  199. package/pipeline/skills/shared/external/skill-creator/SKILL.md +80 -41
  200. package/pipeline/skills/shared/external/skill-creator/audit.md +63 -59
  201. package/pipeline/skills/shared/external/skill-creator/checklist.md +28 -20
  202. package/pipeline/skills/shared/external/skill-creator/examples.md +40 -40
  203. package/pipeline/skills/shared/external/skill-creator/label-check.md +48 -36
  204. package/pipeline/skills/shared/external/skill-creator/scripts/audit-panel.js +91 -100
  205. package/pipeline/skills/shared/external/skill-creator/template.md +51 -39
  206. package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
  207. package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
  208. package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
  209. package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
  210. package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
  211. package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
  212. package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
  213. package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
  214. package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
  215. package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
  216. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
  217. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
  218. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
  219. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
  220. package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
  221. package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
  222. package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
  223. package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
  224. package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
  225. package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
  226. package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
  227. package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
  228. package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
  229. package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
  230. package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
  231. package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
  232. package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
  233. package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
  234. package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
  235. package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
  236. package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
  237. package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
  238. package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
  239. package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
  240. package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
  241. package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
  242. package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
  243. package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
  244. package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
  245. package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
  246. package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
  247. package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
  248. package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
  249. package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
  250. package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
  251. package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
  252. package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
  253. package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
  254. package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
  255. package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
  256. package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
  257. package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
  258. package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
  259. package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
  260. package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
  261. package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
  262. package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
  263. package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
  264. package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
  265. package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
  266. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
  267. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
  268. package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
  269. package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
  270. package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
  271. package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
  272. package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
  273. package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
  274. package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
  275. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
  276. package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
  277. package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
  278. package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
  279. package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
  280. package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
  281. package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
  282. package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
  283. package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
  284. package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
  285. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
  286. package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
  287. package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
  288. package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
  289. package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
  290. package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
  291. package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
  292. package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
  293. package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
  294. package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
  295. package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
  296. package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
  297. package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
  298. package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
  299. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
  300. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
  301. package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
  302. package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
  303. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
  304. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
  305. package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
  306. package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
  307. package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
  308. package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
  309. package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
  310. package/pipeline/skills/shared/external/tailwind-css/SKILL.md +1 -0
  311. package/pipeline/skills/shared/external/testing-backend/SKILL.md +1 -0
  312. package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
  313. package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
  314. package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +1 -0
  315. package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
  316. package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
  317. package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
  318. package/pipeline/skills/shared/external/vue-composition/SKILL.md +1 -0
  319. package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
  320. package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
  321. package/pipeline/skills/shared/external/web-accessibility/SKILL.md +1 -0
  322. package/pipeline/skills/shared/external/web-performance/SKILL.md +1 -0
  323. package/pipeline/skills/shared/external/web-testing/SKILL.md +1 -0
  324. package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
  325. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
  326. package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
@@ -1,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.