@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
@@ -4,43 +4,43 @@
4
4
  {
5
5
  "id": 0,
6
6
  "name": "text-analysis-pipeline",
7
- "prompt": "I'm adding an iOS 26 inbox feature that detects the message language, tokenizes words, extracts people and organizations, computes a sentiment score, and finds semantically similar keywords for search suggestions. Sketch the NaturalLanguage implementation and review checklist.",
8
- "expected_output": "A NaturalLanguage implementation outline that uses NLTokenizer, NLLanguageRecognizer, NLTagger, and NLEmbedding accurately, handles language/support limits, and avoids thread-safety and per-token tagger mistakes.",
7
+ "prompt": "Our support inbox app receives short customer messages in many languages. For each message we want the language, any people, places and companies mentioned, an overall mood score, and a list of similar past keywords. Processing runs on a background queue with several workers. Design the NaturalLanguage side.",
8
+ "expected_output": "Picks sensible token units, keeps every NLTokenizer and NLTagger confined to one worker at a time, uses languageConstraints or languageHints because messages are short, tags entities with the .nameType scheme and scores mood with .sentimentScore, passes .omitWhitespace, .omitPunctuation and .joinNames, handles optional tags and sentiment without force unwraps, and checks that a word embedding exists before using it.",
9
9
  "files": [],
10
10
  "expectations": [
11
- "Uses NLTokenizer with the correct token unit and keeps tokenizer/tagger instances confined to one thread or dispatch queue at a time.",
12
- "Uses NLLanguageRecognizer with languageConstraints or languageHints when text is short or expected languages are known.",
13
- "Uses NLTagger with .nameType, .sentimentScore, and appropriate options such as .omitWhitespace, .omitPunctuation, and .joinNames.",
14
- "Treats sentiment and tags as optional and handles unsupported languages or missing tag schemes instead of force-unwrapping.",
15
- "Checks NLEmbedding word or sentence embedding availability and does not assume embeddings exist for every language."
11
+ "Chooses appropriate tokenizer units and confines each tokenizer or tagger to a single thread",
12
+ "Adds languageConstraints or languageHints for short messages",
13
+ "Uses .nameType for entities and .sentimentScore for mood",
14
+ "Uses the options .omitWhitespace, .omitPunctuation and .joinNames",
15
+ "Handles optional tags, sentiment and embeddings without force unwrapping"
16
16
  ]
17
17
  },
18
18
  {
19
19
  "id": 1,
20
20
  "name": "translation-availability-review",
21
- "prompt": "Review this SwiftUI translation plan: use the system translation popover on iOS 17.4, use TranslationSession and .translationTask for programmatic batch translation on the same deployment target, prefer .highFidelity because it can use a server, and ignore errors because the framework downloads languages automatically.",
22
- "expected_output": "A correction-focused Translation framework review that splits API availability, keeps translation on-device, handles language availability and throwing APIs, and explains SwiftUI and direct-session usage safely.",
21
+ "prompt": "Review our plan: we target iOS 17.4, call TranslationSession directly on launch with the high-fidelity strategy because it uses the cloud, and translate our menu in one batch without any error handling. What is wrong?",
22
+ "expected_output": "Separates availability: the system translation sheet exists from iOS 17.4, whereas iOS 18 is the floor for sessions, the translationTask modifier, LanguageAvailability and batches, and strategies need 26.4. Corrects the claim that .highFidelity uses a server: translation runs on device, with .highFidelity preferring Apple Intelligence models and .lowLatency the classic models. Uses LanguageAvailability with its installed, supported and unsupported states, puts every translate, translations(from:) and prepareTranslation call inside do-catch, and explains that TranslationSession(installedSource:target:) needs both languages installed while translationTask can prompt for downloads.",
23
23
  "files": [],
24
24
  "expectations": [
25
- "Separates translationPresentation availability from TranslationSession, translationTask, LanguageAvailability, and batch translation availability.",
26
- "Corrects highFidelity/lowLatency guidance without claiming TranslationSession sends content to a server.",
27
- "Uses LanguageAvailability status checks and handles .installed, .supported, and .unsupported.",
28
- "Wraps TranslationSession throwing calls such as translate, translations(from:), and prepareTranslation in error handling.",
29
- "Explains that direct TranslationSession(installedSource:target:) outside SwiftUI requires installed languages, while SwiftUI translationTask can request downloads."
25
+ "Distinguishes the 17.4 presentation API from the iOS 18 session, task, availability and batch APIs",
26
+ "States that neither strategy sends text to a server",
27
+ "Lists the .installed, .supported and .unsupported availability states",
28
+ "Catches errors from translate, translations(from:) and prepareTranslation",
29
+ "Explains that the installedSource initializer requires installed languages whereas translationTask can request downloads"
30
30
  ]
31
31
  },
