@devo-bmad-custom/agent-orchestration 1.0.1 → 1.0.3
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.
- package/lib/installer.js +44 -11
- package/package.json +1 -1
- package/src/.agents/skills/audit-website/README.md +20 -20
- package/src/.agents/skills/audit-website/SKILL.md +470 -470
- package/src/.agents/skills/audit-website/agents/openai.yaml +6 -6
- package/src/.agents/skills/audit-website/assets/icon-small.svg +41 -41
- package/src/.agents/skills/audit-website/references/OUTPUT-FORMAT.md +250 -250
- package/src/.agents/skills/clean-code-standards/SKILL.md +104 -104
- package/src/.agents/skills/excalidraw-dark-standard/SKILL.md +281 -281
- package/src/.agents/skills/frontend-responsive-design-standards/SKILL.md +434 -434
- package/src/.agents/skills/java-fundamentals/SKILL.md +116 -116
- package/src/.agents/skills/java-performance/SKILL.md +119 -119
- package/src/.agents/skills/next-best-practices/SKILL.md +153 -153
- package/src/.agents/skills/next-best-practices/async-patterns.md +87 -87
- package/src/.agents/skills/next-best-practices/bundling.md +180 -180
- package/src/.agents/skills/next-best-practices/data-patterns.md +297 -297
- package/src/.agents/skills/next-best-practices/debug-tricks.md +105 -105
- package/src/.agents/skills/next-best-practices/directives.md +73 -73
- package/src/.agents/skills/next-best-practices/error-handling.md +227 -227
- package/src/.agents/skills/next-best-practices/file-conventions.md +140 -140
- package/src/.agents/skills/next-best-practices/font.md +245 -245
- package/src/.agents/skills/next-best-practices/functions.md +108 -108
- package/src/.agents/skills/next-best-practices/hydration-error.md +91 -91
- package/src/.agents/skills/next-best-practices/image.md +173 -173
- package/src/.agents/skills/next-best-practices/metadata.md +301 -301
- package/src/.agents/skills/next-best-practices/parallel-routes.md +287 -287
- package/src/.agents/skills/next-best-practices/route-handlers.md +146 -146
- package/src/.agents/skills/next-best-practices/rsc-boundaries.md +159 -159
- package/src/.agents/skills/next-best-practices/runtime-selection.md +39 -39
- package/src/.agents/skills/next-best-practices/scripts.md +141 -141
- package/src/.agents/skills/next-best-practices/self-hosting.md +371 -371
- package/src/.agents/skills/next-best-practices/suspense-boundaries.md +67 -67
- package/src/.agents/skills/nextjs-app-router-patterns/SKILL.md +537 -537
- package/src/.agents/skills/postgresql-optimization/SKILL.md +404 -404
- package/src/.agents/skills/python-backend/SKILL.md +153 -153
- package/src/.agents/skills/python-fundamentals/SKILL.md +234 -234
- package/src/.agents/skills/python-performance/SKILL.md +404 -404
- package/src/.agents/skills/react-expert/SKILL.md +335 -335
- package/src/.agents/skills/redis-best-practices/SKILL.md +438 -438
- package/src/.agents/skills/security-best-practices/SKILL.md +288 -288
- package/src/.agents/skills/security-review/LICENSE +22 -22
- package/src/.agents/skills/security-review/SKILL.md +312 -312
- package/src/.agents/skills/security-review/infrastructure/docker.md +432 -432
- package/src/.agents/skills/security-review/languages/javascript.md +388 -388
- package/src/.agents/skills/security-review/languages/python.md +363 -363
- package/src/.agents/skills/security-review/references/api-security.md +519 -519
- package/src/.agents/skills/security-review/references/authentication.md +353 -353
- package/src/.agents/skills/security-review/references/authorization.md +372 -372
- package/src/.agents/skills/security-review/references/business-logic.md +443 -443
- package/src/.agents/skills/security-review/references/cryptography.md +329 -329
- package/src/.agents/skills/security-review/references/csrf.md +398 -398
- package/src/.agents/skills/security-review/references/data-protection.md +378 -378
- package/src/.agents/skills/security-review/references/deserialization.md +410 -410
- package/src/.agents/skills/security-review/references/error-handling.md +436 -436
- package/src/.agents/skills/security-review/references/file-security.md +457 -457
- package/src/.agents/skills/security-review/references/injection.md +259 -259
- package/src/.agents/skills/security-review/references/logging.md +433 -433
- package/src/.agents/skills/security-review/references/misconfiguration.md +435 -435
- package/src/.agents/skills/security-review/references/modern-threats.md +475 -475
- package/src/.agents/skills/security-review/references/ssrf.md +415 -415
- package/src/.agents/skills/security-review/references/supply-chain.md +405 -405
- package/src/.agents/skills/security-review/references/xss.md +336 -336
- package/src/.agents/skills/subagent-driven-development/SKILL.md +275 -275
- package/src/.agents/skills/subagent-driven-development/code-quality-reviewer-prompt.md +26 -26
- package/src/.agents/skills/subagent-driven-development/implementer-prompt.md +113 -113
- package/src/.agents/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -61
- package/src/.agents/skills/systematic-debugging/CREATION-LOG.md +119 -119
- package/src/.agents/skills/systematic-debugging/SKILL.md +296 -296
- package/src/.agents/skills/systematic-debugging/condition-based-waiting-example.ts +158 -158
- package/src/.agents/skills/systematic-debugging/condition-based-waiting.md +115 -115
- package/src/.agents/skills/systematic-debugging/defense-in-depth.md +122 -122
- package/src/.agents/skills/systematic-debugging/root-cause-tracing.md +169 -169
- package/src/.agents/skills/systematic-debugging/test-academic.md +14 -14
- package/src/.agents/skills/systematic-debugging/test-pressure-1.md +58 -58
- package/src/.agents/skills/systematic-debugging/test-pressure-2.md +68 -68
- package/src/.agents/skills/systematic-debugging/test-pressure-3.md +69 -69
- package/src/.agents/skills/typescript-best-practices/SKILL.md +373 -373
- package/src/.agents/skills/ui-ux-pro-custom/SKILL.md +348 -348
- package/src/.agents/skills/ui-ux-pro-custom/data/charts.csv +26 -26
- package/src/.agents/skills/ui-ux-pro-custom/data/colors.csv +97 -97
- package/src/.agents/skills/ui-ux-pro-custom/data/icons.csv +101 -101
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/SKILL.md +106 -106
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/accessibility.md +475 -475
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/animation.md +466 -466
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/composition-locals.md +231 -231
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/deprecated-patterns.md +323 -323
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/lists-scrolling.md +400 -400
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/modifiers.md +331 -331
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/navigation.md +416 -416
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/performance.md +446 -446
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/side-effects.md +516 -516
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/foundation-source.md +13327 -13327
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/material3-source.md +19097 -19097
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/navigation-source.md +2947 -2947
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/runtime-source.md +11316 -11316
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/source-code/ui-source.md +7896 -7896
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/state-management.md +377 -377
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/styles-experimental.md +470 -470
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/theming-material3.md +349 -349
- package/src/.agents/skills/ui-ux-pro-custom/data/jetpack-compose-expert-skill/references/view-composition.md +595 -595
- package/src/.agents/skills/ui-ux-pro-custom/data/landing.csv +31 -31
- package/src/.agents/skills/ui-ux-pro-custom/data/mobile-ui-layout.md +654 -654
- package/src/.agents/skills/ui-ux-pro-custom/data/products.csv +96 -96
- package/src/.agents/skills/ui-ux-pro-custom/data/react-performance.csv +45 -45
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/astro.csv +54 -54
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/flutter.csv +53 -53
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/html-tailwind.csv +56 -56
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/jetpack-compose.csv +53 -53
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/nextjs.csv +53 -53
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/nuxt-ui.csv +51 -51
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/nuxtjs.csv +59 -59
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/react-native.csv +56 -56
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/react.csv +54 -54
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/shadcn.csv +61 -61
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/svelte.csv +54 -54
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/swiftui.csv +51 -51
- package/src/.agents/skills/ui-ux-pro-custom/data/stacks/vue.csv +50 -50
- package/src/.agents/skills/ui-ux-pro-custom/data/styles.csv +68 -68
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/alarmkit/SKILL.md +438 -438
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/alarmkit/references/alarmkit-patterns.md +584 -584
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-clips/SKILL.md +436 -436
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-intents/SKILL.md +489 -489
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-intents/references/appintents-advanced.md +1076 -1076
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-store-review/SKILL.md +340 -340
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-store-review/references/privacy-manifest.md +90 -90
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/app-store-review/references/review-checklists.md +106 -106
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/SKILL.md +500 -500
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/references/coreml-conversion.md +425 -425
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/references/coreml-optimization.md +344 -344
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/references/foundation-models.md +508 -508
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/apple-on-device-ai/references/mlx-swift.md +285 -285
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/authentication/SKILL.md +496 -496
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/authentication/references/keychain-biometric.md +211 -211
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/background-processing/SKILL.md +499 -499
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/background-processing/references/background-task-patterns.md +390 -390
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/callkit-voip/SKILL.md +461 -461
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/callkit-voip/references/callkit-patterns.md +425 -425
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/cloudkit-sync/SKILL.md +492 -492
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/cloudkit-sync/references/cloudkit-patterns.md +461 -461
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/codable-patterns/SKILL.md +467 -467
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/contacts-framework/SKILL.md +425 -425
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/contacts-framework/references/contacts-patterns.md +409 -409
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-bluetooth/SKILL.md +491 -491
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-bluetooth/references/ble-patterns.md +435 -435
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-motion/SKILL.md +388 -388
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-motion/references/motion-patterns.md +405 -405
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-nfc/SKILL.md +495 -495
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/core-nfc/references/nfc-patterns.md +420 -420
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/coreml/SKILL.md +459 -459
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/coreml/references/coreml-swift-integration.md +765 -765
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/debugging-instruments/SKILL.md +422 -422
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/debugging-instruments/references/instruments-guide.md +387 -387
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/debugging-instruments/references/lldb-patterns.md +298 -298
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/device-integrity/SKILL.md +477 -477
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/energykit/SKILL.md +460 -460
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/energykit/references/energykit-patterns.md +541 -541
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/eventkit-calendar/SKILL.md +483 -483
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/eventkit-calendar/references/eventkit-patterns.md +326 -326
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/healthkit/SKILL.md +498 -498
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/healthkit/references/healthkit-patterns.md +602 -602
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/homekit-matter/SKILL.md +496 -496
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/homekit-matter/references/matter-commissioning.md +455 -455
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-accessibility/SKILL.md +301 -301
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-accessibility/references/a11y-patterns.md +140 -140
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-localization/SKILL.md +418 -418
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-localization/references/formatstyle-locale.md +627 -627
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-localization/references/string-catalogs.md +462 -462
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/SKILL.md +441 -441
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/references/background-websocket.md +862 -862
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/references/lightweight-clients.md +93 -93
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/references/network-framework.md +563 -563
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-networking/references/urlsession-patterns.md +1116 -1116
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/SKILL.md +496 -496
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/references/app-review-guidelines.md +174 -174
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/references/cryptokit-advanced.md +296 -296
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/references/file-storage-patterns.md +354 -354
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/ios-security/references/privacy-manifest.md +117 -117
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/live-activities/SKILL.md +500 -500
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/live-activities/references/live-activity-patterns.md +868 -868
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/mapkit-location/SKILL.md +485 -485
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/mapkit-location/references/corelocation-patterns.md +730 -730
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/mapkit-location/references/mapkit-patterns.md +748 -748
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/metrickit-diagnostics/SKILL.md +479 -479
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/musickit-audio/SKILL.md +395 -395
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/musickit-audio/references/musickit-patterns.md +363 -363
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/natural-language/SKILL.md +412 -412
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/natural-language/references/translation-patterns.md +311 -311
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/passkit-wallet/SKILL.md +398 -398
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/passkit-wallet/references/wallet-passes.md +254 -254
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/pencilkit-drawing/SKILL.md +387 -387
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/pencilkit-drawing/references/paperkit-integration.md +376 -376
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/pencilkit-drawing/references/pencilkit-patterns.md +302 -302
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/permissionkit/SKILL.md +446 -446
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/permissionkit/references/permissionkit-patterns.md +435 -435
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/SKILL.md +500 -500
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/references/av-playback.md +701 -701
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/references/camera-capture.md +774 -774
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/references/image-loading-caching.md +869 -869
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/photos-camera-media/references/photospicker-patterns.md +597 -597
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/push-notifications/SKILL.md +500 -500
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/push-notifications/references/notification-patterns.md +677 -677
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/push-notifications/references/rich-notifications.md +745 -745
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/realitykit-ar/SKILL.md +479 -479
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/realitykit-ar/references/realitykit-patterns.md +480 -480
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/shareplay-activities/SKILL.md +483 -483
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/shareplay-activities/references/shareplay-patterns.md +544 -544
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/speech-recognition/SKILL.md +485 -485
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/storekit/SKILL.md +478 -478
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/storekit/references/app-review-guidelines.md +58 -58
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/storekit/references/storekit-advanced.md +755 -755
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-charts/SKILL.md +487 -487
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-charts/references/charts-patterns.md +895 -895
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/SKILL.md +408 -408
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/references/approachable-concurrency.md +80 -80
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/references/swift-6-2-concurrency.md +233 -233
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/references/swiftui-concurrency.md +187 -187
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-concurrency/references/synchronization-primitives.md +341 -341
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-language/SKILL.md +498 -498
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-language/references/swift-patterns-extended.md +505 -505
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-testing/SKILL.md +467 -467
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swift-testing/references/testing-patterns.md +504 -504
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftdata/SKILL.md +334 -334
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftdata/references/core-data-coexistence.md +504 -504
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftdata/references/swiftdata-advanced.md +975 -975
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftdata/references/swiftdata-queries.md +675 -675
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-animation/SKILL.md +481 -481
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-animation/references/animation-advanced.md +804 -804
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-animation/references/core-animation-bridge.md +553 -553
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-gestures/SKILL.md +450 -450
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-gestures/references/gesture-patterns.md +425 -425
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/SKILL.md +336 -336
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/references/form.md +97 -97
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/references/grids.md +69 -69
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/references/list.md +99 -99
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-layout-components/references/scrollview.md +147 -147
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-liquid-glass/SKILL.md +325 -325
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-liquid-glass/references/liquid-glass.md +387 -387
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/SKILL.md +262 -262
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/references/deeplinks.md +207 -207
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/references/navigationstack.md +177 -177
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/references/sheets.md +169 -169
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-navigation/references/tabview.md +178 -178
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/SKILL.md +381 -381
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/references/architecture-patterns.md +486 -486
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/references/deprecated-migration.md +1097 -1097
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/references/design-polish.md +780 -780
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-patterns/references/platform-and-sharing.md +696 -696
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/SKILL.md +491 -491
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +46 -46
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +29 -29
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/references/understanding-hangs-in-your-app.md +33 -33
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-performance/references/understanding-improving-swiftui-performance.md +52 -52
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-uikit-interop/SKILL.md +428 -428
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-uikit-interop/references/hosting-migration.md +534 -534
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/swiftui-uikit-interop/references/representable-recipes.md +1133 -1133
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/tipkit/SKILL.md +494 -494
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/tipkit/references/tipkit-patterns.md +782 -782
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/vision-framework/SKILL.md +475 -475
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/vision-framework/references/vision-requests.md +736 -736
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/vision-framework/references/visionkit-scanner.md +738 -738
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/weatherkit/SKILL.md +410 -410
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/weatherkit/references/weatherkit-patterns.md +567 -567
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/widgetkit/SKILL.md +497 -497
- package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/widgetkit/references/widgetkit-advanced.md +871 -871
- package/src/.agents/skills/ui-ux-pro-custom/data/typography.csv +57 -57
- package/src/.agents/skills/ui-ux-pro-custom/data/ui-reasoning.csv +101 -101
- package/src/.agents/skills/ui-ux-pro-custom/data/ux-guidelines.csv +99 -99
- package/src/.agents/skills/ui-ux-pro-custom/data/web-interface.csv +31 -31
- package/src/.agents/skills/ui-ux-pro-custom/scripts/core.py +253 -253
- package/src/.agents/skills/ui-ux-pro-custom/scripts/design_system.py +1067 -1067
- package/src/.agents/skills/ui-ux-pro-custom/scripts/search.py +114 -114
- package/src/.agents/skills/ux-audit/SKILL.md +150 -150
- package/src/.agents/skills/websocket-engineer/SKILL.md +168 -168
- package/src/.agents/skills/websocket-engineer/references/alternatives.md +391 -391
- package/src/.agents/skills/websocket-engineer/references/patterns.md +400 -400
- package/src/.agents/skills/websocket-engineer/references/protocol.md +195 -195
- package/src/.agents/skills/websocket-engineer/references/scaling.md +333 -333
- package/src/.agents/skills/websocket-engineer/references/security.md +474 -474
- package/src/.agents/skills/writing-skills/SKILL.md +655 -655
- package/src/.agents/skills/writing-skills/anthropic-best-practices.md +1150 -1150
- package/src/.agents/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -189
- package/src/.agents/skills/writing-skills/graphviz-conventions.dot +171 -171
- package/src/.agents/skills/writing-skills/persuasion-principles.md +187 -187
- package/src/.agents/skills/writing-skills/render-graphs.js +168 -168
- package/src/.agents/skills/writing-skills/testing-skills-with-subagents.md +384 -384
- package/src/.claude/commands/bmad-track-compact.md +1 -1
- package/src/.claude/commands/bmad-track-extended.md +1 -1
- package/src/.claude/commands/bmad-track-large.md +1 -1
- package/src/.claude/commands/bmad-track-medium.md +1 -1
- package/src/.claude/commands/bmad-track-nano.md +1 -1
- package/src/.claude/commands/bmad-track-rv.md +1 -1
- package/src/.claude/commands/bmad-track-small.md +1 -1
- package/src/.claude/commands/master-orchestrator.md +15 -0
- package/src/_memory/config.yaml +11 -11
- package/src/_memory/master-orchestrator-sidecar/instructions.md +85 -32
- package/src/_memory/skills/nimbalyst-tracking/SKILL.md +103 -103
- package/src/_memory/skills/writing-skills/SKILL.md +655 -655
- package/src/bmb/agents/agent-builder.md +59 -59
- package/src/bmb/agents/module-builder.md +60 -60
- package/src/bmb/agents/workflow-builder.md +61 -61
- package/src/bmb/config.yaml +12 -12
- package/src/bmb/module-help.csv +13 -13
- package/src/bmb/workflows/agent/data/agent-architecture.md +258 -258
- package/src/bmb/workflows/agent/data/agent-compilation.md +185 -185
- package/src/bmb/workflows/agent/data/agent-menu-patterns.md +189 -189
- package/src/bmb/workflows/agent/data/agent-metadata.md +133 -133
- package/src/bmb/workflows/agent/data/agent-validation.md +111 -111
- package/src/bmb/workflows/agent/data/brainstorm-context.md +96 -96
- package/src/bmb/workflows/agent/data/communication-presets.csv +61 -61
- package/src/bmb/workflows/agent/data/critical-actions.md +75 -75
- package/src/bmb/workflows/agent/data/persona-properties.md +252 -252
- package/src/bmb/workflows/agent/data/principles-crafting.md +142 -142
- package/src/bmb/workflows/agent/data/reference/module-examples/architect.md +68 -68
- package/src/bmb/workflows/agent/data/reference/with-sidecar/journal-keeper/journal-keeper-sidecar/entries/yy-mm-dd-entry-template.md +16 -16
- package/src/bmb/workflows/agent/data/understanding-agent-types.md +126 -126
- package/src/bmb/workflows/agent/steps-c/step-01-brainstorm.md +129 -129
- package/src/bmb/workflows/agent/steps-c/step-02-discovery.md +170 -170
- package/src/bmb/workflows/agent/steps-c/step-03-sidecar-metadata.md +309 -309
- package/src/bmb/workflows/agent/steps-c/step-04-persona.md +213 -213
- package/src/bmb/workflows/agent/steps-c/step-05-commands-menu.md +179 -179
- package/src/bmb/workflows/agent/steps-c/step-06-activation.md +278 -278
- package/src/bmb/workflows/agent/steps-c/step-07-build-agent.md +316 -316
- package/src/bmb/workflows/agent/steps-c/step-08-celebrate.md +247 -247
- package/src/bmb/workflows/agent/steps-e/e-01-load-existing.md +221 -221
- package/src/bmb/workflows/agent/steps-e/e-02-discover-edits.md +195 -195
- package/src/bmb/workflows/agent/steps-e/e-04-sidecar-metadata.md +126 -126
- package/src/bmb/workflows/agent/steps-e/e-05-persona.md +135 -135
- package/src/bmb/workflows/agent/steps-e/e-06-commands-menu.md +123 -123
- package/src/bmb/workflows/agent/steps-e/e-07-activation.md +124 -124
- package/src/bmb/workflows/agent/steps-e/e-08-edit-agent.md +197 -197
- package/src/bmb/workflows/agent/steps-e/e-09-celebrate.md +155 -155
- package/src/bmb/workflows/agent/steps-v/v-01-load-review.md +137 -137
- package/src/bmb/workflows/agent/steps-v/v-02a-validate-metadata.md +116 -116
- package/src/bmb/workflows/agent/steps-v/v-02b-validate-persona.md +124 -124
- package/src/bmb/workflows/agent/steps-v/v-02c-validate-menu.md +127 -127
- package/src/bmb/workflows/agent/steps-v/v-02d-validate-structure.md +134 -134
- package/src/bmb/workflows/agent/steps-v/v-02e-validate-sidecar.md +134 -134
- package/src/bmb/workflows/agent/steps-v/v-03-summary.md +104 -104
- package/src/bmb/workflows/agent/templates/agent-plan.template.md +5 -5
- package/src/bmb/workflows/agent/templates/agent-template.md +89 -89
- package/src/bmb/workflows/agent/workflow-create-agent.md +72 -72
- package/src/bmb/workflows/agent/workflow-edit-agent.md +75 -75
- package/src/bmb/workflows/agent/workflow-validate-agent.md +73 -73
- package/src/bmb/workflows/module/data/agent-architecture.md +179 -179
- package/src/bmb/workflows/module/data/agent-spec-template.md +79 -79
- package/src/bmb/workflows/module/data/module-standards.md +263 -263
- package/src/bmb/workflows/module/data/module-yaml-conventions.md +392 -392
- package/src/bmb/workflows/module/module-help-generate.md +254 -254
- package/src/bmb/workflows/module/steps-b/step-01-welcome.md +148 -148
- package/src/bmb/workflows/module/steps-b/step-02-spark.md +141 -141
- package/src/bmb/workflows/module/steps-b/step-03-module-type.md +149 -149
- package/src/bmb/workflows/module/steps-b/step-04-vision.md +83 -83
- package/src/bmb/workflows/module/steps-b/step-05-identity.md +97 -97
- package/src/bmb/workflows/module/steps-b/step-06-users.md +86 -86
- package/src/bmb/workflows/module/steps-b/step-07-value.md +76 -76
- package/src/bmb/workflows/module/steps-b/step-08-agents.md +97 -97
- package/src/bmb/workflows/module/steps-b/step-09-workflows.md +83 -83
- package/src/bmb/workflows/module/steps-b/step-10-tools.md +91 -91
- package/src/bmb/workflows/module/steps-b/step-11-scenarios.md +84 -84
- package/src/bmb/workflows/module/steps-b/step-12-creative.md +95 -95
- package/src/bmb/workflows/module/steps-b/step-13-review.md +105 -105
- package/src/bmb/workflows/module/steps-b/step-14-finalize.md +117 -117
- package/src/bmb/workflows/module/steps-c/step-01-load-brief.md +179 -179
- package/src/bmb/workflows/module/steps-c/step-01b-continue.md +82 -82
- package/src/bmb/workflows/module/steps-c/step-02-structure.md +105 -105
- package/src/bmb/workflows/module/steps-c/step-03-config.md +119 -119
- package/src/bmb/workflows/module/steps-c/step-04-agents.md +168 -168
- package/src/bmb/workflows/module/steps-c/step-05-workflows.md +184 -184
- package/src/bmb/workflows/module/steps-c/step-06-docs.md +401 -401
- package/src/bmb/workflows/module/steps-c/step-07-complete.md +152 -152
- package/src/bmb/workflows/module/steps-e/step-01-load-target.md +81 -81
- package/src/bmb/workflows/module/steps-e/step-02-select-edit.md +77 -77
- package/src/bmb/workflows/module/steps-e/step-03-apply-edit.md +77 -77
- package/src/bmb/workflows/module/steps-e/step-04-review.md +80 -80
- package/src/bmb/workflows/module/steps-e/step-05-confirm.md +75 -75
- package/src/bmb/workflows/module/steps-v/step-01-load-target.md +96 -96
- package/src/bmb/workflows/module/steps-v/step-02-file-structure.md +93 -93
- package/src/bmb/workflows/module/steps-v/step-03-module-yaml.md +99 -99
- package/src/bmb/workflows/module/steps-v/step-04-agent-specs.md +152 -152
- package/src/bmb/workflows/module/steps-v/step-05-workflow-specs.md +152 -152
- package/src/bmb/workflows/module/steps-v/step-06-documentation.md +143 -143
- package/src/bmb/workflows/module/steps-v/step-07-installation.md +102 -102
- package/src/bmb/workflows/module/steps-v/step-08-report.md +197 -197
- package/src/bmb/workflows/module/templates/brief-template.md +154 -154
- package/src/bmb/workflows/module/templates/workflow-spec-template.md +96 -96
- package/src/bmb/workflows/module/workflow-create-module-brief.md +71 -71
- package/src/bmb/workflows/module/workflow-create-module.md +86 -86
- package/src/bmb/workflows/module/workflow-edit-module.md +66 -66
- package/src/bmb/workflows/module/workflow-validate-module.md +66 -66
- package/src/bmb/workflows/workflow/data/architecture.md +150 -150
- package/src/bmb/workflows/workflow/data/common-workflow-tools.csv +19 -19
- package/src/bmb/workflows/workflow/data/csv-data-file-standards.md +53 -53
- package/src/bmb/workflows/workflow/data/frontmatter-standards.md +184 -184
- package/src/bmb/workflows/workflow/data/input-discovery-standards.md +191 -191
- package/src/bmb/workflows/workflow/data/intent-vs-prescriptive-spectrum.md +44 -44
- package/src/bmb/workflows/workflow/data/menu-handling-standards.md +133 -133
- package/src/bmb/workflows/workflow/data/output-format-standards.md +135 -135
- package/src/bmb/workflows/workflow/data/step-file-rules.md +235 -235
- package/src/bmb/workflows/workflow/data/step-type-patterns.md +257 -257
- package/src/bmb/workflows/workflow/data/subprocess-optimization-patterns.md +188 -188
- package/src/bmb/workflows/workflow/data/trimodal-workflow-structure.md +164 -164
- package/src/bmb/workflows/workflow/data/workflow-chaining-standards.md +222 -222
- package/src/bmb/workflows/workflow/data/workflow-examples.md +232 -232
- package/src/bmb/workflows/workflow/data/workflow-type-criteria.md +134 -134
- package/src/bmb/workflows/workflow/steps-c/step-00-conversion.md +263 -263
- package/src/bmb/workflows/workflow/steps-c/step-01-discovery.md +194 -194
- package/src/bmb/workflows/workflow/steps-c/step-01b-continuation.md +3 -3
- package/src/bmb/workflows/workflow/steps-c/step-02-classification.md +270 -270
- package/src/bmb/workflows/workflow/steps-c/step-03-requirements.md +283 -283
- package/src/bmb/workflows/workflow/steps-c/step-04-tools.md +282 -282
- package/src/bmb/workflows/workflow/steps-c/step-05-plan-review.md +243 -243
- package/src/bmb/workflows/workflow/steps-c/step-06-design.md +330 -330
- package/src/bmb/workflows/workflow/steps-c/step-07-foundation.md +239 -239
- package/src/bmb/workflows/workflow/steps-c/step-08-build-step-01.md +379 -379
- package/src/bmb/workflows/workflow/steps-c/step-09-build-next-step.md +350 -350
- package/src/bmb/workflows/workflow/steps-c/step-10-confirmation.md +322 -322
- package/src/bmb/workflows/workflow/steps-c/step-11-completion.md +191 -191
- package/src/bmb/workflows/workflow/steps-e/step-e-01-assess-workflow.md +237 -237
- package/src/bmb/workflows/workflow/steps-e/step-e-02-discover-edits.md +251 -251
- package/src/bmb/workflows/workflow/steps-e/step-e-03-fix-validation.md +254 -254
- package/src/bmb/workflows/workflow/steps-e/step-e-04-direct-edit.md +277 -277
- package/src/bmb/workflows/workflow/steps-e/step-e-05-apply-edit.md +154 -154
- package/src/bmb/workflows/workflow/steps-e/step-e-06-validate-after.md +190 -190
- package/src/bmb/workflows/workflow/steps-e/step-e-07-complete.md +206 -206
- package/src/bmb/workflows/workflow/steps-v/step-01-validate-max-mode.md +109 -109
- package/src/bmb/workflows/workflow/steps-v/step-01-validate.md +221 -221
- package/src/bmb/workflows/workflow/steps-v/step-01b-structure.md +152 -152
- package/src/bmb/workflows/workflow/steps-v/step-02-frontmatter-validation.md +199 -199
- package/src/bmb/workflows/workflow/steps-v/step-02b-path-violations.md +265 -265
- package/src/bmb/workflows/workflow/steps-v/step-03-menu-validation.md +164 -164
- package/src/bmb/workflows/workflow/steps-v/step-04-step-type-validation.md +211 -211
- package/src/bmb/workflows/workflow/steps-v/step-05-output-format-validation.md +200 -200
- package/src/bmb/workflows/workflow/steps-v/step-06-validation-design-check.md +195 -195
- package/src/bmb/workflows/workflow/steps-v/step-07-instruction-style-check.md +209 -209
- package/src/bmb/workflows/workflow/steps-v/step-08-collaborative-experience-check.md +199 -199
- package/src/bmb/workflows/workflow/steps-v/step-08b-subprocess-optimization.md +179 -179
- package/src/bmb/workflows/workflow/steps-v/step-09-cohesive-review.md +186 -186
- package/src/bmb/workflows/workflow/steps-v/step-10-report-complete.md +154 -154
- package/src/bmb/workflows/workflow/steps-v/step-11-plan-validation.md +237 -237
- package/src/bmb/workflows/workflow/templates/minimal-output-template.md +11 -11
- package/src/bmb/workflows/workflow/templates/step-01-init-continuable-template.md +241 -241
- package/src/bmb/workflows/workflow/templates/step-1b-template.md +224 -224
- package/src/bmb/workflows/workflow/templates/step-template.md +294 -294
- package/src/bmb/workflows/workflow/templates/workflow-template.md +102 -102
- package/src/bmb/workflows/workflow/workflow-create-workflow.md +79 -79
- package/src/bmb/workflows/workflow/workflow-edit-workflow.md +65 -65
- package/src/bmb/workflows/workflow/workflow-rework-workflow.md +65 -65
- package/src/bmb/workflows/workflow/workflow-validate-max-parallel-workflow.md +66 -66
- package/src/bmb/workflows/workflow/workflow-validate-workflow.md +65 -65
- package/src/bmm/agents/analyst.md +104 -104
- package/src/bmm/agents/dev.md +100 -100
- package/src/bmm/agents/qa.md +100 -90
- package/src/bmm/agents/review-agent.md +1 -1
- package/src/bmm/agents/tech-writer/tech-writer.md +94 -94
- package/src/bmm/module-help.csv +31 -31
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01-init.md +115 -115
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-01b-continue.md +107 -107
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md +141 -141
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md +144 -144
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md +147 -147
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md +161 -161
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-06-complete.md +99 -99
- package/src/bmm/workflows/1-analysis/create-product-brief/workflow.md +57 -57
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-01-init.md +87 -87
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md +156 -156
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md +165 -165
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md +140 -140
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md +152 -152
- package/src/bmm/workflows/1-analysis/research/domain-steps/step-06-research-synthesis.md +345 -345
- package/src/bmm/workflows/1-analysis/research/market-steps/step-01-init.md +92 -92
- package/src/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md +164 -164
- package/src/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md +174 -174
- package/src/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md +184 -184
- package/src/bmm/workflows/1-analysis/research/market-steps/step-05-competitive-analysis.md +105 -105
- package/src/bmm/workflows/1-analysis/research/market-steps/step-06-research-completion.md +360 -360
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-01-init.md +87 -87
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-02-technical-overview.md +165 -165
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-03-integration-patterns.md +174 -174
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-04-architectural-patterns.md +141 -141
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-05-implementation-research.md +159 -159
- package/src/bmm/workflows/1-analysis/research/technical-steps/step-06-research-synthesis.md +387 -387
- package/src/bmm/workflows/1-analysis/research/workflow-domain-research.md +54 -54
- package/src/bmm/workflows/1-analysis/research/workflow-market-research.md +54 -54
- package/src/bmm/workflows/1-analysis/research/workflow-technical-research.md +54 -54
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-01b-continue.md +100 -100
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02-discovery.md +160 -160
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02b-vision.md +88 -88
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02c-executive-summary.md +99 -99
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md +169 -169
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md +156 -156
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md +136 -136
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md +176 -176
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md +184 -184
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md +174 -174
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md +175 -175
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md +189 -189
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md +162 -162
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-12-complete.md +79 -79
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-01-discovery.md +183 -183
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-01b-legacy-conversion.md +149 -149
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-02-review.md +187 -187
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-03-edit.md +192 -192
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-04-complete.md +108 -108
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md +166 -166
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-02-format-detection.md +131 -131
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-02b-parity-check.md +150 -150
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-03-density-validation.md +118 -118
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-04-brief-coverage-validation.md +155 -155
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-05-measurability-validation.md +170 -170
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-06-traceability-validation.md +158 -158
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-07-implementation-leakage-validation.md +147 -147
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-08-domain-compliance-validation.md +182 -182
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-09-project-type-validation.md +202 -202
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-10-smart-validation.md +148 -148
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-11-holistic-quality-validation.md +201 -201
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-12-completeness-validation.md +179 -179
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-13-report-complete.md +164 -164
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-create-prd.md +65 -65
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-edit-prd.md +65 -65
- package/src/bmm/workflows/2-plan-workflows/create-prd/workflow-validate-prd.md +63 -63
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01b-continue.md +63 -63
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md +106 -106
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md +111 -111
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md +115 -115
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md +127 -127
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md +167 -167
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md +143 -143
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md +118 -118
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md +154 -154
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md +136 -136
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md +165 -165
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md +135 -135
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md +192 -192
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-14-complete.md +101 -101
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md +45 -45
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-01-document-discovery.md +185 -185
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-02-prd-analysis.md +129 -129
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-03-epic-coverage-validation.md +130 -130
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-04-ux-alignment.md +93 -93
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-05-epic-quality-review.md +196 -196
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-06-final-assessment.md +129 -129
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md +54 -54
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-01b-continue.md +82 -82
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md +106 -106
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md +138 -138
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md +129 -129
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md +166 -166
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md +186 -186
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md +163 -163
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-08-complete.md +38 -38
- package/src/bmm/workflows/3-solutioning/create-architecture/workflow.md +49 -49
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md +124 -124
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md +122 -122
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md +84 -84
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md +58 -58
- package/src/bmm/workflows/4-implementation/code-review/workflow.yaml +43 -43
- package/src/bmm/workflows/4-implementation/correct-course/workflow.yaml +53 -53
- package/src/bmm/workflows/4-implementation/create-story/checklist.md +159 -159
- package/src/bmm/workflows/4-implementation/create-story/template.md +79 -79
- package/src/bmm/workflows/4-implementation/create-story/workflow.yaml +52 -52
- package/src/bmm/workflows/4-implementation/dev-story/workflow.yaml +20 -20
- package/src/bmm/workflows/4-implementation/retrospective/workflow.yaml +52 -52
- package/src/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +52 -52
- package/src/bmm/workflows/4-implementation/sprint-status/workflow.yaml +25 -25
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-01-mode-detection.md +158 -158
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-02-context-gathering.md +122 -122
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-03-execute.md +93 -93
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-04-self-check.md +93 -93
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md +87 -87
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-06-resolve-findings.md +146 -146
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md +50 -50
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-02-investigate.md +152 -152
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-03-generate.md +123 -123
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md +201 -201
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md +79 -79
- package/src/bmm/workflows/document-project/workflow.yaml +22 -22
- package/src/bmm/workflows/generate-project-context/steps/step-01-discover.md +184 -184
- package/src/bmm/workflows/generate-project-context/steps/step-02-generate.md +322 -322
- package/src/bmm/workflows/generate-project-context/steps/step-03-complete.md +235 -235
- package/src/bmm/workflows/generate-project-context/workflow.md +49 -49
- package/src/bmm/workflows/qa/automate/workflow.yaml +233 -233
- package/src/bmm/workflows/qa-generate-e2e-tests/workflow.yaml +42 -42
- package/src/core/agents/master-orchestrator.md +3 -3
- package/src/core/config.yaml +9 -9
- package/src/core/module-help.csv +10 -10
- package/src/core/scripts/generate-loop-report.py +72 -72
- package/src/core/tasks/editorial-review-prose.xml +101 -101
- package/src/core/tasks/editorial-review-structure.xml +207 -207
- package/src/core/tasks/help.md +86 -86
- package/src/core/tasks/index-docs.xml +64 -64
- package/src/core/tasks/review-adversarial-general.xml +66 -66
- package/src/core/tasks/review-adversarial-loop.xml +46 -46
- package/src/core/tasks/review-edge-case-hunter.xml +63 -63
- package/src/core/tasks/review-party-loop.xml +46 -46
- package/src/core/tasks/shard-doc.xml +107 -107
- package/src/core/tasks/workflow.xml +235 -235
- package/src/core/templates/review-loop-report.html +88 -88
- package/src/core/templates/review-loop-report.md +5 -5
- package/src/core/workflows/advanced-elicitation/workflow.xml +117 -117
- package/src/core/workflows/brainstorming/steps/step-01-session-setup.md +212 -212
- package/src/core/workflows/brainstorming/steps/step-01b-continue.md +122 -122
- package/src/core/workflows/brainstorming/steps/step-02a-user-selected.md +225 -225
- package/src/core/workflows/brainstorming/steps/step-02b-ai-recommended.md +237 -237
- package/src/core/workflows/brainstorming/steps/step-02c-random-selection.md +209 -209
- package/src/core/workflows/brainstorming/steps/step-02d-progressive-flow.md +264 -264
- package/src/core/workflows/brainstorming/steps/step-02e-deep-dive.md +68 -68
- package/src/core/workflows/brainstorming/steps/step-03-technique-execution.md +403 -403
- package/src/core/workflows/brainstorming/steps/step-04-idea-organization.md +303 -303
- package/src/core/workflows/brainstorming/workflow.md +60 -60
- package/src/core/workflows/extract-trackers/workflow.md +45 -45
- package/src/core/workflows/party-mode/steps/step-01-agent-loading.md +142 -142
- package/src/core/workflows/party-mode/workflow.md +194 -194
- package/src/docs/dev/tmux/actions_popup.py +291 -291
- package/src/docs/dev/tmux/tmux-setup.md +62 -1
package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/speech-recognition/SKILL.md
CHANGED
|
@@ -1,485 +1,485 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: speech-recognition
|
|
3
|
-
description: "Transcribe speech to text using the Speech framework. Use when implementing live microphone transcription with AVAudioEngine, recognizing pre-recorded audio files, configuring on-device vs server-based recognition, handling authorization flows, or adopting the new SpeechAnalyzer API (iOS 26+) for modern async/await speech-to-text."
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Speech Recognition
|
|
7
|
-
|
|
8
|
-
Transcribe live and pre-recorded audio to text using Apple's Speech framework.
|
|
9
|
-
Covers `SFSpeechRecognizer` (iOS 10+) and the new `SpeechAnalyzer` API (iOS 26+).
|
|
10
|
-
|
|
11
|
-
## Contents
|
|
12
|
-
|
|
13
|
-
- [SpeechAnalyzer (iOS 26+)](#speechanalyzer-ios-26)
|
|
14
|
-
- [SFSpeechRecognizer Setup](#sfspeechrecognizer-setup)
|
|
15
|
-
- [Authorization](#authorization)
|
|
16
|
-
- [Live Microphone Transcription](#live-microphone-transcription)
|
|
17
|
-
- [Pre-Recorded Audio File Recognition](#pre-recorded-audio-file-recognition)
|
|
18
|
-
- [On-Device vs Server Recognition](#on-device-vs-server-recognition)
|
|
19
|
-
- [Handling Results](#handling-results)
|
|
20
|
-
- [Common Mistakes](#common-mistakes)
|
|
21
|
-
- [Review Checklist](#review-checklist)
|
|
22
|
-
- [References](#references)
|
|
23
|
-
|
|
24
|
-
## SpeechAnalyzer (iOS 26+)
|
|
25
|
-
|
|
26
|
-
`SpeechAnalyzer` is an actor-based API introduced in iOS 26 that replaces
|
|
27
|
-
`SFSpeechRecognizer` for new projects. It uses Swift concurrency, `AsyncSequence`
|
|
28
|
-
for results, and supports modular analysis via `SpeechTranscriber`.
|
|
29
|
-
|
|
30
|
-
### Basic transcription with SpeechAnalyzer
|
|
31
|
-
|
|
32
|
-
```swift
|
|
33
|
-
import Speech
|
|
34
|
-
|
|
35
|
-
// 1. Create a transcriber module
|
|
36
|
-
guard let locale = SpeechTranscriber.supportedLocale(
|
|
37
|
-
equivalentTo: Locale.current
|
|
38
|
-
) else { return }
|
|
39
|
-
let transcriber = SpeechTranscriber(locale: locale, preset: .offlineTranscription)
|
|
40
|
-
|
|
41
|
-
// 2. Ensure assets are installed
|
|
42
|
-
if let request = try await AssetInventory.assetInstallationRequest(
|
|
43
|
-
supporting: [transcriber]
|
|
44
|
-
) {
|
|
45
|
-
try await request.downloadAndInstall()
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// 3. Create input stream and analyzer
|
|
49
|
-
let (inputSequence, inputBuilder) = AsyncStream.makeStream(of: AnalyzerInput.self)
|
|
50
|
-
let audioFormat = await SpeechAnalyzer.bestAvailableAudioFormat(
|
|
51
|
-
compatibleWith: [transcriber]
|
|
52
|
-
)
|
|
53
|
-
let analyzer = SpeechAnalyzer(modules: [transcriber])
|
|
54
|
-
|
|
55
|
-
// 4. Feed audio buffers (from AVAudioEngine or file)
|
|
56
|
-
Task {
|
|
57
|
-
// Append PCM buffers converted to audioFormat
|
|
58
|
-
let pcmBuffer: AVAudioPCMBuffer = // ... your audio buffer
|
|
59
|
-
inputBuilder.yield(AnalyzerInput(buffer: pcmBuffer))
|
|
60
|
-
inputBuilder.finish()
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// 5. Consume results
|
|
64
|
-
Task {
|
|
65
|
-
for try await result in transcriber.results {
|
|
66
|
-
let text = String(result.text.characters)
|
|
67
|
-
print(text)
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// 6. Run analysis
|
|
72
|
-
let lastSampleTime = try await analyzer.analyzeSequence(inputSequence)
|
|
73
|
-
|
|
74
|
-
// 7. Finalize
|
|
75
|
-
if let lastSampleTime {
|
|
76
|
-
try await analyzer.finalizeAndFinish(through: lastSampleTime)
|
|
77
|
-
} else {
|
|
78
|
-
try analyzer.cancelAndFinishNow()
|
|
79
|
-
}
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### Transcribing an audio file with SpeechAnalyzer
|
|
83
|
-
|
|
84
|
-
```swift
|
|
85
|
-
let transcriber = SpeechTranscriber(locale: locale, preset: .offlineTranscription)
|
|
86
|
-
let audioFile = try AVAudioFile(forReading: fileURL)
|
|
87
|
-
let analyzer = SpeechAnalyzer(
|
|
88
|
-
inputAudioFile: audioFile, modules: [transcriber], finishAfterFile: true
|
|
89
|
-
)
|
|
90
|
-
for try await result in transcriber.results {
|
|
91
|
-
print(String(result.text.characters))
|
|
92
|
-
}
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### Key differences from SFSpeechRecognizer
|
|
96
|
-
|
|
97
|
-
| Feature | SFSpeechRecognizer | SpeechAnalyzer |
|
|
98
|
-
|---|---|---|
|
|
99
|
-
| Concurrency | Callbacks/delegates | async/await + AsyncSequence |
|
|
100
|
-
| Type | `class` | `actor` |
|
|
101
|
-
| Modules | Monolithic | Composable (`SpeechTranscriber`, `SpeechDetector`) |
|
|
102
|
-
| Audio input | `append(_:)` on request | `AsyncStream<AnalyzerInput>` |
|
|
103
|
-
| Availability | iOS 10+ | iOS 26+ |
|
|
104
|
-
| On-device | `requiresOnDeviceRecognition` | Asset-based via `AssetInventory` |
|
|
105
|
-
|
|
106
|
-
## SFSpeechRecognizer Setup
|
|
107
|
-
|
|
108
|
-
### Creating a recognizer with locale
|
|
109
|
-
|
|
110
|
-
```swift
|
|
111
|
-
import Speech
|
|
112
|
-
|
|
113
|
-
// Default locale (user's current language)
|
|
114
|
-
let recognizer = SFSpeechRecognizer()
|
|
115
|
-
|
|
116
|
-
// Specific locale
|
|
117
|
-
let recognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))
|
|
118
|
-
|
|
119
|
-
// Check if recognition is available for this locale
|
|
120
|
-
guard let recognizer, recognizer.isAvailable else {
|
|
121
|
-
print("Speech recognition not available")
|
|
122
|
-
return
|
|
123
|
-
}
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### Monitoring availability changes
|
|
127
|
-
|
|
128
|
-
```swift
|
|
129
|
-
final class SpeechManager: NSObject, SFSpeechRecognizerDelegate {
|
|
130
|
-
private let recognizer = SFSpeechRecognizer()!
|
|
131
|
-
|
|
132
|
-
override init() {
|
|
133
|
-
super.init()
|
|
134
|
-
recognizer.delegate = self
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
func speechRecognizer(
|
|
138
|
-
_ speechRecognizer: SFSpeechRecognizer,
|
|
139
|
-
availabilityDidChange available: Bool
|
|
140
|
-
) {
|
|
141
|
-
// Update UI — disable record button when unavailable
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
## Authorization
|
|
147
|
-
|
|
148
|
-
Request **both** speech recognition and microphone permissions before starting
|
|
149
|
-
live transcription. Add these keys to `Info.plist`:
|
|
150
|
-
|
|
151
|
-
- `NSSpeechRecognitionUsageDescription`
|
|
152
|
-
- `NSMicrophoneUsageDescription`
|
|
153
|
-
|
|
154
|
-
```swift
|
|
155
|
-
import Speech
|
|
156
|
-
import AVFoundation
|
|
157
|
-
|
|
158
|
-
func requestPermissions() async -> Bool {
|
|
159
|
-
let speechStatus = await withCheckedContinuation { continuation in
|
|
160
|
-
SFSpeechRecognizer.requestAuthorization { status in
|
|
161
|
-
continuation.resume(returning: status)
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
guard speechStatus == .authorized else { return false }
|
|
165
|
-
|
|
166
|
-
let micStatus: Bool
|
|
167
|
-
if #available(iOS 17, *) {
|
|
168
|
-
micStatus = await AVAudioApplication.requestRecordPermission()
|
|
169
|
-
} else {
|
|
170
|
-
micStatus = await withCheckedContinuation { continuation in
|
|
171
|
-
AVAudioSession.sharedInstance().requestRecordPermission { granted in
|
|
172
|
-
continuation.resume(returning: granted)
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
return micStatus
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
## Live Microphone Transcription
|
|
181
|
-
|
|
182
|
-
The standard pattern: `AVAudioEngine` captures microphone audio → buffers are
|
|
183
|
-
appended to `SFSpeechAudioBufferRecognitionRequest` → results stream in.
|
|
184
|
-
|
|
185
|
-
```swift
|
|
186
|
-
import Speech
|
|
187
|
-
import AVFoundation
|
|
188
|
-
|
|
189
|
-
final class LiveTranscriber {
|
|
190
|
-
private let recognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))!
|
|
191
|
-
private let audioEngine = AVAudioEngine()
|
|
192
|
-
private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?
|
|
193
|
-
private var recognitionTask: SFSpeechRecognitionTask?
|
|
194
|
-
|
|
195
|
-
func startTranscribing() throws {
|
|
196
|
-
// Cancel any in-progress task
|
|
197
|
-
recognitionTask?.cancel()
|
|
198
|
-
recognitionTask = nil
|
|
199
|
-
|
|
200
|
-
// Configure audio session
|
|
201
|
-
let audioSession = AVAudioSession.sharedInstance()
|
|
202
|
-
try audioSession.setCategory(.record, mode: .measurement, options: .duckOthers)
|
|
203
|
-
try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
|
|
204
|
-
|
|
205
|
-
// Create request
|
|
206
|
-
let request = SFSpeechAudioBufferRecognitionRequest()
|
|
207
|
-
request.shouldReportPartialResults = true
|
|
208
|
-
self.recognitionRequest = request
|
|
209
|
-
|
|
210
|
-
// Start recognition task
|
|
211
|
-
recognitionTask = recognizer.recognitionTask(with: request) { result, error in
|
|
212
|
-
if let result {
|
|
213
|
-
let text = result.bestTranscription.formattedString
|
|
214
|
-
print("Transcription: \(text)")
|
|
215
|
-
|
|
216
|
-
if result.isFinal {
|
|
217
|
-
self.stopTranscribing()
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
if let error {
|
|
221
|
-
print("Recognition error: \(error)")
|
|
222
|
-
self.stopTranscribing()
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// Install audio tap
|
|
227
|
-
let inputNode = audioEngine.inputNode
|
|
228
|
-
let recordingFormat = inputNode.outputFormat(forBus: 0)
|
|
229
|
-
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) {
|
|
230
|
-
buffer, _ in
|
|
231
|
-
request.append(buffer)
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
audioEngine.prepare()
|
|
235
|
-
try audioEngine.start()
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
func stopTranscribing() {
|
|
239
|
-
audioEngine.stop()
|
|
240
|
-
audioEngine.inputNode.removeTap(onBus: 0)
|
|
241
|
-
recognitionRequest?.endAudio()
|
|
242
|
-
recognitionRequest = nil
|
|
243
|
-
recognitionTask?.cancel()
|
|
244
|
-
recognitionTask = nil
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
## Pre-Recorded Audio File Recognition
|
|
250
|
-
|
|
251
|
-
Use `SFSpeechURLRecognitionRequest` for audio files on disk:
|
|
252
|
-
|
|
253
|
-
```swift
|
|
254
|
-
func transcribeFile(at url: URL) async throws -> String {
|
|
255
|
-
guard let recognizer = SFSpeechRecognizer(), recognizer.isAvailable else {
|
|
256
|
-
throw SpeechError.unavailable
|
|
257
|
-
}
|
|
258
|
-
let request = SFSpeechURLRecognitionRequest(url: url)
|
|
259
|
-
request.shouldReportPartialResults = false
|
|
260
|
-
|
|
261
|
-
return try await withCheckedThrowingContinuation { continuation in
|
|
262
|
-
recognizer.recognitionTask(with: request) { result, error in
|
|
263
|
-
if let error {
|
|
264
|
-
continuation.resume(throwing: error)
|
|
265
|
-
} else if let result, result.isFinal {
|
|
266
|
-
continuation.resume(
|
|
267
|
-
returning: result.bestTranscription.formattedString
|
|
268
|
-
)
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
## On-Device vs Server Recognition
|
|
276
|
-
|
|
277
|
-
On-device recognition (iOS 13+) works offline but supports fewer locales:
|
|
278
|
-
|
|
279
|
-
```swift
|
|
280
|
-
let recognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))!
|
|
281
|
-
|
|
282
|
-
// Check if on-device is supported for this locale
|
|
283
|
-
if recognizer.supportsOnDeviceRecognition {
|
|
284
|
-
let request = SFSpeechAudioBufferRecognitionRequest()
|
|
285
|
-
request.requiresOnDeviceRecognition = true // Force on-device
|
|
286
|
-
}
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
> **Tip:** On-device recognition avoids network latency and the one-minute
|
|
290
|
-
> audio limit imposed by server-based recognition. However, accuracy may be
|
|
291
|
-
> lower and not all locales are supported. Check `supportsOnDeviceRecognition`
|
|
292
|
-
> before forcing on-device mode.
|
|
293
|
-
|
|
294
|
-
## Handling Results
|
|
295
|
-
|
|
296
|
-
### Partial vs final results
|
|
297
|
-
|
|
298
|
-
```swift
|
|
299
|
-
let request = SFSpeechAudioBufferRecognitionRequest()
|
|
300
|
-
request.shouldReportPartialResults = true // default is true
|
|
301
|
-
|
|
302
|
-
recognizer.recognitionTask(with: request) { result, error in
|
|
303
|
-
guard let result else { return }
|
|
304
|
-
|
|
305
|
-
if result.isFinal {
|
|
306
|
-
// Final transcription — recognition is complete
|
|
307
|
-
let final = result.bestTranscription.formattedString
|
|
308
|
-
} else {
|
|
309
|
-
// Partial result — may change as more audio is processed
|
|
310
|
-
let partial = result.bestTranscription.formattedString
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
### Accessing alternative transcriptions and confidence
|
|
316
|
-
|
|
317
|
-
```swift
|
|
318
|
-
recognizer.recognitionTask(with: request) { result, error in
|
|
319
|
-
guard let result else { return }
|
|
320
|
-
|
|
321
|
-
// Best transcription
|
|
322
|
-
let best = result.bestTranscription
|
|
323
|
-
|
|
324
|
-
// All alternatives (sorted by confidence, descending)
|
|
325
|
-
for transcription in result.transcriptions {
|
|
326
|
-
for segment in transcription.segments {
|
|
327
|
-
print("\(segment.substring): \(segment.confidence)")
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
### Adding punctuation (iOS 16+)
|
|
334
|
-
|
|
335
|
-
```swift
|
|
336
|
-
let request = SFSpeechAudioBufferRecognitionRequest()
|
|
337
|
-
request.addsPunctuation = true
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
### Contextual strings
|
|
341
|
-
|
|
342
|
-
Improve recognition of domain-specific terms:
|
|
343
|
-
|
|
344
|
-
```swift
|
|
345
|
-
let request = SFSpeechAudioBufferRecognitionRequest()
|
|
346
|
-
request.contextualStrings = ["SwiftUI", "Xcode", "CloudKit"]
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
## Common Mistakes
|
|
350
|
-
|
|
351
|
-
### Not requesting both speech and microphone authorization
|
|
352
|
-
|
|
353
|
-
```swift
|
|
354
|
-
// ❌ DON'T: Only request speech authorization for live audio
|
|
355
|
-
SFSpeechRecognizer.requestAuthorization { status in
|
|
356
|
-
// Missing microphone permission — audio engine will fail
|
|
357
|
-
self.startRecording()
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
// ✅ DO: Request both permissions before recording
|
|
361
|
-
SFSpeechRecognizer.requestAuthorization { status in
|
|
362
|
-
guard status == .authorized else { return }
|
|
363
|
-
AVAudioSession.sharedInstance().requestRecordPermission { granted in
|
|
364
|
-
guard granted else { return }
|
|
365
|
-
self.startRecording()
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
### Not handling availability changes
|
|
371
|
-
|
|
372
|
-
```swift
|
|
373
|
-
// ❌ DON'T: Assume recognizer stays available after initial check
|
|
374
|
-
let recognizer = SFSpeechRecognizer()!
|
|
375
|
-
// Recognition may fail if network drops or locale changes
|
|
376
|
-
|
|
377
|
-
// ✅ DO: Monitor availability via delegate
|
|
378
|
-
recognizer.delegate = self
|
|
379
|
-
func speechRecognizer(
|
|
380
|
-
_ speechRecognizer: SFSpeechRecognizer,
|
|
381
|
-
availabilityDidChange available: Bool
|
|
382
|
-
) {
|
|
383
|
-
recordButton.isEnabled = available
|
|
384
|
-
}
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
### Not stopping the audio engine when recognition ends
|
|
388
|
-
|
|
389
|
-
```swift
|
|
390
|
-
// ❌ DON'T: Leave audio engine running after recognition finishes
|
|
391
|
-
recognizer.recognitionTask(with: request) { result, error in
|
|
392
|
-
if result?.isFinal == true {
|
|
393
|
-
// Audio engine still running, wasting resources and battery
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// ✅ DO: Clean up all audio resources
|
|
398
|
-
recognizer.recognitionTask(with: request) { result, error in
|
|
399
|
-
if result?.isFinal == true || error != nil {
|
|
400
|
-
self.audioEngine.stop()
|
|
401
|
-
self.audioEngine.inputNode.removeTap(onBus: 0)
|
|
402
|
-
self.recognitionRequest?.endAudio()
|
|
403
|
-
self.recognitionRequest = nil
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
### Assuming on-device recognition is available for all locales
|
|
409
|
-
|
|
410
|
-
```swift
|
|
411
|
-
// ❌ DON'T: Force on-device without checking support
|
|
412
|
-
let request = SFSpeechAudioBufferRecognitionRequest()
|
|
413
|
-
request.requiresOnDeviceRecognition = true // May silently fail
|
|
414
|
-
|
|
415
|
-
// ✅ DO: Check support before requiring on-device
|
|
416
|
-
if recognizer.supportsOnDeviceRecognition {
|
|
417
|
-
request.requiresOnDeviceRecognition = true
|
|
418
|
-
} else {
|
|
419
|
-
// Fall back to server-based or inform user
|
|
420
|
-
}
|
|
421
|
-
```
|
|
422
|
-
|
|
423
|
-
### Not handling the one-minute recognition limit
|
|
424
|
-
|
|
425
|
-
```swift
|
|
426
|
-
// ❌ DON'T: Start one long continuous recognition session
|
|
427
|
-
func startRecording() {
|
|
428
|
-
// This will be cut off after ~60 seconds (server-based)
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
// ✅ DO: Restart recognition when approaching the limit
|
|
432
|
-
func startRecording() {
|
|
433
|
-
// Use a timer to restart before the limit
|
|
434
|
-
recognitionTimer = Timer.scheduledTimer(withTimeInterval: 55, repeats: false) {
|
|
435
|
-
[weak self] _ in
|
|
436
|
-
self?.restartRecognition()
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
### Creating multiple simultaneous recognition tasks
|
|
442
|
-
|
|
443
|
-
```swift
|
|
444
|
-
// ❌ DON'T: Start a new task without canceling the previous one
|
|
445
|
-
func startRecording() {
|
|
446
|
-
recognitionTask = recognizer.recognitionTask(with: request) { ... }
|
|
447
|
-
// Previous task is still running — undefined behavior
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
// ✅ DO: Cancel existing task before creating a new one
|
|
451
|
-
func startRecording() {
|
|
452
|
-
recognitionTask?.cancel()
|
|
453
|
-
recognitionTask = nil
|
|
454
|
-
recognitionTask = recognizer.recognitionTask(with: request) { ... }
|
|
455
|
-
}
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
## Review Checklist
|
|
459
|
-
|
|
460
|
-
- [ ] `NSSpeechRecognitionUsageDescription` is in Info.plist
|
|
461
|
-
- [ ] `NSMicrophoneUsageDescription` is in Info.plist (if using live audio)
|
|
462
|
-
- [ ] Authorization is requested before starting recognition
|
|
463
|
-
- [ ] `SFSpeechRecognizerDelegate` is set to handle `availabilityDidChange`
|
|
464
|
-
- [ ] Audio engine is stopped and tap removed when recognition ends
|
|
465
|
-
- [ ] `recognitionRequest.endAudio()` is called when done recording
|
|
466
|
-
- [ ] Previous `recognitionTask` is canceled before starting a new one
|
|
467
|
-
- [ ] `supportsOnDeviceRecognition` is checked before requiring on-device mode
|
|
468
|
-
- [ ] Partial results are handled separately from final (`isFinal`) results
|
|
469
|
-
- [ ] One-minute limit is accounted for in server-based recognition
|
|
470
|
-
- [ ] For iOS 26+: `AssetInventory` assets are installed before using `SpeechAnalyzer`
|
|
471
|
-
- [ ] For iOS 26+: `SpeechTranscriber.supportedLocale(equivalentTo:)` is checked
|
|
472
|
-
|
|
473
|
-
## References
|
|
474
|
-
|
|
475
|
-
- [Speech framework](https://sosumi.ai/documentation/speech)
|
|
476
|
-
- [SpeechAnalyzer](https://sosumi.ai/documentation/speech/speechanalyzer)
|
|
477
|
-
- [SpeechTranscriber](https://sosumi.ai/documentation/speech/speechtranscriber)
|
|
478
|
-
- [SFSpeechRecognizer](https://sosumi.ai/documentation/speech/sfspeechrecognizer)
|
|
479
|
-
- [SFSpeechAudioBufferRecognitionRequest](https://sosumi.ai/documentation/speech/sfspeechaudiobufferrecognitionrequest)
|
|
480
|
-
- [SFSpeechURLRecognitionRequest](https://sosumi.ai/documentation/speech/sfspeechurlrecognitionrequest)
|
|
481
|
-
- [SFSpeechRecognitionResult](https://sosumi.ai/documentation/speech/sfspeechrecognitionresult)
|
|
482
|
-
- [SFSpeechRecognitionRequest](https://sosumi.ai/documentation/speech/sfspeechrecognitionrequest)
|
|
483
|
-
- [AssetInventory](https://sosumi.ai/documentation/speech/assetinventory)
|
|
484
|
-
- [Asking Permission to Use Speech Recognition](https://sosumi.ai/documentation/speech/asking-permission-to-use-speech-recognition)
|
|
485
|
-
- [Recognizing Speech in Live Audio](https://sosumi.ai/documentation/speech/recognizing-speech-in-live-audio)
|
|
1
|
+
---
|
|
2
|
+
name: speech-recognition
|
|
3
|
+
description: "Transcribe speech to text using the Speech framework. Use when implementing live microphone transcription with AVAudioEngine, recognizing pre-recorded audio files, configuring on-device vs server-based recognition, handling authorization flows, or adopting the new SpeechAnalyzer API (iOS 26+) for modern async/await speech-to-text."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Speech Recognition
|
|
7
|
+
|
|
8
|
+
Transcribe live and pre-recorded audio to text using Apple's Speech framework.
|
|
9
|
+
Covers `SFSpeechRecognizer` (iOS 10+) and the new `SpeechAnalyzer` API (iOS 26+).
|
|
10
|
+
|
|
11
|
+
## Contents
|
|
12
|
+
|
|
13
|
+
- [SpeechAnalyzer (iOS 26+)](#speechanalyzer-ios-26)
|
|
14
|
+
- [SFSpeechRecognizer Setup](#sfspeechrecognizer-setup)
|
|
15
|
+
- [Authorization](#authorization)
|
|
16
|
+
- [Live Microphone Transcription](#live-microphone-transcription)
|
|
17
|
+
- [Pre-Recorded Audio File Recognition](#pre-recorded-audio-file-recognition)
|
|
18
|
+
- [On-Device vs Server Recognition](#on-device-vs-server-recognition)
|
|
19
|
+
- [Handling Results](#handling-results)
|
|
20
|
+
- [Common Mistakes](#common-mistakes)
|
|
21
|
+
- [Review Checklist](#review-checklist)
|
|
22
|
+
- [References](#references)
|
|
23
|
+
|
|
24
|
+
## SpeechAnalyzer (iOS 26+)
|
|
25
|
+
|
|
26
|
+
`SpeechAnalyzer` is an actor-based API introduced in iOS 26 that replaces
|
|
27
|
+
`SFSpeechRecognizer` for new projects. It uses Swift concurrency, `AsyncSequence`
|
|
28
|
+
for results, and supports modular analysis via `SpeechTranscriber`.
|
|
29
|
+
|
|
30
|
+
### Basic transcription with SpeechAnalyzer
|
|
31
|
+
|
|
32
|
+
```swift
|
|
33
|
+
import Speech
|
|
34
|
+
|
|
35
|
+
// 1. Create a transcriber module
|
|
36
|
+
guard let locale = SpeechTranscriber.supportedLocale(
|
|
37
|
+
equivalentTo: Locale.current
|
|
38
|
+
) else { return }
|
|
39
|
+
let transcriber = SpeechTranscriber(locale: locale, preset: .offlineTranscription)
|
|
40
|
+
|
|
41
|
+
// 2. Ensure assets are installed
|
|
42
|
+
if let request = try await AssetInventory.assetInstallationRequest(
|
|
43
|
+
supporting: [transcriber]
|
|
44
|
+
) {
|
|
45
|
+
try await request.downloadAndInstall()
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 3. Create input stream and analyzer
|
|
49
|
+
let (inputSequence, inputBuilder) = AsyncStream.makeStream(of: AnalyzerInput.self)
|
|
50
|
+
let audioFormat = await SpeechAnalyzer.bestAvailableAudioFormat(
|
|
51
|
+
compatibleWith: [transcriber]
|
|
52
|
+
)
|
|
53
|
+
let analyzer = SpeechAnalyzer(modules: [transcriber])
|
|
54
|
+
|
|
55
|
+
// 4. Feed audio buffers (from AVAudioEngine or file)
|
|
56
|
+
Task {
|
|
57
|
+
// Append PCM buffers converted to audioFormat
|
|
58
|
+
let pcmBuffer: AVAudioPCMBuffer = // ... your audio buffer
|
|
59
|
+
inputBuilder.yield(AnalyzerInput(buffer: pcmBuffer))
|
|
60
|
+
inputBuilder.finish()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 5. Consume results
|
|
64
|
+
Task {
|
|
65
|
+
for try await result in transcriber.results {
|
|
66
|
+
let text = String(result.text.characters)
|
|
67
|
+
print(text)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 6. Run analysis
|
|
72
|
+
let lastSampleTime = try await analyzer.analyzeSequence(inputSequence)
|
|
73
|
+
|
|
74
|
+
// 7. Finalize
|
|
75
|
+
if let lastSampleTime {
|
|
76
|
+
try await analyzer.finalizeAndFinish(through: lastSampleTime)
|
|
77
|
+
} else {
|
|
78
|
+
try analyzer.cancelAndFinishNow()
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Transcribing an audio file with SpeechAnalyzer
|
|
83
|
+
|
|
84
|
+
```swift
|
|
85
|
+
let transcriber = SpeechTranscriber(locale: locale, preset: .offlineTranscription)
|
|
86
|
+
let audioFile = try AVAudioFile(forReading: fileURL)
|
|
87
|
+
let analyzer = SpeechAnalyzer(
|
|
88
|
+
inputAudioFile: audioFile, modules: [transcriber], finishAfterFile: true
|
|
89
|
+
)
|
|
90
|
+
for try await result in transcriber.results {
|
|
91
|
+
print(String(result.text.characters))
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Key differences from SFSpeechRecognizer
|
|
96
|
+
|
|
97
|
+
| Feature | SFSpeechRecognizer | SpeechAnalyzer |
|
|
98
|
+
|---|---|---|
|
|
99
|
+
| Concurrency | Callbacks/delegates | async/await + AsyncSequence |
|
|
100
|
+
| Type | `class` | `actor` |
|
|
101
|
+
| Modules | Monolithic | Composable (`SpeechTranscriber`, `SpeechDetector`) |
|
|
102
|
+
| Audio input | `append(_:)` on request | `AsyncStream<AnalyzerInput>` |
|
|
103
|
+
| Availability | iOS 10+ | iOS 26+ |
|
|
104
|
+
| On-device | `requiresOnDeviceRecognition` | Asset-based via `AssetInventory` |
|
|
105
|
+
|
|
106
|
+
## SFSpeechRecognizer Setup
|
|
107
|
+
|
|
108
|
+
### Creating a recognizer with locale
|
|
109
|
+
|
|
110
|
+
```swift
|
|
111
|
+
import Speech
|
|
112
|
+
|
|
113
|
+
// Default locale (user's current language)
|
|
114
|
+
let recognizer = SFSpeechRecognizer()
|
|
115
|
+
|
|
116
|
+
// Specific locale
|
|
117
|
+
let recognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))
|
|
118
|
+
|
|
119
|
+
// Check if recognition is available for this locale
|
|
120
|
+
guard let recognizer, recognizer.isAvailable else {
|
|
121
|
+
print("Speech recognition not available")
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Monitoring availability changes
|
|
127
|
+
|
|
128
|
+
```swift
|
|
129
|
+
final class SpeechManager: NSObject, SFSpeechRecognizerDelegate {
|
|
130
|
+
private let recognizer = SFSpeechRecognizer()!
|
|
131
|
+
|
|
132
|
+
override init() {
|
|
133
|
+
super.init()
|
|
134
|
+
recognizer.delegate = self
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
func speechRecognizer(
|
|
138
|
+
_ speechRecognizer: SFSpeechRecognizer,
|
|
139
|
+
availabilityDidChange available: Bool
|
|
140
|
+
) {
|
|
141
|
+
// Update UI — disable record button when unavailable
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Authorization
|
|
147
|
+
|
|
148
|
+
Request **both** speech recognition and microphone permissions before starting
|
|
149
|
+
live transcription. Add these keys to `Info.plist`:
|
|
150
|
+
|
|
151
|
+
- `NSSpeechRecognitionUsageDescription`
|
|
152
|
+
- `NSMicrophoneUsageDescription`
|
|
153
|
+
|
|
154
|
+
```swift
|
|
155
|
+
import Speech
|
|
156
|
+
import AVFoundation
|
|
157
|
+
|
|
158
|
+
func requestPermissions() async -> Bool {
|
|
159
|
+
let speechStatus = await withCheckedContinuation { continuation in
|
|
160
|
+
SFSpeechRecognizer.requestAuthorization { status in
|
|
161
|
+
continuation.resume(returning: status)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
guard speechStatus == .authorized else { return false }
|
|
165
|
+
|
|
166
|
+
let micStatus: Bool
|
|
167
|
+
if #available(iOS 17, *) {
|
|
168
|
+
micStatus = await AVAudioApplication.requestRecordPermission()
|
|
169
|
+
} else {
|
|
170
|
+
micStatus = await withCheckedContinuation { continuation in
|
|
171
|
+
AVAudioSession.sharedInstance().requestRecordPermission { granted in
|
|
172
|
+
continuation.resume(returning: granted)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return micStatus
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Live Microphone Transcription
|
|
181
|
+
|
|
182
|
+
The standard pattern: `AVAudioEngine` captures microphone audio → buffers are
|
|
183
|
+
appended to `SFSpeechAudioBufferRecognitionRequest` → results stream in.
|
|
184
|
+
|
|
185
|
+
```swift
|
|
186
|
+
import Speech
|
|
187
|
+
import AVFoundation
|
|
188
|
+
|
|
189
|
+
final class LiveTranscriber {
|
|
190
|
+
private let recognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))!
|
|
191
|
+
private let audioEngine = AVAudioEngine()
|
|
192
|
+
private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?
|
|
193
|
+
private var recognitionTask: SFSpeechRecognitionTask?
|
|
194
|
+
|
|
195
|
+
func startTranscribing() throws {
|
|
196
|
+
// Cancel any in-progress task
|
|
197
|
+
recognitionTask?.cancel()
|
|
198
|
+
recognitionTask = nil
|
|
199
|
+
|
|
200
|
+
// Configure audio session
|
|
201
|
+
let audioSession = AVAudioSession.sharedInstance()
|
|
202
|
+
try audioSession.setCategory(.record, mode: .measurement, options: .duckOthers)
|
|
203
|
+
try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
|
|
204
|
+
|
|
205
|
+
// Create request
|
|
206
|
+
let request = SFSpeechAudioBufferRecognitionRequest()
|
|
207
|
+
request.shouldReportPartialResults = true
|
|
208
|
+
self.recognitionRequest = request
|
|
209
|
+
|
|
210
|
+
// Start recognition task
|
|
211
|
+
recognitionTask = recognizer.recognitionTask(with: request) { result, error in
|
|
212
|
+
if let result {
|
|
213
|
+
let text = result.bestTranscription.formattedString
|
|
214
|
+
print("Transcription: \(text)")
|
|
215
|
+
|
|
216
|
+
if result.isFinal {
|
|
217
|
+
self.stopTranscribing()
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if let error {
|
|
221
|
+
print("Recognition error: \(error)")
|
|
222
|
+
self.stopTranscribing()
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Install audio tap
|
|
227
|
+
let inputNode = audioEngine.inputNode
|
|
228
|
+
let recordingFormat = inputNode.outputFormat(forBus: 0)
|
|
229
|
+
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) {
|
|
230
|
+
buffer, _ in
|
|
231
|
+
request.append(buffer)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
audioEngine.prepare()
|
|
235
|
+
try audioEngine.start()
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
func stopTranscribing() {
|
|
239
|
+
audioEngine.stop()
|
|
240
|
+
audioEngine.inputNode.removeTap(onBus: 0)
|
|
241
|
+
recognitionRequest?.endAudio()
|
|
242
|
+
recognitionRequest = nil
|
|
243
|
+
recognitionTask?.cancel()
|
|
244
|
+
recognitionTask = nil
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Pre-Recorded Audio File Recognition
|
|
250
|
+
|
|
251
|
+
Use `SFSpeechURLRecognitionRequest` for audio files on disk:
|
|
252
|
+
|
|
253
|
+
```swift
|
|
254
|
+
func transcribeFile(at url: URL) async throws -> String {
|
|
255
|
+
guard let recognizer = SFSpeechRecognizer(), recognizer.isAvailable else {
|
|
256
|
+
throw SpeechError.unavailable
|
|
257
|
+
}
|
|
258
|
+
let request = SFSpeechURLRecognitionRequest(url: url)
|
|
259
|
+
request.shouldReportPartialResults = false
|
|
260
|
+
|
|
261
|
+
return try await withCheckedThrowingContinuation { continuation in
|
|
262
|
+
recognizer.recognitionTask(with: request) { result, error in
|
|
263
|
+
if let error {
|
|
264
|
+
continuation.resume(throwing: error)
|
|
265
|
+
} else if let result, result.isFinal {
|
|
266
|
+
continuation.resume(
|
|
267
|
+
returning: result.bestTranscription.formattedString
|
|
268
|
+
)
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## On-Device vs Server Recognition
|
|
276
|
+
|
|
277
|
+
On-device recognition (iOS 13+) works offline but supports fewer locales:
|
|
278
|
+
|
|
279
|
+
```swift
|
|
280
|
+
let recognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))!
|
|
281
|
+
|
|
282
|
+
// Check if on-device is supported for this locale
|
|
283
|
+
if recognizer.supportsOnDeviceRecognition {
|
|
284
|
+
let request = SFSpeechAudioBufferRecognitionRequest()
|
|
285
|
+
request.requiresOnDeviceRecognition = true // Force on-device
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
> **Tip:** On-device recognition avoids network latency and the one-minute
|
|
290
|
+
> audio limit imposed by server-based recognition. However, accuracy may be
|
|
291
|
+
> lower and not all locales are supported. Check `supportsOnDeviceRecognition`
|
|
292
|
+
> before forcing on-device mode.
|
|
293
|
+
|
|
294
|
+
## Handling Results
|
|
295
|
+
|
|
296
|
+
### Partial vs final results
|
|
297
|
+
|
|
298
|
+
```swift
|
|
299
|
+
let request = SFSpeechAudioBufferRecognitionRequest()
|
|
300
|
+
request.shouldReportPartialResults = true // default is true
|
|
301
|
+
|
|
302
|
+
recognizer.recognitionTask(with: request) { result, error in
|
|
303
|
+
guard let result else { return }
|
|
304
|
+
|
|
305
|
+
if result.isFinal {
|
|
306
|
+
// Final transcription — recognition is complete
|
|
307
|
+
let final = result.bestTranscription.formattedString
|
|
308
|
+
} else {
|
|
309
|
+
// Partial result — may change as more audio is processed
|
|
310
|
+
let partial = result.bestTranscription.formattedString
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Accessing alternative transcriptions and confidence
|
|
316
|
+
|
|
317
|
+
```swift
|
|
318
|
+
recognizer.recognitionTask(with: request) { result, error in
|
|
319
|
+
guard let result else { return }
|
|
320
|
+
|
|
321
|
+
// Best transcription
|
|
322
|
+
let best = result.bestTranscription
|
|
323
|
+
|
|
324
|
+
// All alternatives (sorted by confidence, descending)
|
|
325
|
+
for transcription in result.transcriptions {
|
|
326
|
+
for segment in transcription.segments {
|
|
327
|
+
print("\(segment.substring): \(segment.confidence)")
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Adding punctuation (iOS 16+)
|
|
334
|
+
|
|
335
|
+
```swift
|
|
336
|
+
let request = SFSpeechAudioBufferRecognitionRequest()
|
|
337
|
+
request.addsPunctuation = true
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Contextual strings
|
|
341
|
+
|
|
342
|
+
Improve recognition of domain-specific terms:
|
|
343
|
+
|
|
344
|
+
```swift
|
|
345
|
+
let request = SFSpeechAudioBufferRecognitionRequest()
|
|
346
|
+
request.contextualStrings = ["SwiftUI", "Xcode", "CloudKit"]
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Common Mistakes
|
|
350
|
+
|
|
351
|
+
### Not requesting both speech and microphone authorization
|
|
352
|
+
|
|
353
|
+
```swift
|
|
354
|
+
// ❌ DON'T: Only request speech authorization for live audio
|
|
355
|
+
SFSpeechRecognizer.requestAuthorization { status in
|
|
356
|
+
// Missing microphone permission — audio engine will fail
|
|
357
|
+
self.startRecording()
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// ✅ DO: Request both permissions before recording
|
|
361
|
+
SFSpeechRecognizer.requestAuthorization { status in
|
|
362
|
+
guard status == .authorized else { return }
|
|
363
|
+
AVAudioSession.sharedInstance().requestRecordPermission { granted in
|
|
364
|
+
guard granted else { return }
|
|
365
|
+
self.startRecording()
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Not handling availability changes
|
|
371
|
+
|
|
372
|
+
```swift
|
|
373
|
+
// ❌ DON'T: Assume recognizer stays available after initial check
|
|
374
|
+
let recognizer = SFSpeechRecognizer()!
|
|
375
|
+
// Recognition may fail if network drops or locale changes
|
|
376
|
+
|
|
377
|
+
// ✅ DO: Monitor availability via delegate
|
|
378
|
+
recognizer.delegate = self
|
|
379
|
+
func speechRecognizer(
|
|
380
|
+
_ speechRecognizer: SFSpeechRecognizer,
|
|
381
|
+
availabilityDidChange available: Bool
|
|
382
|
+
) {
|
|
383
|
+
recordButton.isEnabled = available
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### Not stopping the audio engine when recognition ends
|
|
388
|
+
|
|
389
|
+
```swift
|
|
390
|
+
// ❌ DON'T: Leave audio engine running after recognition finishes
|
|
391
|
+
recognizer.recognitionTask(with: request) { result, error in
|
|
392
|
+
if result?.isFinal == true {
|
|
393
|
+
// Audio engine still running, wasting resources and battery
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// ✅ DO: Clean up all audio resources
|
|
398
|
+
recognizer.recognitionTask(with: request) { result, error in
|
|
399
|
+
if result?.isFinal == true || error != nil {
|
|
400
|
+
self.audioEngine.stop()
|
|
401
|
+
self.audioEngine.inputNode.removeTap(onBus: 0)
|
|
402
|
+
self.recognitionRequest?.endAudio()
|
|
403
|
+
self.recognitionRequest = nil
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Assuming on-device recognition is available for all locales
|
|
409
|
+
|
|
410
|
+
```swift
|
|
411
|
+
// ❌ DON'T: Force on-device without checking support
|
|
412
|
+
let request = SFSpeechAudioBufferRecognitionRequest()
|
|
413
|
+
request.requiresOnDeviceRecognition = true // May silently fail
|
|
414
|
+
|
|
415
|
+
// ✅ DO: Check support before requiring on-device
|
|
416
|
+
if recognizer.supportsOnDeviceRecognition {
|
|
417
|
+
request.requiresOnDeviceRecognition = true
|
|
418
|
+
} else {
|
|
419
|
+
// Fall back to server-based or inform user
|
|
420
|
+
}
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Not handling the one-minute recognition limit
|
|
424
|
+
|
|
425
|
+
```swift
|
|
426
|
+
// ❌ DON'T: Start one long continuous recognition session
|
|
427
|
+
func startRecording() {
|
|
428
|
+
// This will be cut off after ~60 seconds (server-based)
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// ✅ DO: Restart recognition when approaching the limit
|
|
432
|
+
func startRecording() {
|
|
433
|
+
// Use a timer to restart before the limit
|
|
434
|
+
recognitionTimer = Timer.scheduledTimer(withTimeInterval: 55, repeats: false) {
|
|
435
|
+
[weak self] _ in
|
|
436
|
+
self?.restartRecognition()
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### Creating multiple simultaneous recognition tasks
|
|
442
|
+
|
|
443
|
+
```swift
|
|
444
|
+
// ❌ DON'T: Start a new task without canceling the previous one
|
|
445
|
+
func startRecording() {
|
|
446
|
+
recognitionTask = recognizer.recognitionTask(with: request) { ... }
|
|
447
|
+
// Previous task is still running — undefined behavior
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// ✅ DO: Cancel existing task before creating a new one
|
|
451
|
+
func startRecording() {
|
|
452
|
+
recognitionTask?.cancel()
|
|
453
|
+
recognitionTask = nil
|
|
454
|
+
recognitionTask = recognizer.recognitionTask(with: request) { ... }
|
|
455
|
+
}
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
## Review Checklist
|
|
459
|
+
|
|
460
|
+
- [ ] `NSSpeechRecognitionUsageDescription` is in Info.plist
|
|
461
|
+
- [ ] `NSMicrophoneUsageDescription` is in Info.plist (if using live audio)
|
|
462
|
+
- [ ] Authorization is requested before starting recognition
|
|
463
|
+
- [ ] `SFSpeechRecognizerDelegate` is set to handle `availabilityDidChange`
|
|
464
|
+
- [ ] Audio engine is stopped and tap removed when recognition ends
|
|
465
|
+
- [ ] `recognitionRequest.endAudio()` is called when done recording
|
|
466
|
+
- [ ] Previous `recognitionTask` is canceled before starting a new one
|
|
467
|
+
- [ ] `supportsOnDeviceRecognition` is checked before requiring on-device mode
|
|
468
|
+
- [ ] Partial results are handled separately from final (`isFinal`) results
|
|
469
|
+
- [ ] One-minute limit is accounted for in server-based recognition
|
|
470
|
+
- [ ] For iOS 26+: `AssetInventory` assets are installed before using `SpeechAnalyzer`
|
|
471
|
+
- [ ] For iOS 26+: `SpeechTranscriber.supportedLocale(equivalentTo:)` is checked
|
|
472
|
+
|
|
473
|
+
## References
|
|
474
|
+
|
|
475
|
+
- [Speech framework](https://sosumi.ai/documentation/speech)
|
|
476
|
+
- [SpeechAnalyzer](https://sosumi.ai/documentation/speech/speechanalyzer)
|
|
477
|
+
- [SpeechTranscriber](https://sosumi.ai/documentation/speech/speechtranscriber)
|
|
478
|
+
- [SFSpeechRecognizer](https://sosumi.ai/documentation/speech/sfspeechrecognizer)
|
|
479
|
+
- [SFSpeechAudioBufferRecognitionRequest](https://sosumi.ai/documentation/speech/sfspeechaudiobufferrecognitionrequest)
|
|
480
|
+
- [SFSpeechURLRecognitionRequest](https://sosumi.ai/documentation/speech/sfspeechurlrecognitionrequest)
|
|
481
|
+
- [SFSpeechRecognitionResult](https://sosumi.ai/documentation/speech/sfspeechrecognitionresult)
|
|
482
|
+
- [SFSpeechRecognitionRequest](https://sosumi.ai/documentation/speech/sfspeechrecognitionrequest)
|
|
483
|
+
- [AssetInventory](https://sosumi.ai/documentation/speech/assetinventory)
|
|
484
|
+
- [Asking Permission to Use Speech Recognition](https://sosumi.ai/documentation/speech/asking-permission-to-use-speech-recognition)
|
|
485
|
+
- [Recognizing Speech in Live Audio](https://sosumi.ai/documentation/speech/recognizing-speech-in-live-audio)
|