@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
|
@@ -1,446 +1,446 @@
|
|
|
1
|
-
# Performance Optimization Reference
|
|
2
|
-
|
|
3
|
-
## Three Phases: Composition, Layout, Drawing
|
|
4
|
-
|
|
5
|
-
Every frame consists of three phases. Understanding state reads in each phase prevents unnecessary recompositions.
|
|
6
|
-
|
|
7
|
-
### Composition Phase
|
|
8
|
-
- Executes composable functions, evaluates state reads
|
|
9
|
-
- Generates lambda and instance allocations
|
|
10
|
-
- **State reads here trigger recomposition** of the entire scope
|
|
11
|
-
|
|
12
|
-
### Layout Phase
|
|
13
|
-
- Calculates size and position, runs `measure` and `layout` blocks
|
|
14
|
-
- Can read state without triggering composition recomposition
|
|
15
|
-
- Mutable state reads OK; prefer `Modifier.offset { }` over `Modifier.offset()`
|
|
16
|
-
|
|
17
|
-
### Drawing Phase
|
|
18
|
-
- Emits draw operations, runs `Canvas` and custom `DrawScope`
|
|
19
|
-
- Cannot read mutable state without stability warnings
|
|
20
|
-
|
|
21
|
-
**Source**: `androidx/compose/runtime/Composer.kt`
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
## Recomposition Skipping with Compiler Reports
|
|
26
|
-
|
|
27
|
-
The Compose compiler generates `$changed` bitmasks to detect state changes. Check compiler reports:
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
# In build.gradle.kts
|
|
31
|
-
composeOptions {
|
|
32
|
-
kotlinCompilerExtensionVersion = "1.5.0"
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Compiler report shows skipped/non-skipped functions
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
### Stability — @Stable and @Immutable
|
|
39
|
-
|
|
40
|
-
A type is **stable** if:
|
|
41
|
-
- Its public properties are stable
|
|
42
|
-
- Overrides to `equals()` and `hashCode()` are based on stable properties
|
|
43
|
-
- Recomposition is skipped when the same instance is passed
|
|
44
|
-
|
|
45
|
-
Mark stable types explicitly:
|
|
46
|
-
|
|
47
|
-
```kotlin
|
|
48
|
-
@Immutable
|
|
49
|
-
data class Person(val name: String, val age: Int)
|
|
50
|
-
|
|
51
|
-
@Stable
|
|
52
|
-
class UserViewModel : ViewModel {
|
|
53
|
-
private val _state = MutableState(UserState())
|
|
54
|
-
val state: State<UserState> = _state
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Composable receiving stable types can skip recomposition
|
|
58
|
-
@Composable
|
|
59
|
-
fun PersonCard(person: Person) {
|
|
60
|
-
Text(person.name) // Skips if person unchanged
|
|
61
|
-
}
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
**Avoid**: `@Stable` on data classes with mutable fields or non-final properties.
|
|
65
|
-
|
|
66
|
-
---
|
|
67
|
-
|
|
68
|
-
## Strong Skipping Mode (Default)
|
|
69
|
-
|
|
70
|
-
Android Gradle Plugin 8.0+ and Compose compiler 1.5.0+ enable **strong skipping mode**. This changes how lambdas are treated:
|
|
71
|
-
|
|
72
|
-
Without strong skipping, every lambda is unstable. With it enabled:
|
|
73
|
-
- Lambdas become stable if all captured variables are stable
|
|
74
|
-
- Fewer unnecessary recompositions
|
|
75
|
-
|
|
76
|
-
```kotlin
|
|
77
|
-
// With strong skipping: lambda is stable if count is stable
|
|
78
|
-
@Composable
|
|
79
|
-
fun Counter(count: Int) {
|
|
80
|
-
Button(onClick = { println(count) }) { // Stable lambda
|
|
81
|
-
Text("Count: $count")
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
Check `build.gradle.kts`:
|
|
87
|
-
```kotlin
|
|
88
|
-
android {
|
|
89
|
-
composeOptions {
|
|
90
|
-
kotlinCompilerExtensionVersion = "1.5.0"
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
---
|
|
96
|
-
|
|
97
|
-
## Defer State Reads to Layout/Draw Phase
|
|
98
|
-
|
|
99
|
-
Reading state in composition triggers recomposition. Push reads to later phases:
|
|
100
|
-
|
|
101
|
-
### Bad: Recomposition on Every Offset Change
|
|
102
|
-
```kotlin
|
|
103
|
-
@Composable
|
|
104
|
-
fun Box(offsetX: State<Float>) {
|
|
105
|
-
val x = offsetX.value // Reads in composition, triggers recomposition
|
|
106
|
-
Box(modifier = Modifier.offset(x.dp, 0.dp))
|
|
107
|
-
}
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### Good: Deferred Read in Layout Phase
|
|
111
|
-
```kotlin
|
|
112
|
-
@Composable
|
|
113
|
-
fun Box(offsetX: State<Float>) {
|
|
114
|
-
Box(
|
|
115
|
-
modifier = Modifier.offset {
|
|
116
|
-
IntOffset(offsetX.value.toInt(), 0) // Read in layout phase
|
|
117
|
-
}
|
|
118
|
-
)
|
|
119
|
-
}
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
Use `Modifier.offset { }` (lambda) instead of `Modifier.offset()` (parameter) for state-dependent positioning.
|
|
123
|
-
|
|
124
|
-
---
|
|
125
|
-
|
|
126
|
-
## derivedStateOf — Reducing Recomposition Frequency
|
|
127
|
-
|
|
128
|
-
When deriving expensive computations from state, wrap in `derivedStateOf` to dedup recompositions:
|
|
129
|
-
|
|
130
|
-
```kotlin
|
|
131
|
-
// Bad: recomposes on every items change
|
|
132
|
-
@Composable
|
|
133
|
-
fun SearchResults(items: List<Item>, query: String) {
|
|
134
|
-
val filtered = items.filter { query in it.title } // Composition phase
|
|
135
|
-
LazyColumn {
|
|
136
|
-
items(filtered) { /* ... */ }
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Good: only recomposes if filtered result actually changes
|
|
141
|
-
@Composable
|
|
142
|
-
fun SearchResults(items: List<Item>, query: String) {
|
|
143
|
-
val filtered = remember(items, query) {
|
|
144
|
-
derivedStateOf { items.filter { query in it.title } }
|
|
145
|
-
}
|
|
146
|
-
LazyColumn {
|
|
147
|
-
items(filtered.value) { /* ... */ }
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
`derivedStateOf` deduplicates downstream recompositions — two different filters yielding the same list trigger only one downstream recomposition.
|
|
153
|
-
|
|
154
|
-
---
|
|
155
|
-
|
|
156
|
-
## remember with Keys
|
|
157
|
-
|
|
158
|
-
Avoid unnecessary recalculation:
|
|
159
|
-
|
|
160
|
-
```kotlin
|
|
161
|
-
// Recalculates on every recomposition
|
|
162
|
-
@Composable
|
|
163
|
-
fun ExpensiveItem(id: Int) {
|
|
164
|
-
val metadata = computeMetadata(id) // Called every time
|
|
165
|
-
Text(metadata)
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Recalculates only when id changes
|
|
169
|
-
@Composable
|
|
170
|
-
fun ExpensiveItem(id: Int) {
|
|
171
|
-
val metadata = remember(id) { computeMetadata(id) }
|
|
172
|
-
Text(metadata)
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Multiple keys
|
|
176
|
-
@Composable
|
|
177
|
-
fun Item(id: Int, userId: Int) {
|
|
178
|
-
val data = remember(id, userId) { fetchData(id, userId) }
|
|
179
|
-
Text(data.toString())
|
|
180
|
-
}
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
Omit `remember` if computation is cheap (string formatting, simple objects). Over-wrapping causes memory leaks.
|
|
184
|
-
|
|
185
|
-
---
|
|
186
|
-
|
|
187
|
-
## LazyList Performance — Keys and ContentType
|
|
188
|
-
|
|
189
|
-
### Always Provide Keys
|
|
190
|
-
|
|
191
|
-
Keys enable item reuse and animations:
|
|
192
|
-
|
|
193
|
-
```kotlin
|
|
194
|
-
// Bad: no keys, items recreated on every list change
|
|
195
|
-
LazyColumn {
|
|
196
|
-
items(users) { user ->
|
|
197
|
-
UserRow(user)
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Good: keys enable reuse
|
|
202
|
-
LazyColumn {
|
|
203
|
-
items(users, key = { it.id }) { user ->
|
|
204
|
-
UserRow(user)
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
### ContentType for Efficient Reuse
|
|
210
|
-
|
|
211
|
-
```kotlin
|
|
212
|
-
sealed class ListItem {
|
|
213
|
-
data class Header(val title: String) : ListItem()
|
|
214
|
-
data class User(val user: User) : ListItem()
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
LazyColumn {
|
|
218
|
-
items(
|
|
219
|
-
items = items,
|
|
220
|
-
key = { it.hashCode() },
|
|
221
|
-
contentType = { item ->
|
|
222
|
-
when (item) {
|
|
223
|
-
is ListItem.Header -> "header"
|
|
224
|
-
is ListItem.User -> "user"
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
) { item ->
|
|
228
|
-
when (item) {
|
|
229
|
-
is ListItem.Header -> HeaderRow(item.title)
|
|
230
|
-
is ListItem.User -> UserRow(item.user)
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
Without `contentType`, all items compete for one ViewHolder pool. With it, items reuse efficiently.
|
|
237
|
-
|
|
238
|
-
### Avoid Allocations in Item Scope
|
|
239
|
-
|
|
240
|
-
```kotlin
|
|
241
|
-
// Bad: allocates on every recomposition
|
|
242
|
-
LazyColumn {
|
|
243
|
-
items(users) { user ->
|
|
244
|
-
val userState = remember { mutableStateOf(user) }
|
|
245
|
-
UserRow(userState.value)
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// Good: allocates once
|
|
250
|
-
LazyColumn {
|
|
251
|
-
items(
|
|
252
|
-
items = users,
|
|
253
|
-
key = { it.id }
|
|
254
|
-
) { user ->
|
|
255
|
-
UserRow(user)
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
---
|
|
261
|
-
|
|
262
|
-
## Baseline Profiles
|
|
263
|
-
|
|
264
|
-
Baseline profiles instruct R8 to pre-compile hot code paths, reducing startup time and jank.
|
|
265
|
-
|
|
266
|
-
### Generating Profiles
|
|
267
|
-
|
|
268
|
-
Use Jetpack Macrobenchmark to record profiles:
|
|
269
|
-
|
|
270
|
-
```kotlin
|
|
271
|
-
@RunWith(AndroidBenchmarkRunner::class)
|
|
272
|
-
class StartupBenchmark {
|
|
273
|
-
@get:Rule
|
|
274
|
-
val benchmarkRule = MacrobenchmarkRule()
|
|
275
|
-
|
|
276
|
-
@Test
|
|
277
|
-
fun startupCompilation() = benchmarkRule.measureRepeated(
|
|
278
|
-
packageName = "com.example.app",
|
|
279
|
-
metrics = listOf(StartupTimings.FIRST_FRAME),
|
|
280
|
-
iterations = 10,
|
|
281
|
-
setupBlock = {
|
|
282
|
-
pressHome()
|
|
283
|
-
startActivityAndWait()
|
|
284
|
-
}
|
|
285
|
-
) {
|
|
286
|
-
// Interact with app
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
Profiles are generated in `baseline-prof.txt`:
|
|
292
|
-
```
|
|
293
|
-
androidx/compose/runtime/Recomposer;startRecomposition()V
|
|
294
|
-
com/example/MyScreen;ComposableFunctionName(ILandroidx/compose/runtime/Composer;I)V
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
---
|
|
298
|
-
|
|
299
|
-
## R8/ProGuard Compose Rules
|
|
300
|
-
|
|
301
|
-
Compose includes default ProGuard rules. Ensure `shrinkResources true` and `minifyEnabled true`:
|
|
302
|
-
|
|
303
|
-
```gradle
|
|
304
|
-
android {
|
|
305
|
-
buildTypes {
|
|
306
|
-
release {
|
|
307
|
-
minifyEnabled true
|
|
308
|
-
shrinkResources true
|
|
309
|
-
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
Custom rules to preserve stability:
|
|
316
|
-
|
|
317
|
-
```proguard
|
|
318
|
-
-keep @androidx.compose.runtime.Stable class **
|
|
319
|
-
-keep @androidx.compose.runtime.Immutable class **
|
|
320
|
-
-keepclassmembers class * {
|
|
321
|
-
@androidx.compose.runtime.Stable <methods>;
|
|
322
|
-
}
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
---
|
|
326
|
-
|
|
327
|
-
## Measuring Performance
|
|
328
|
-
|
|
329
|
-
### Layout Inspector — Recomposition Counts
|
|
330
|
-
|
|
331
|
-
In Android Studio:
|
|
332
|
-
1. Run app on device
|
|
333
|
-
2. Open **Layout Inspector** (Tools > Layout Inspector)
|
|
334
|
-
3. Select target process
|
|
335
|
-
4. Check **Show Composition Counts** (toggle in inspector)
|
|
336
|
-
|
|
337
|
-
Recomposition counts display how many times each composable was recomposed since inspection started.
|
|
338
|
-
|
|
339
|
-
### Macrobenchmark — Frame Timing
|
|
340
|
-
|
|
341
|
-
```kotlin
|
|
342
|
-
benchmarkRule.measureRepeated(
|
|
343
|
-
packageName = "com.example.app",
|
|
344
|
-
metrics = listOf(FrameTimingMetric()),
|
|
345
|
-
iterations = 10
|
|
346
|
-
) {
|
|
347
|
-
// Interact: scroll, click, etc.
|
|
348
|
-
}
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
Reports frame times (ms), jank, jitter. Target <16.67ms for 60 fps.
|
|
352
|
-
|
|
353
|
-
---
|
|
354
|
-
|
|
355
|
-
## Common Hot Paths
|
|
356
|
-
|
|
357
|
-
### String Formatting in Composition
|
|
358
|
-
```kotlin
|
|
359
|
-
// Bad: allocates string every recomposition
|
|
360
|
-
@Composable
|
|
361
|
-
fun Counter(count: Int) {
|
|
362
|
-
Text("Count: ${count}") // String.format called
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
// Still composed, but optimized
|
|
366
|
-
@Composable
|
|
367
|
-
fun Counter(count: Int) {
|
|
368
|
-
Text(buildString { append("Count: "); append(count) })
|
|
369
|
-
}
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
### List Filtering Without derivedStateOf
|
|
373
|
-
```kotlin
|
|
374
|
-
// Bad: filters every recomposition
|
|
375
|
-
@Composable
|
|
376
|
-
fun FilteredList(items: List<Item>, predicate: (Item) -> Boolean) {
|
|
377
|
-
LazyColumn {
|
|
378
|
-
items(items.filter(predicate)) { /* ... */ }
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// Good
|
|
383
|
-
@Composable
|
|
384
|
-
fun FilteredList(items: List<Item>, predicate: (Item) -> Boolean) {
|
|
385
|
-
val filtered = remember(items, predicate) {
|
|
386
|
-
derivedStateOf { items.filter(predicate) }
|
|
387
|
-
}
|
|
388
|
-
LazyColumn {
|
|
389
|
-
items(filtered.value) { /* ... */ }
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
### Creating Objects in Lambdas
|
|
395
|
-
```kotlin
|
|
396
|
-
// Bad
|
|
397
|
-
Button(
|
|
398
|
-
colors = ButtonDefaults.buttonColors(
|
|
399
|
-
containerColor = if (isPressed) Color.Red else Color.Blue
|
|
400
|
-
)
|
|
401
|
-
) { }
|
|
402
|
-
|
|
403
|
-
// Good: compute once
|
|
404
|
-
val buttonColors = remember(isPressed) {
|
|
405
|
-
ButtonDefaults.buttonColors(
|
|
406
|
-
containerColor = if (isPressed) Color.Red else Color.Blue
|
|
407
|
-
)
|
|
408
|
-
}
|
|
409
|
-
Button(colors = buttonColors) { }
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
---
|
|
413
|
-
|
|
414
|
-
## Anti-Patterns
|
|
415
|
-
|
|
416
|
-
### Wrapping Everything in remember
|
|
417
|
-
```kotlin
|
|
418
|
-
// Unnecessary
|
|
419
|
-
val text = remember { "Hello" }
|
|
420
|
-
val size = remember { 12.sp }
|
|
421
|
-
val color = remember { Color.Black }
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
`remember` only for mutable state or expensive calculations.
|
|
425
|
-
|
|
426
|
-
### Premature Optimization
|
|
427
|
-
Profile first. Don't add `derivedStateOf` or `remember` without Layout Inspector data.
|
|
428
|
-
|
|
429
|
-
### @Stable on Mutable Data Classes
|
|
430
|
-
```kotlin
|
|
431
|
-
// DON'T
|
|
432
|
-
@Stable
|
|
433
|
-
data class MutableUser(val name: String, val age: MutableState<Int>)
|
|
434
|
-
|
|
435
|
-
// DO
|
|
436
|
-
@Immutable
|
|
437
|
-
data class User(val name: String, val age: Int)
|
|
438
|
-
```
|
|
439
|
-
|
|
440
|
-
---
|
|
441
|
-
|
|
442
|
-
## Resources
|
|
443
|
-
|
|
444
|
-
- **Compose Compiler Reports**: https://developer.android.com/develop/ui/compose/performance/stability-report
|
|
445
|
-
- **Macrobenchmark**: https://developer.android.com/develop/ui/compose/performance/measurement
|
|
446
|
-
- **Baseline Profiles**: https://developer.android.com/develop/ui/compose/performance/baseline-profiles
|
|
1
|
+
# Performance Optimization Reference
|
|
2
|
+
|
|
3
|
+
## Three Phases: Composition, Layout, Drawing
|
|
4
|
+
|
|
5
|
+
Every frame consists of three phases. Understanding state reads in each phase prevents unnecessary recompositions.
|
|
6
|
+
|
|
7
|
+
### Composition Phase
|
|
8
|
+
- Executes composable functions, evaluates state reads
|
|
9
|
+
- Generates lambda and instance allocations
|
|
10
|
+
- **State reads here trigger recomposition** of the entire scope
|
|
11
|
+
|
|
12
|
+
### Layout Phase
|
|
13
|
+
- Calculates size and position, runs `measure` and `layout` blocks
|
|
14
|
+
- Can read state without triggering composition recomposition
|
|
15
|
+
- Mutable state reads OK; prefer `Modifier.offset { }` over `Modifier.offset()`
|
|
16
|
+
|
|
17
|
+
### Drawing Phase
|
|
18
|
+
- Emits draw operations, runs `Canvas` and custom `DrawScope`
|
|
19
|
+
- Cannot read mutable state without stability warnings
|
|
20
|
+
|
|
21
|
+
**Source**: `androidx/compose/runtime/Composer.kt`
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Recomposition Skipping with Compiler Reports
|
|
26
|
+
|
|
27
|
+
The Compose compiler generates `$changed` bitmasks to detect state changes. Check compiler reports:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# In build.gradle.kts
|
|
31
|
+
composeOptions {
|
|
32
|
+
kotlinCompilerExtensionVersion = "1.5.0"
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Compiler report shows skipped/non-skipped functions
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Stability — @Stable and @Immutable
|
|
39
|
+
|
|
40
|
+
A type is **stable** if:
|
|
41
|
+
- Its public properties are stable
|
|
42
|
+
- Overrides to `equals()` and `hashCode()` are based on stable properties
|
|
43
|
+
- Recomposition is skipped when the same instance is passed
|
|
44
|
+
|
|
45
|
+
Mark stable types explicitly:
|
|
46
|
+
|
|
47
|
+
```kotlin
|
|
48
|
+
@Immutable
|
|
49
|
+
data class Person(val name: String, val age: Int)
|
|
50
|
+
|
|
51
|
+
@Stable
|
|
52
|
+
class UserViewModel : ViewModel {
|
|
53
|
+
private val _state = MutableState(UserState())
|
|
54
|
+
val state: State<UserState> = _state
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Composable receiving stable types can skip recomposition
|
|
58
|
+
@Composable
|
|
59
|
+
fun PersonCard(person: Person) {
|
|
60
|
+
Text(person.name) // Skips if person unchanged
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Avoid**: `@Stable` on data classes with mutable fields or non-final properties.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Strong Skipping Mode (Default)
|
|
69
|
+
|
|
70
|
+
Android Gradle Plugin 8.0+ and Compose compiler 1.5.0+ enable **strong skipping mode**. This changes how lambdas are treated:
|
|
71
|
+
|
|
72
|
+
Without strong skipping, every lambda is unstable. With it enabled:
|
|
73
|
+
- Lambdas become stable if all captured variables are stable
|
|
74
|
+
- Fewer unnecessary recompositions
|
|
75
|
+
|
|
76
|
+
```kotlin
|
|
77
|
+
// With strong skipping: lambda is stable if count is stable
|
|
78
|
+
@Composable
|
|
79
|
+
fun Counter(count: Int) {
|
|
80
|
+
Button(onClick = { println(count) }) { // Stable lambda
|
|
81
|
+
Text("Count: $count")
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Check `build.gradle.kts`:
|
|
87
|
+
```kotlin
|
|
88
|
+
android {
|
|
89
|
+
composeOptions {
|
|
90
|
+
kotlinCompilerExtensionVersion = "1.5.0"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Defer State Reads to Layout/Draw Phase
|
|
98
|
+
|
|
99
|
+
Reading state in composition triggers recomposition. Push reads to later phases:
|
|
100
|
+
|
|
101
|
+
### Bad: Recomposition on Every Offset Change
|
|
102
|
+
```kotlin
|
|
103
|
+
@Composable
|
|
104
|
+
fun Box(offsetX: State<Float>) {
|
|
105
|
+
val x = offsetX.value // Reads in composition, triggers recomposition
|
|
106
|
+
Box(modifier = Modifier.offset(x.dp, 0.dp))
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Good: Deferred Read in Layout Phase
|
|
111
|
+
```kotlin
|
|
112
|
+
@Composable
|
|
113
|
+
fun Box(offsetX: State<Float>) {
|
|
114
|
+
Box(
|
|
115
|
+
modifier = Modifier.offset {
|
|
116
|
+
IntOffset(offsetX.value.toInt(), 0) // Read in layout phase
|
|
117
|
+
}
|
|
118
|
+
)
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Use `Modifier.offset { }` (lambda) instead of `Modifier.offset()` (parameter) for state-dependent positioning.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## derivedStateOf — Reducing Recomposition Frequency
|
|
127
|
+
|
|
128
|
+
When deriving expensive computations from state, wrap in `derivedStateOf` to dedup recompositions:
|
|
129
|
+
|
|
130
|
+
```kotlin
|
|
131
|
+
// Bad: recomposes on every items change
|
|
132
|
+
@Composable
|
|
133
|
+
fun SearchResults(items: List<Item>, query: String) {
|
|
134
|
+
val filtered = items.filter { query in it.title } // Composition phase
|
|
135
|
+
LazyColumn {
|
|
136
|
+
items(filtered) { /* ... */ }
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Good: only recomposes if filtered result actually changes
|
|
141
|
+
@Composable
|
|
142
|
+
fun SearchResults(items: List<Item>, query: String) {
|
|
143
|
+
val filtered = remember(items, query) {
|
|
144
|
+
derivedStateOf { items.filter { query in it.title } }
|
|
145
|
+
}
|
|
146
|
+
LazyColumn {
|
|
147
|
+
items(filtered.value) { /* ... */ }
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`derivedStateOf` deduplicates downstream recompositions — two different filters yielding the same list trigger only one downstream recomposition.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## remember with Keys
|
|
157
|
+
|
|
158
|
+
Avoid unnecessary recalculation:
|
|
159
|
+
|
|
160
|
+
```kotlin
|
|
161
|
+
// Recalculates on every recomposition
|
|
162
|
+
@Composable
|
|
163
|
+
fun ExpensiveItem(id: Int) {
|
|
164
|
+
val metadata = computeMetadata(id) // Called every time
|
|
165
|
+
Text(metadata)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Recalculates only when id changes
|
|
169
|
+
@Composable
|
|
170
|
+
fun ExpensiveItem(id: Int) {
|
|
171
|
+
val metadata = remember(id) { computeMetadata(id) }
|
|
172
|
+
Text(metadata)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Multiple keys
|
|
176
|
+
@Composable
|
|
177
|
+
fun Item(id: Int, userId: Int) {
|
|
178
|
+
val data = remember(id, userId) { fetchData(id, userId) }
|
|
179
|
+
Text(data.toString())
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Omit `remember` if computation is cheap (string formatting, simple objects). Over-wrapping causes memory leaks.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## LazyList Performance — Keys and ContentType
|
|
188
|
+
|
|
189
|
+
### Always Provide Keys
|
|
190
|
+
|
|
191
|
+
Keys enable item reuse and animations:
|
|
192
|
+
|
|
193
|
+
```kotlin
|
|
194
|
+
// Bad: no keys, items recreated on every list change
|
|
195
|
+
LazyColumn {
|
|
196
|
+
items(users) { user ->
|
|
197
|
+
UserRow(user)
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Good: keys enable reuse
|
|
202
|
+
LazyColumn {
|
|
203
|
+
items(users, key = { it.id }) { user ->
|
|
204
|
+
UserRow(user)
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### ContentType for Efficient Reuse
|
|
210
|
+
|
|
211
|
+
```kotlin
|
|
212
|
+
sealed class ListItem {
|
|
213
|
+
data class Header(val title: String) : ListItem()
|
|
214
|
+
data class User(val user: User) : ListItem()
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
LazyColumn {
|
|
218
|
+
items(
|
|
219
|
+
items = items,
|
|
220
|
+
key = { it.hashCode() },
|
|
221
|
+
contentType = { item ->
|
|
222
|
+
when (item) {
|
|
223
|
+
is ListItem.Header -> "header"
|
|
224
|
+
is ListItem.User -> "user"
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
) { item ->
|
|
228
|
+
when (item) {
|
|
229
|
+
is ListItem.Header -> HeaderRow(item.title)
|
|
230
|
+
is ListItem.User -> UserRow(item.user)
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Without `contentType`, all items compete for one ViewHolder pool. With it, items reuse efficiently.
|
|
237
|
+
|
|
238
|
+
### Avoid Allocations in Item Scope
|
|
239
|
+
|
|
240
|
+
```kotlin
|
|
241
|
+
// Bad: allocates on every recomposition
|
|
242
|
+
LazyColumn {
|
|
243
|
+
items(users) { user ->
|
|
244
|
+
val userState = remember { mutableStateOf(user) }
|
|
245
|
+
UserRow(userState.value)
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Good: allocates once
|
|
250
|
+
LazyColumn {
|
|
251
|
+
items(
|
|
252
|
+
items = users,
|
|
253
|
+
key = { it.id }
|
|
254
|
+
) { user ->
|
|
255
|
+
UserRow(user)
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Baseline Profiles
|
|
263
|
+
|
|
264
|
+
Baseline profiles instruct R8 to pre-compile hot code paths, reducing startup time and jank.
|
|
265
|
+
|
|
266
|
+
### Generating Profiles
|
|
267
|
+
|
|
268
|
+
Use Jetpack Macrobenchmark to record profiles:
|
|
269
|
+
|
|
270
|
+
```kotlin
|
|
271
|
+
@RunWith(AndroidBenchmarkRunner::class)
|
|
272
|
+
class StartupBenchmark {
|
|
273
|
+
@get:Rule
|
|
274
|
+
val benchmarkRule = MacrobenchmarkRule()
|
|
275
|
+
|
|
276
|
+
@Test
|
|
277
|
+
fun startupCompilation() = benchmarkRule.measureRepeated(
|
|
278
|
+
packageName = "com.example.app",
|
|
279
|
+
metrics = listOf(StartupTimings.FIRST_FRAME),
|
|
280
|
+
iterations = 10,
|
|
281
|
+
setupBlock = {
|
|
282
|
+
pressHome()
|
|
283
|
+
startActivityAndWait()
|
|
284
|
+
}
|
|
285
|
+
) {
|
|
286
|
+
// Interact with app
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Profiles are generated in `baseline-prof.txt`:
|
|
292
|
+
```
|
|
293
|
+
androidx/compose/runtime/Recomposer;startRecomposition()V
|
|
294
|
+
com/example/MyScreen;ComposableFunctionName(ILandroidx/compose/runtime/Composer;I)V
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## R8/ProGuard Compose Rules
|
|
300
|
+
|
|
301
|
+
Compose includes default ProGuard rules. Ensure `shrinkResources true` and `minifyEnabled true`:
|
|
302
|
+
|
|
303
|
+
```gradle
|
|
304
|
+
android {
|
|
305
|
+
buildTypes {
|
|
306
|
+
release {
|
|
307
|
+
minifyEnabled true
|
|
308
|
+
shrinkResources true
|
|
309
|
+
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Custom rules to preserve stability:
|
|
316
|
+
|
|
317
|
+
```proguard
|
|
318
|
+
-keep @androidx.compose.runtime.Stable class **
|
|
319
|
+
-keep @androidx.compose.runtime.Immutable class **
|
|
320
|
+
-keepclassmembers class * {
|
|
321
|
+
@androidx.compose.runtime.Stable <methods>;
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Measuring Performance
|
|
328
|
+
|
|
329
|
+
### Layout Inspector — Recomposition Counts
|
|
330
|
+
|
|
331
|
+
In Android Studio:
|
|
332
|
+
1. Run app on device
|
|
333
|
+
2. Open **Layout Inspector** (Tools > Layout Inspector)
|
|
334
|
+
3. Select target process
|
|
335
|
+
4. Check **Show Composition Counts** (toggle in inspector)
|
|
336
|
+
|
|
337
|
+
Recomposition counts display how many times each composable was recomposed since inspection started.
|
|
338
|
+
|
|
339
|
+
### Macrobenchmark — Frame Timing
|
|
340
|
+
|
|
341
|
+
```kotlin
|
|
342
|
+
benchmarkRule.measureRepeated(
|
|
343
|
+
packageName = "com.example.app",
|
|
344
|
+
metrics = listOf(FrameTimingMetric()),
|
|
345
|
+
iterations = 10
|
|
346
|
+
) {
|
|
347
|
+
// Interact: scroll, click, etc.
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
Reports frame times (ms), jank, jitter. Target <16.67ms for 60 fps.
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
355
|
+
## Common Hot Paths
|
|
356
|
+
|
|
357
|
+
### String Formatting in Composition
|
|
358
|
+
```kotlin
|
|
359
|
+
// Bad: allocates string every recomposition
|
|
360
|
+
@Composable
|
|
361
|
+
fun Counter(count: Int) {
|
|
362
|
+
Text("Count: ${count}") // String.format called
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Still composed, but optimized
|
|
366
|
+
@Composable
|
|
367
|
+
fun Counter(count: Int) {
|
|
368
|
+
Text(buildString { append("Count: "); append(count) })
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### List Filtering Without derivedStateOf
|
|
373
|
+
```kotlin
|
|
374
|
+
// Bad: filters every recomposition
|
|
375
|
+
@Composable
|
|
376
|
+
fun FilteredList(items: List<Item>, predicate: (Item) -> Boolean) {
|
|
377
|
+
LazyColumn {
|
|
378
|
+
items(items.filter(predicate)) { /* ... */ }
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// Good
|
|
383
|
+
@Composable
|
|
384
|
+
fun FilteredList(items: List<Item>, predicate: (Item) -> Boolean) {
|
|
385
|
+
val filtered = remember(items, predicate) {
|
|
386
|
+
derivedStateOf { items.filter(predicate) }
|
|
387
|
+
}
|
|
388
|
+
LazyColumn {
|
|
389
|
+
items(filtered.value) { /* ... */ }
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### Creating Objects in Lambdas
|
|
395
|
+
```kotlin
|
|
396
|
+
// Bad
|
|
397
|
+
Button(
|
|
398
|
+
colors = ButtonDefaults.buttonColors(
|
|
399
|
+
containerColor = if (isPressed) Color.Red else Color.Blue
|
|
400
|
+
)
|
|
401
|
+
) { }
|
|
402
|
+
|
|
403
|
+
// Good: compute once
|
|
404
|
+
val buttonColors = remember(isPressed) {
|
|
405
|
+
ButtonDefaults.buttonColors(
|
|
406
|
+
containerColor = if (isPressed) Color.Red else Color.Blue
|
|
407
|
+
)
|
|
408
|
+
}
|
|
409
|
+
Button(colors = buttonColors) { }
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
## Anti-Patterns
|
|
415
|
+
|
|
416
|
+
### Wrapping Everything in remember
|
|
417
|
+
```kotlin
|
|
418
|
+
// Unnecessary
|
|
419
|
+
val text = remember { "Hello" }
|
|
420
|
+
val size = remember { 12.sp }
|
|
421
|
+
val color = remember { Color.Black }
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
`remember` only for mutable state or expensive calculations.
|
|
425
|
+
|
|
426
|
+
### Premature Optimization
|
|
427
|
+
Profile first. Don't add `derivedStateOf` or `remember` without Layout Inspector data.
|
|
428
|
+
|
|
429
|
+
### @Stable on Mutable Data Classes
|
|
430
|
+
```kotlin
|
|
431
|
+
// DON'T
|
|
432
|
+
@Stable
|
|
433
|
+
data class MutableUser(val name: String, val age: MutableState<Int>)
|
|
434
|
+
|
|
435
|
+
// DO
|
|
436
|
+
@Immutable
|
|
437
|
+
data class User(val name: String, val age: Int)
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
442
|
+
## Resources
|
|
443
|
+
|
|
444
|
+
- **Compose Compiler Reports**: https://developer.android.com/develop/ui/compose/performance/stability-report
|
|
445
|
+
- **Macrobenchmark**: https://developer.android.com/develop/ui/compose/performance/measurement
|
|
446
|
+
- **Baseline Profiles**: https://developer.android.com/develop/ui/compose/performance/baseline-profiles
|