32
32
  {
33
33
  "id": 2,
34
34
  "name": "sibling-boundary-routing",
35
- "prompt": "I have one feature request: scan text from a receipt image, transcribe a spoken note, tokenize and identify the language of the resulting text, detect names and sentiment, find semantically similar keywords with embeddings, maybe add a custom text classifier/tagger, translate a summary to Spanish, localize UI strings with String Catalogs (.xcstrings), plurals, RTL, date and currency formatting, and maybe use Apple Intelligence to generate the summary. Which parts belong in the NaturalLanguage skill and which should be handed to sibling skills?",
36
- "expected_output": "A boundary-aware routing answer that keeps NaturalLanguage/Translation responsible for text analysis and translation, and routes OCR, speech transcription, localization, and generative summarization to the appropriate sibling skills.",
35
+ "prompt": "Our travel journal app scans printed tickets, dictates voice notes, shows its UI in eight languages, summarizes each trip, and tags places and moods in the journal text. Which parts belong to the NaturalLanguage skill and which go elsewhere?",
36
+ "expected_output": "Keeps tokenization, language identification, entity extraction, sentiment, embeddings and translation of journal text in this skill. Ticket OCR goes to vision-framework, voice-note transcription to speech-recognition, String Catalogs, plurals and formatting to ios-localization, and generated trip summaries to apple-on-device-ai.",
37
37
  "files": [],
38
38
  "expectations": [
39
- "Keeps tokenization, language identification, named entity recognition, sentiment analysis, embeddings, and in-app translation in the natural-language scope.",
40
- "Routes receipt-image OCR to the Vision framework skill rather than treating NaturalLanguage as OCR.",
41
- "Routes spoken-note transcription to the Speech framework skill rather than treating NaturalLanguage as speech recognition.",
42
- "Routes UI strings, String Catalogs, pluralization, and locale-aware formatting to the iOS localization skill.",
43
- "Routes Apple Intelligence or generative summarization to the on-device AI skill rather than presenting NaturalLanguage as a generative LLM framework."
39
+ "Keeps tokenization, language identification, entities, sentiment, embeddings and translation here",
40
+ "Sends ticket OCR to vision-framework",
41
+ "Sends voice-note transcription to speech-recognition",
42
+ "Sends UI strings, plurals and formatting to ios-localization",
43
+ "Sends generated trip summaries to apple-on-device-ai"
44
44
  ]
45
45
  }
46
46
  ]
@@ -1,324 +1,270 @@
1
- # NaturalLanguage + Translation Extended Patterns
1
+ # Translation and text-analysis patterns
2
2
 
3
- Overflow reference for the `natural-language` skill. Contains advanced patterns
4
- that exceed the main skill file's scope.
3
+ Deeper material for the `natural-language` skill ([../SKILL.md](../SKILL.md)).
5
4
 
6
- ## Contents
5
+ ## Plugging in a Create ML model
7
6
 
8
- - [Custom NLModel Integration](#custom-nlmodel-integration)
9
- - [Contextual Embeddings](#contextual-embeddings)
10
- - [Gazetteers for Domain Vocabulary](#gazetteers-for-domain-vocabulary)
11
- - [NLTagger with Multiple Schemes](#nltagger-with-multiple-schemes)
12
- - [Translation with Replacement Action](#translation-with-replacement-action)
13
- - [Translation Session Strategies](#translation-session-strategies)
14
- - [SwiftUI Integration Patterns](#swiftui-integration-patterns)
15
- - [Lemmatization](#lemmatization)
16
-
17
- ## Custom NLModel Integration
18
-
19
- Load a Create ML text classifier or word tagger into `NLTagger` via `NLModel`.
7
+ A text classifier or word tagger trained in Create ML is loaded as an
8
+ `MLModel`, wrapped in `NLModel`, and then either attached to a tagger or
9
+ called directly.
20
10
 
21
11
  ```swift
22
- import NaturalLanguage
23
12
  import CoreML
13
+ import NaturalLanguage
24
14
 
25
- func setupCustomTagger() throws -> NLTagger {
26
- let mlModel = try MLModel(contentsOf: modelURL)
27
- let nlModel = try NLModel(mlModel: mlModel)
28
-
29
- let tagger = NLTagger(tagSchemes: [.nameType])
30
- tagger.setModels([nlModel], forTagScheme: .nameType)
31
- return tagger
32
- }
33
-
34
- // Direct prediction without a tagger
35
- func classifyText(_ text: String) throws -> String? {
36
- let mlModel = try MLModel(contentsOf: modelURL)
37
- let nlModel = try NLModel(mlModel: mlModel)
38
- return nlModel.predictedLabel(for: text)
15
+ func makeTicketTagger(modelURL: URL) throws -> (NLTagger, NLModel) {
16
+ let compiled = try MLModel(contentsOf: modelURL)
17
+ let wrapper = try NLModel(mlModel: compiled)
18
+ let routing = NLTagScheme("TicketRouting")
19
+ let tagger = NLTagger(tagSchemes: [routing])
20
+ tagger.setModels([wrapper], forTagScheme: routing)
21
+ return (tagger, wrapper)
39
22
  }
40
23
 
41
- // Predictions with confidence scores
42
- func classifyWithConfidence(_ text: String) throws -> [String: Double] {
43
- let mlModel = try MLModel(contentsOf: modelURL)
44
- let nlModel = try NLModel(mlModel: mlModel)
45
- return nlModel.predictedLabelHypotheses(for: text, maximumCount: 5)
24
+ func triage(_ ticket: String, with wrapper: NLModel) -> (String?, [String: Double]) {
25
+ let top = wrapper.predictedLabel(for: ticket)
26
+ let spread = wrapper.predictedLabelHypotheses(for: ticket, maximumCount: 3)
27
+ return (top, spread)
46
28
  }
47
29
  ```
48
30
 
49
- ## Contextual Embeddings
31
+ ## Contextual embeddings
50
32
 
51
- `NLContextualEmbedding` produces context-aware vectors where the same word
52
- gets different vectors based on surrounding text.
33
+ `NLContextualEmbedding` produces vectors that depend on the surrounding
34
+ words, so "bank" in "river bank" and "bank loan" get different values. The
35
+ initializer is failable, and the model assets may need a download first.
53
36
 
54
37
  ```swift
55
- import NaturalLanguage
38
+ func tokenVectors(for text: String) async throws -> [[Double]] {
39
+ guard let model = NLContextualEmbedding(language: .english) else { return [] }
56
40
 
57
- func contextualVectors(for text: String) throws -> [([Double], Range<String.Index>)] {
58
- guard let embedding = NLContextualEmbedding(language: .english) else {
59
- return []
60
- }
61
-
62
- // Check and load assets
63
- guard embedding.hasAvailableAssets else {
64
- embedding.requestAssets { result, error in
65
- // Handle download
66
- }
67
- return []
41
+ if !model.hasAvailableAssets {
42
+ let outcome = try await model.requestAssets()
43
+ guard outcome == .available else { return [] }
68
44
  }
69
45
 
70
- try embedding.load()
71
- defer { embedding.unload() }
46
+ try model.load()
47
+ defer { model.unload() }
72
48
 
73
- let result = try embedding.embeddingResult(for: text, language: .english)
74
- var vectors: [([Double], Range<String.Index>)] = []
75
-
76
- result.enumerateTokenVectors(in: text.startIndex..<text.endIndex) { vector, range in
77
- vectors.append((vector, range))
49
+ let result = try model.embeddingResult(for: text, language: .english)
50
+ var vectors: [[Double]] = []
51
+ let whole = text.startIndex..<text.endIndex
52
+ result.enumerateTokenVectors(in: whole) { vector, _ in
53
+ vectors.append(vector)
78
54
  return true
79
55
  }
80
56
  return vectors
81
57
  }
82
58
  ```
83
59
 
84
- ### Finding Available Contextual Embeddings
60
+ A completion-handler form, `requestAssets { result, error in }`, is also
61
+ available. To see which models exist for a language:
85
62
 
86
63
  ```swift
87
- let embeddings = NLContextualEmbedding.contextualEmbeddings(forValues: [
88
- .languages: [NLLanguage.english.rawValue]
89
- ])
90
-
91
- for embedding in embeddings {
92
- print("Model: \(embedding.modelIdentifier)")
93
- print("Dimension: \(embedding.dimension)")
94
- print("Max length: \(embedding.maximumSequenceLength)")
64
+ let candidates = NLContextualEmbedding.contextualEmbeddings(
65
+ forValues: [.languages: [NLLanguage.german.rawValue]]
66
+ )
67
+ for model in candidates {
68
+ print(model.modelIdentifier, model.dimension, model.maximumSequenceLength)
95
69
  }
96
70
  ```
97
71
 
98
- ## Gazetteers for Domain Vocabulary
72
+ ## Gazetteers for your own vocabulary
99
73
 
100
- Override or supplement tagger results with custom term-to-label mappings.
74
+ A gazetteer maps known terms to labels and overrides or supplements what the
75
+ tagger would say. Useful for product names, internal teams or medical terms.
101
76
 
102
77
  ```swift
103
- func setupGazetteer() throws -> NLTagger {
104
- let dictionary: [String: [String]] = [
105
- "PRODUCT": ["iPhone", "MacBook Pro", "Apple Watch"],
106
- "FEATURE": ["Dynamic Island", "ProMotion", "MagSafe"]
107
- ]
108
-
109
- let gazetteer = try NLGazetteer(dictionary: dictionary, language: .english)
110
- let tagger = NLTagger(tagSchemes: [.nameType])
111
- tagger.setGazetteers([gazetteer], for: .nameType)
112
- return tagger
113
- }
78
+ let catalogue = try NLGazetteer(
79
+ dictionary: [
80
+ "Product": ["Aurora Hub", "Nimbus Cam"],
81
+ "Team": ["Platform Guild", "Night Shift"]
82
+ ],
83
+ language: .english
84
+ )
85
+ let tagger = NLTagger(tagSchemes: [.nameType])
86
+ tagger.setGazetteers([catalogue], for: .nameType)
114
87
 
115
- // Persist a gazetteer to disk
116
- func saveGazetteer(_ dictionary: [String: [String]], to url: URL) throws {
117
- try NLGazetteer.write(dictionary, language: .english, to: url)
118
- }
88
+ try NLGazetteer.write(["Product": ["Aurora Hub"]],
89
+ language: .english,
90
+ to: cacheFolder.appendingPathComponent("products.gazetteer"))
119
91
  ```
120
92
 
121
- ## NLTagger with Multiple Schemes
93
+ ## One tagger, several schemes
122
94
 
123
- Request multiple tag schemes in a single tagger for efficient processing.
95
+ Load all the schemes you need up front and query them from the same pass.
124
96
 
125
97
  ```swift
126
- func analyzeText(_ text: String) {
127
- let tagger = NLTagger(tagSchemes: [.lexicalClass, .nameType, .lemma])
128
- tagger.string = text
129
-
130
- let range = text.startIndex..<text.endIndex
131
- let options: NLTagger.Options = [.omitWhitespace, .omitPunctuation, .joinNames]
132
-
133
- tagger.enumerateTags(in: range, unit: .word, scheme: .nameTypeOrLexicalClass,
134
- options: options) { tag, tokenRange in
135
- let word = String(text[tokenRange])
136
- let (lemmaTag, _) = tagger.tag(at: tokenRange.lowerBound,
137
- unit: .word, scheme: .lemma)
138
- let lemma = lemmaTag?.rawValue ?? word
139
- print("\(word) -> tag: \(tag?.rawValue ?? "?"), lemma: \(lemma)")
140
- return true
141
- }
98
+ let multi = NLTagger(tagSchemes: [.lexicalClass, .nameType, .lemma])
99
+ multi.string = note
100
+ multi.enumerateTags(in: note.startIndex..<note.endIndex,
101
+ unit: .word,
102
+ scheme: .nameTypeOrLexicalClass,
103
+ options: [.omitPunctuation, .omitWhitespace, .joinNames]) { kind, span in
104
+ let (root, _) = multi.tag(at: span.lowerBound, unit: .word, scheme: .lemma)
105
+ rows.append((String(note[span]), kind?.rawValue ?? "?", root?.rawValue))
106
+ return true
142
107
  }
143
108
  ```
144
109
 
145
- ## Translation with Replacement Action
110
+ ## Translating text in place
146
111
 
147
- Replace the source text in-place after translation using the replacement action.
112
+ With a `replacementAction`, the system sheet offers a Replace button that
113
+ hands you the translated string.
148
114
 
149
115
  ```swift
150
- import SwiftUI
151
- import Translation
152
-
153
- struct EditableTranslationView: View {
154
- @State private var text = "Hello, how are you?"
155
- @State private var showTranslation = false
116
+ struct DraftEditor: View {
117
+ @State private var draft = ""
118
+ @State private var translating = false
156
119
 
157
120
  var body: some View {
158
- TextEditor(text: $text)
159
- .toolbar {
160
- Button("Translate") { showTranslation = true }
121
+ TextEditor(text: $draft)
122
+ .toolbar { Button("Translate") { translating = true } }
123
+ .translationPresentation(isPresented: $translating, text: draft) { translated in
124
+ draft = translated
161
125
  }
162
- .translationPresentation(
163
- isPresented: $showTranslation,
164
- text: text,
165
- replacementAction: { translated in
166
- text = translated
167
- }
168
- )
169
126
  }
170
127
  }
171
128
  ```
172
129
 
173
- ## Translation Session Strategies
130
+ ## Choosing a translation strategy
174
131
 
175
- Control whether translations prioritize quality or speed. Strategy selection
176
- requires iOS 26.4+ / macOS 26.4+. Translation content is processed on device;
177
- `.highFidelity` uses Apple Intelligence models when available, and
178
- `.lowLatency` uses traditional models.
132
+ Requires iOS 26.4 or macOS 26.4. Translation always runs on the device.
133
+ `.highFidelity` prefers the Apple Intelligence translation models when the
134
+ device has them; `.lowLatency` uses the classic translation models. Neither
135
+ sends text to a server.
179
136
 
180
137
  ```swift
181
- import Translation
182
-
183
- // High fidelity: more fluent translations when Apple Intelligence is available
184
- let highQualityConfig = TranslationSession.Configuration(
185
- source: Locale.Language(identifier: "en"),
186
- target: Locale.Language(identifier: "ja"),
187
- preferredStrategy: .highFidelity
188
- )
189
-
190
- // Low latency: faster traditional translation models
191
- let fastConfig = TranslationSession.Configuration(
192
- source: Locale.Language(identifier: "en"),
193
- target: Locale.Language(identifier: "ja"),
194
- preferredStrategy: .lowLatency
195
- )
138
+ if #available(iOS 26.4, macOS 26.4, *) {
139
+ request = TranslationSession.Configuration(
140
+ source: Locale.Language(identifier: "fr"),
141
+ target: Locale.Language(identifier: "en"),
142
+ preferredStrategy: .lowLatency
143
+ )
144
+ }
196
145
  ```
197
146
 
198
- ### Preparing a Translation Session
147
+ ## Getting a session ready
199
148
 
200
- Pre-download models before translating to avoid UI delays.
149
+ Download models before the user is waiting on a result:
201
150
 
202
151
  ```swift
203
- .translationTask(configuration) { session in
204
- do {
205
- try await session.prepareTranslation()
206
- // Models are now ready, translate without delay
207
- let response = try await session.translate(sourceText)
208
- await MainActor.run {
209
- translatedText = response.targetText
210
- }
211
- } catch {
212
- // Handle download refusal, cancellation, or unsupported language pairs.
152
+ struct PhrasebookScreen: View {
153
+ @State private var warmUp: TranslationSession.Configuration?
154
+
155
+ var body: some View {
156
+ PhraseList()
157
+ .onAppear { warmUp = .init(source: .init(identifier: "es"), target: .init(identifier: "en")) }
158
+ .translationTask(warmUp) { @concurrent session in
159
+ do {
160
+ try await session.prepareTranslation() // triggers any download now
161
+ } catch {
162
+ // declined download, cancellation, or an unsupported pair
163
+ }
164
+ }
213
165
  }
214
166
  }
215
167
  ```
216
168
 
217
- For non-UI translation, initialize `TranslationSession(installedSource:target:)`
218
- only after the source and target languages are installed; this initializer
219
- throws when the required languages are unavailable.
169
+ `PhraseList` stands for the app's own content view. The closure is
170
+ `@concurrent` for the same reason as in the main skill: the session is not
171
+ `Sendable` and cannot be used from the main actor.
172
+
173
+ `TranslationSession(installedSource:target:)` (iOS 26, macOS 26) builds a
174
+ session without any view. The initializer does not throw; the session works
175
+ only with models already on the device, so translating fails when either
176
+ language is missing. Create it only after `LanguageAvailability` reports
177
+ `.installed`; a `.translationTask` session, in contrast, can ask the user to
178
+ download.
220
179
 
221
- ## SwiftUI Integration Patterns
180
+ ```swift
181
+ @available(iOS 26, macOS 26, *)
182
+ func quietSession(from source: Locale.Language, to target: Locale.Language) async -> TranslationSession? {
183
+ let state = await LanguageAvailability().status(from: source, to: target)
184
+ guard state == .installed else { return nil }
185
+ return TranslationSession(installedSource: source, target: target)
186
+ }
187
+ ```
222
188
 
223
- ### Language Analysis View
189
+ ## A live analysis panel in SwiftUI
224
190
 
225
191
  ```swift
226
- import SwiftUI
227
192
  import NaturalLanguage
193
+ import Observation
194
+ import SwiftUI
228
195
 
229
196
  @Observable
230
197
  @MainActor
231
- final class TextAnalyzer {
232
- var tokens: [String] = []
233
- var detectedLanguage: String = ""
234
- var sentimentLabel: String = ""
235
-
236
- func analyze(_ text: String) {
237
- guard !text.isEmpty else { return }
238
-
239
- // Tokenize
240
- let tokenizer = NLTokenizer(unit: .word)
241
- tokenizer.string = text
242
- tokens = tokenizer.tokens(for: text.startIndex..<text.endIndex)
243
- .map { String(text[$0]) }
244
-
245
- // Language
246
- detectedLanguage = NLLanguageRecognizer.dominantLanguage(for: text)?
247
- .rawValue ?? "Unknown"
248
-
249
- // Sentiment
250
- let tagger = NLTagger(tagSchemes: [.sentimentScore])
251
- tagger.string = text
252
- let (tag, _) = tagger.tag(at: text.startIndex, unit: .paragraph,
253
- scheme: .sentimentScore)
254
- if let score = tag.flatMap({ Double($0.rawValue) }) {
255
- sentimentLabel = score > 0.1 ? "Positive" :
256
- score < -0.1 ? "Negative" : "Neutral"
257
- }
198
+ final class TextInsights {
199
+ private(set) var wordCount = 0
200
+ private(set) var languageCode = "-"
201
+ private(set) var tone = "neutral"
202
+
203
+ func update(for text: String) {
204
+ let words = NLTokenizer(unit: .word)
205
+ words.string = text
206
+ let everything = text.startIndex..<text.endIndex
207
+ wordCount = words.tokens(for: everything).count
208
+
209
+ languageCode = NLLanguageRecognizer.dominantLanguage(for: text)?.rawValue ?? "-"
210
+
211
+ let scorer = NLTagger(tagSchemes: [.sentimentScore])
212
+ scorer.string = text
213
+ let (moodTag, _) = scorer.tag(at: everything.lowerBound, unit: .paragraph, scheme: .sentimentScore)
214
+ let value = moodTag.flatMap { Double($0.rawValue) } ?? 0
215
+ tone = value > 0.1 ? "positive" : value < -0.1 ? "negative" : "neutral"
258
216
  }
259
217
  }
260
218
 
261
- struct TextAnalysisView: View {
262
- @State private var text = ""
263
- @State private var analyzer = TextAnalyzer()
219
+ struct InsightsPanel: View {
220
+ @State private var input = ""
221
+ @State private var insights = TextInsights()
264
222
 
265
223
  var body: some View {
266
224
  Form {
267
- TextField("Enter text", text: $text)
268
- .onChange(of: text) { _, newValue in
269
- analyzer.analyze(newValue)
270
- }
271
- Section("Results") {
272
- LabeledContent("Language", value: analyzer.detectedLanguage)
273
- LabeledContent("Sentiment", value: analyzer.sentimentLabel)
274
- LabeledContent("Words", value: "\(analyzer.tokens.count)")
275
- }
225
+ TextField("Type something", text: $input, axis: .vertical)
226
+ .onChange(of: input) { _, text in insights.update(for: text) }
227
+ LabeledContent("Words", value: "\(insights.wordCount)")
228
+ LabeledContent("Language", value: insights.languageCode)
229
+ LabeledContent("Tone", value: insights.tone)
276
230
  }
277
231
  }
278
232
  }
279
233
  ```
280
234
 
281
- ### Requesting NLTagger Assets
235
+ ### Tagger assets
282
236
 
283
- Some tag schemes require downloadable assets. Request them before tagging.
237
+ Some schemes need assets that are fetched on demand:
284
238
 
285
239
  ```swift
286
- NLTagger.requestAssets(for: .japanese, tagScheme: .nameType) { result, error in
287
- switch result {
288
- case .available:
289
- // Assets loaded, safe to tag Japanese text
290
- break
291
- case .notAvailable:
292
- // Assets not available for this language/scheme
293
- break
294
- case .error:
295
- print("Asset request error: \(error?.localizedDescription ?? "")")
296
- @unknown default:
297
- break
240
+ NLTagger.requestAssets(for: .korean, tagScheme: .lexicalClass) { outcome, _ in
241
+ switch outcome {
242
+ case .available: break // ready to tag
243
+ case .notAvailable: break // this scheme is not offered for the language
244
+ case .error: break // retry later
245
+ @unknown default: break
298
246
  }
299
247
  }
300
248
  ```
301
249
 
302
- ## Lemmatization
250
+ ## Lemmas for search
303
251
 
304
- Get the base form of words for indexing or search normalization.
252
+ Reducing words to their dictionary form makes "running" and "ran" match
253
+ "run", and "were" match "be". Handy for indexing and search keys.
305
254
 
306
255
  ```swift
307
- func lemmatize(_ text: String) -> [String] {
256
+ func lemmas(in text: String) -> [String] {
308
257
  let tagger = NLTagger(tagSchemes: [.lemma])
309
258
  tagger.string = text
310
-
311
- var lemmas: [String] = []
312
- tagger.enumerateTags(
313
- in: text.startIndex..<text.endIndex,
314
- unit: .word,
315
- scheme: .lemma,
316
- options: [.omitPunctuation, .omitWhitespace]
317
- ) { tag, range in
318
- lemmas.append(tag?.rawValue ?? String(text[range]))
259
+ var roots: [String] = []
260
+ let fullRange = text.startIndex..<text.endIndex
261
+ tagger.enumerateTags(in: fullRange,
262
+ unit: .word,
263
+ scheme: .lemma,
264
+ options: [.omitPunctuation, .omitWhitespace]) { tag, span in
265
+ roots.append(tag?.rawValue ?? String(text[span]))
319
266
  return true
320
267
  }
321
- return lemmas
268
+ return roots
322
269
  }
323
- // "The cats were running quickly" -> ["the", "cat", "be", "run", "quickly"]
324
270
  ```