@devo-bmad-custom/agent-orchestration 1.0.2 → 1.0.4
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 +33 -0
- 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/master-orchestrator.md +15 -0
- package/src/_memory/config.yaml +11 -11
- package/src/_memory/master-orchestrator-sidecar/instructions.md +97 -47
- 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/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/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,504 +1,504 @@
|
|
|
1
|
-
# Core Data Coexistence
|
|
2
|
-
|
|
3
|
-
Standalone Core Data patterns for projects not yet on SwiftData, strategies
|
|
4
|
-
for running Core Data and SwiftData side by side against the same store, and
|
|
5
|
-
migration guidance for transitioning from Core Data to SwiftData.
|
|
6
|
-
|
|
7
|
-
## Contents
|
|
8
|
-
|
|
9
|
-
- [Standalone Core Data Stack](#standalone-core-data-stack)
|
|
10
|
-
- [Core Data + SwiftData Coexistence](#core-data--swiftdata-coexistence)
|
|
11
|
-
- [Migration from Core Data to SwiftData](#migration-from-core-data-to-swiftdata)
|
|
12
|
-
|
|
13
|
-
## Standalone Core Data Stack
|
|
14
|
-
|
|
15
|
-
For teams that haven't adopted SwiftData, Core Data remains a fully supported
|
|
16
|
-
persistence framework.
|
|
17
|
-
|
|
18
|
-
Docs: [NSPersistentContainer](https://sosumi.ai/documentation/coredata/nspersistentcontainer),
|
|
19
|
-
[Setting up a Core Data stack](https://sosumi.ai/documentation/coredata/setting-up-a-core-data-stack)
|
|
20
|
-
|
|
21
|
-
### NSPersistentContainer Setup
|
|
22
|
-
|
|
23
|
-
`NSPersistentContainer` encapsulates the Core Data stack: the managed object
|
|
24
|
-
model, the persistent store coordinator, and the managed object context.
|
|
25
|
-
|
|
26
|
-
```swift
|
|
27
|
-
import CoreData
|
|
28
|
-
|
|
29
|
-
final class CoreDataStack: @unchecked Sendable {
|
|
30
|
-
static let shared = CoreDataStack()
|
|
31
|
-
|
|
32
|
-
let container: NSPersistentContainer
|
|
33
|
-
|
|
34
|
-
private init() {
|
|
35
|
-
// Name must match the .xcdatamodeld file name
|
|
36
|
-
container = NSPersistentContainer(name: "MyAppModel")
|
|
37
|
-
|
|
38
|
-
container.loadPersistentStores { description, error in
|
|
39
|
-
if let error {
|
|
40
|
-
fatalError("Core Data store failed to load: \(error)")
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Automatically merge changes from background contexts
|
|
45
|
-
container.viewContext.automaticallyMergesChangesFromParent = true
|
|
46
|
-
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/// The main-thread context for UI reads
|
|
50
|
-
var viewContext: NSManagedObjectContext {
|
|
51
|
-
container.viewContext
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/// A new background context for writes
|
|
55
|
-
func newBackgroundContext() -> NSManagedObjectContext {
|
|
56
|
-
container.newBackgroundContext()
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### NSManagedObjectContext Usage
|
|
62
|
-
|
|
63
|
-
The `viewContext` is bound to the main queue; use it for reads and UI. Use
|
|
64
|
-
background contexts for writes and batch operations.
|
|
65
|
-
|
|
66
|
-
```swift
|
|
67
|
-
// Reading on the main context
|
|
68
|
-
func fetchTrips() throws -> [CDTrip] {
|
|
69
|
-
let context = CoreDataStack.shared.viewContext
|
|
70
|
-
let request = CDTrip.fetchRequest()
|
|
71
|
-
request.sortDescriptors = [NSSortDescriptor(keyPath: \CDTrip.startDate, ascending: true)]
|
|
72
|
-
return try context.fetch(request)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Writing on a background context
|
|
76
|
-
func createTrip(name: String, destination: String) async throws {
|
|
77
|
-
let context = CoreDataStack.shared.newBackgroundContext()
|
|
78
|
-
try await context.perform {
|
|
79
|
-
let trip = CDTrip(context: context)
|
|
80
|
-
trip.name = name
|
|
81
|
-
trip.destination = destination
|
|
82
|
-
trip.startDate = Date.now
|
|
83
|
-
trip.id = UUID()
|
|
84
|
-
try context.save()
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### NSFetchRequest with NSPredicate and NSSortDescriptor
|
|
90
|
-
|
|
91
|
-
```swift
|
|
92
|
-
import CoreData
|
|
93
|
-
|
|
94
|
-
func fetchUpcomingTrips(destination: String) throws -> [CDTrip] {
|
|
95
|
-
let context = CoreDataStack.shared.viewContext
|
|
96
|
-
let request: NSFetchRequest<CDTrip> = CDTrip.fetchRequest()
|
|
97
|
-
|
|
98
|
-
// Predicate: filter by destination and future start date
|
|
99
|
-
request.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [
|
|
100
|
-
NSPredicate(format: "destination ==[cd] %@", destination),
|
|
101
|
-
NSPredicate(format: "startDate > %@", Date.now as NSDate)
|
|
102
|
-
])
|
|
103
|
-
|
|
104
|
-
// Sort: newest first
|
|
105
|
-
request.sortDescriptors = [
|
|
106
|
-
NSSortDescriptor(keyPath: \CDTrip.startDate, ascending: false)
|
|
107
|
-
]
|
|
108
|
-
|
|
109
|
-
// Performance: limit results and prefetch relationships
|
|
110
|
-
request.fetchLimit = 20
|
|
111
|
-
request.relationshipKeyPathsForPrefetching = ["accommodation"]
|
|
112
|
-
|
|
113
|
-
return try context.fetch(request)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Counting without loading objects
|
|
117
|
-
func countFavoriteTrips() throws -> Int {
|
|
118
|
-
let request: NSFetchRequest<CDTrip> = CDTrip.fetchRequest()
|
|
119
|
-
request.predicate = NSPredicate(format: "isFavorite == YES")
|
|
120
|
-
return try CoreDataStack.shared.viewContext.count(for: request)
|
|
121
|
-
}
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
### Saving Context and Error Handling
|
|
125
|
-
|
|
126
|
-
```swift
|
|
127
|
-
func saveContext(_ context: NSManagedObjectContext) throws {
|
|
128
|
-
guard context.hasChanges else { return }
|
|
129
|
-
|
|
130
|
-
do {
|
|
131
|
-
try context.save()
|
|
132
|
-
} catch {
|
|
133
|
-
// Roll back unsaved changes to prevent inconsistent state
|
|
134
|
-
context.rollback()
|
|
135
|
-
|
|
136
|
-
if let nsError = error as NSError? {
|
|
137
|
-
// Check for common Core Data errors
|
|
138
|
-
switch nsError.code {
|
|
139
|
-
case NSManagedObjectConstraintMergeError:
|
|
140
|
-
// Unique constraint violation -- handle merge conflict
|
|
141
|
-
throw PersistenceError.constraintViolation(nsError)
|
|
142
|
-
case NSValidationMissingMandatoryPropertyError:
|
|
143
|
-
// Required property is nil
|
|
144
|
-
throw PersistenceError.validationFailed(nsError)
|
|
145
|
-
default:
|
|
146
|
-
throw PersistenceError.saveFailed(nsError)
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
throw error
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
enum PersistenceError: Error {
|
|
154
|
-
case constraintViolation(NSError)
|
|
155
|
-
case validationFailed(NSError)
|
|
156
|
-
case saveFailed(NSError)
|
|
157
|
-
}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
### Background Processing Pattern
|
|
161
|
-
|
|
162
|
-
```swift
|
|
163
|
-
func importTrips(_ records: [TripRecord]) async throws {
|
|
164
|
-
let context = CoreDataStack.shared.newBackgroundContext()
|
|
165
|
-
try await context.perform {
|
|
166
|
-
// Batch insert for performance (iOS 13+)
|
|
167
|
-
let batchInsert = NSBatchInsertRequest(
|
|
168
|
-
entity: CDTrip.entity(),
|
|
169
|
-
objects: records.map { record in
|
|
170
|
-
[
|
|
171
|
-
"id": record.id,
|
|
172
|
-
"name": record.name,
|
|
173
|
-
"destination": record.destination,
|
|
174
|
-
"startDate": record.startDate
|
|
175
|
-
] as [String: Any]
|
|
176
|
-
}
|
|
177
|
-
)
|
|
178
|
-
batchInsert.resultType = .count
|
|
179
|
-
let result = try context.execute(batchInsert) as? NSBatchInsertResult
|
|
180
|
-
print("Inserted \(result?.result as? Int ?? 0) trips")
|
|
181
|
-
|
|
182
|
-
// Merge changes into viewContext
|
|
183
|
-
NSManagedObjectContext.mergeChanges(
|
|
184
|
-
fromRemoteContextSave: [NSInsertedObjectsKey: []],
|
|
185
|
-
into: [CoreDataStack.shared.viewContext]
|
|
186
|
-
)
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
## Core Data + SwiftData Coexistence
|
|
192
|
-
|
|
193
|
-
Core Data and SwiftData can share the same underlying SQLite store. This
|
|
194
|
-
enables gradual migration: keep existing Core Data code running while
|
|
195
|
-
introducing SwiftData for new features.
|
|
196
|
-
|
|
197
|
-
Docs: [Adopting SwiftData for a Core Data app](https://sosumi.ai/documentation/coredata/adopting_swiftdata_for_a_core_data_app)
|
|
198
|
-
|
|
199
|
-
### Using the Same Underlying Store
|
|
200
|
-
|
|
201
|
-
Both stacks must point to the same SQLite file and agree on the schema. The
|
|
202
|
-
Core Data `.xcdatamodeld` and SwiftData `@Model` classes must describe the
|
|
203
|
-
same entities and properties.
|
|
204
|
-
|
|
205
|
-
```swift
|
|
206
|
-
import SwiftData
|
|
207
|
-
import CoreData
|
|
208
|
-
|
|
209
|
-
// 1. Determine the store URL that Core Data already uses
|
|
210
|
-
let storeURL = NSPersistentContainer.defaultDirectoryURL()
|
|
211
|
-
.appendingPathComponent("MyAppModel.sqlite")
|
|
212
|
-
|
|
213
|
-
// 2. Point SwiftData at the same store
|
|
214
|
-
let config = ModelConfiguration(
|
|
215
|
-
"MyAppModel",
|
|
216
|
-
url: storeURL
|
|
217
|
-
)
|
|
218
|
-
|
|
219
|
-
let container = try ModelContainer(
|
|
220
|
-
for: Trip.self,
|
|
221
|
-
configurations: config
|
|
222
|
-
)
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
### ModelConfiguration Pointing to Existing Core Data Store
|
|
226
|
-
|
|
227
|
-
Key rules for coexistence:
|
|
228
|
-
|
|
229
|
-
1. The `@Model` class name must match the Core Data entity name.
|
|
230
|
-
2. Property names and types must match exactly.
|
|
231
|
-
3. Use `@Attribute(originalName:)` if you renamed properties.
|
|
232
|
-
4. Both stacks should use the same store file.
|
|
233
|
-
|
|
234
|
-
```swift
|
|
235
|
-
// Core Data entity: CDTrip (entity name "Trip" in .xcdatamodeld)
|
|
236
|
-
// Attributes: name (String), destination (String), startDate (Date),
|
|
237
|
-
// isFavorite (Boolean), imageData (Binary Data)
|
|
238
|
-
|
|
239
|
-
// Matching SwiftData model
|
|
240
|
-
@Model
|
|
241
|
-
class Trip {
|
|
242
|
-
var name: String
|
|
243
|
-
var destination: String
|
|
244
|
-
var startDate: Date
|
|
245
|
-
var isFavorite: Bool = false
|
|
246
|
-
@Attribute(.externalStorage) var imageData: Data?
|
|
247
|
-
|
|
248
|
-
init(name: String, destination: String, startDate: Date) {
|
|
249
|
-
self.name = name
|
|
250
|
-
self.destination = destination
|
|
251
|
-
self.startDate = startDate
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
### Gradual Coexistence Strategy
|
|
257
|
-
|
|
258
|
-
```swift
|
|
259
|
-
// Phase 1: Core Data stack still handles writes;
|
|
260
|
-
// SwiftData reads the same store for new UI
|
|
261
|
-
@main
|
|
262
|
-
struct MyApp: App {
|
|
263
|
-
let coreDataStack = CoreDataStack.shared // Existing Core Data
|
|
264
|
-
|
|
265
|
-
var body: some Scene {
|
|
266
|
-
WindowGroup {
|
|
267
|
-
ContentView()
|
|
268
|
-
}
|
|
269
|
-
// SwiftData reads from the same store
|
|
270
|
-
.modelContainer(for: Trip.self, configurations:
|
|
271
|
-
ModelConfiguration(url: coreDataStack.storeURL)
|
|
272
|
-
)
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// Phase 2: New features use SwiftData for both reads and writes
|
|
277
|
-
// Phase 3: Migrate remaining Core Data code to SwiftData
|
|
278
|
-
// Phase 4: Remove Core Data stack and .xcdatamodeld
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
### Important Coexistence Rules
|
|
282
|
-
|
|
283
|
-
- **Do not write to the same entity from both stacks simultaneously.** Pick
|
|
284
|
-
one stack per entity for writes to avoid conflicts.
|
|
285
|
-
- Core Data's `automaticallyMergesChangesFromParent` and
|
|
286
|
-
`NSPersistentStoreRemoteChangeNotification` help detect changes from the
|
|
287
|
-
other stack.
|
|
288
|
-
- Test thoroughly -- schema mismatches between the `.xcdatamodeld` and
|
|
289
|
-
`@Model` cause crashes.
|
|
290
|
-
|
|
291
|
-
## Migration from Core Data to SwiftData
|
|
292
|
-
|
|
293
|
-
### Step 1: Map Core Data Entities to @Model Classes
|
|
294
|
-
|
|
295
|
-
Create a `@Model` class for each Core Data entity. Property names and types
|
|
296
|
-
must align with the `.xcdatamodeld` definition.
|
|
297
|
-
|
|
298
|
-
```swift
|
|
299
|
-
// Core Data entity "Article"
|
|
300
|
-
// Attributes: id (UUID), title (String), body (String),
|
|
301
|
-
// createdAt (Date), isDraft (Boolean)
|
|
302
|
-
// Relationships: author (to-one → Author), tags (to-many → Tag)
|
|
303
|
-
|
|
304
|
-
@Model
|
|
305
|
-
class Article {
|
|
306
|
-
@Attribute(.unique) var id: UUID
|
|
307
|
-
var title: String
|
|
308
|
-
var body: String
|
|
309
|
-
var createdAt: Date
|
|
310
|
-
var isDraft: Bool = true
|
|
311
|
-
|
|
312
|
-
@Relationship(deleteRule: .nullify, inverse: \Author.articles)
|
|
313
|
-
var author: Author?
|
|
314
|
-
|
|
315
|
-
@Relationship(deleteRule: .nullify, inverse: \Tag.articles)
|
|
316
|
-
var tags: [Tag] = []
|
|
317
|
-
|
|
318
|
-
init(id: UUID = UUID(), title: String, body: String, createdAt: Date = .now) {
|
|
319
|
-
self.id = id
|
|
320
|
-
self.title = title
|
|
321
|
-
self.body = body
|
|
322
|
-
self.createdAt = createdAt
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
@Model
|
|
327
|
-
class Author {
|
|
328
|
-
@Attribute(.unique) var id: UUID
|
|
329
|
-
var name: String
|
|
330
|
-
var articles: [Article] = []
|
|
331
|
-
|
|
332
|
-
init(id: UUID = UUID(), name: String) {
|
|
333
|
-
self.id = id
|
|
334
|
-
self.name = name
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
@Model
|
|
339
|
-
class Tag {
|
|
340
|
-
@Attribute(.unique) var id: UUID
|
|
341
|
-
var name: String
|
|
342
|
-
var articles: [Article] = []
|
|
343
|
-
|
|
344
|
-
init(id: UUID = UUID(), name: String) {
|
|
345
|
-
self.id = id
|
|
346
|
-
self.name = name
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
### Type Mapping Reference
|
|
352
|
-
|
|
353
|
-
| Core Data Type | SwiftData Type |
|
|
354
|
-
|---|---|
|
|
355
|
-
| String | String |
|
|
356
|
-
| Boolean | Bool |
|
|
357
|
-
| Integer 16/32/64 | Int |
|
|
358
|
-
| Float / Double | Float / Double |
|
|
359
|
-
| Date | Date |
|
|
360
|
-
| Binary Data | Data |
|
|
361
|
-
| UUID | UUID |
|
|
362
|
-
| URI | URL |
|
|
363
|
-
| Decimal | Decimal |
|
|
364
|
-
| Transformable | Codable struct (composite, iOS 18+) |
|
|
365
|
-
| To-one relationship | Optional reference to @Model |
|
|
366
|
-
| To-many relationship | Array of @Model |
|
|
367
|
-
|
|
368
|
-
### Step 2: Schema Versioning Considerations
|
|
369
|
-
|
|
370
|
-
If the Core Data store has existing data, SwiftData must be able to open it.
|
|
371
|
-
Use `VersionedSchema` and `SchemaMigrationPlan` for non-trivial changes.
|
|
372
|
-
|
|
373
|
-
```swift
|
|
374
|
-
// If the SwiftData model exactly matches the Core Data schema,
|
|
375
|
-
// no migration is needed -- SwiftData opens the store directly.
|
|
376
|
-
|
|
377
|
-
// For schema differences, define versioned schemas:
|
|
378
|
-
enum SchemaV1: VersionedSchema {
|
|
379
|
-
static var versionIdentifier = Schema.Version(1, 0, 0)
|
|
380
|
-
static var models: [any PersistentModel.Type] { [Article.self, Author.self] }
|
|
381
|
-
|
|
382
|
-
@Model class Article {
|
|
383
|
-
var id: UUID
|
|
384
|
-
var title: String
|
|
385
|
-
var body: String
|
|
386
|
-
var createdAt: Date
|
|
387
|
-
init(id: UUID, title: String, body: String, createdAt: Date) {
|
|
388
|
-
self.id = id; self.title = title
|
|
389
|
-
self.body = body; self.createdAt = createdAt
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
@Model class Author {
|
|
394
|
-
var id: UUID
|
|
395
|
-
var name: String
|
|
396
|
-
init(id: UUID, name: String) { self.id = id; self.name = name }
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
enum SchemaV2: VersionedSchema {
|
|
401
|
-
static var versionIdentifier = Schema.Version(2, 0, 0)
|
|
402
|
-
static var models: [any PersistentModel.Type] { [Article.self, Author.self, Tag.self] }
|
|
403
|
-
|
|
404
|
-
@Model class Article {
|
|
405
|
-
var id: UUID
|
|
406
|
-
var title: String
|
|
407
|
-
var body: String
|
|
408
|
-
var createdAt: Date
|
|
409
|
-
var isDraft: Bool = true // New property
|
|
410
|
-
init(id: UUID, title: String, body: String, createdAt: Date) {
|
|
411
|
-
self.id = id; self.title = title
|
|
412
|
-
self.body = body; self.createdAt = createdAt
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
@Model class Author {
|
|
417
|
-
var id: UUID
|
|
418
|
-
var name: String
|
|
419
|
-
init(id: UUID, name: String) { self.id = id; self.name = name }
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
@Model class Tag {
|
|
423
|
-
var id: UUID
|
|
424
|
-
var name: String
|
|
425
|
-
init(id: UUID, name: String) { self.id = id; self.name = name }
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
enum ArticleMigrationPlan: SchemaMigrationPlan {
|
|
430
|
-
static var schemas: [any VersionedSchema.Type] { [SchemaV1.self, SchemaV2.self] }
|
|
431
|
-
static var stages: [MigrationStage] {
|
|
432
|
-
[MigrationStage.lightweight(fromVersion: SchemaV1.self, toVersion: SchemaV2.self)]
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
```
|
|
436
|
-
|
|
437
|
-
### Step 3: Testing Migration Paths
|
|
438
|
-
|
|
439
|
-
Always test migration with real production data copies before shipping.
|
|
440
|
-
|
|
441
|
-
```swift
|
|
442
|
-
import XCTest
|
|
443
|
-
import SwiftData
|
|
444
|
-
|
|
445
|
-
final class MigrationTests: XCTestCase {
|
|
446
|
-
|
|
447
|
-
func testCoreDataToSwiftDataMigration() throws {
|
|
448
|
-
// 1. Copy a known Core Data store into the test bundle
|
|
449
|
-
let sourceURL = Bundle(for: type(of: self))
|
|
450
|
-
.url(forResource: "TestStore", withExtension: "sqlite")!
|
|
451
|
-
|
|
452
|
-
let tempDir = FileManager.default.temporaryDirectory
|
|
453
|
-
.appendingPathComponent(UUID().uuidString)
|
|
454
|
-
try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)
|
|
455
|
-
|
|
456
|
-
let destURL = tempDir.appendingPathComponent("TestStore.sqlite")
|
|
457
|
-
try FileManager.default.copyItem(at: sourceURL, to: destURL)
|
|
458
|
-
|
|
459
|
-
// Copy WAL and SHM if they exist
|
|
460
|
-
for ext in ["-wal", "-shm"] {
|
|
461
|
-
let src = sourceURL.deletingLastPathComponent()
|
|
462
|
-
.appendingPathComponent("TestStore.sqlite\(ext)")
|
|
463
|
-
if FileManager.default.fileExists(atPath: src.path) {
|
|
464
|
-
try FileManager.default.copyItem(
|
|
465
|
-
at: src,
|
|
466
|
-
to: tempDir.appendingPathComponent("TestStore.sqlite\(ext)")
|
|
467
|
-
)
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
// 2. Open with SwiftData
|
|
472
|
-
let config = ModelConfiguration(url: destURL)
|
|
473
|
-
let container = try ModelContainer(
|
|
474
|
-
for: SchemaV2.Article.self,
|
|
475
|
-
migrationPlan: ArticleMigrationPlan.self,
|
|
476
|
-
configurations: config
|
|
477
|
-
)
|
|
478
|
-
|
|
479
|
-
// 3. Verify data survived migration
|
|
480
|
-
let context = ModelContext(container)
|
|
481
|
-
let articles = try context.fetch(FetchDescriptor<SchemaV2.Article>())
|
|
482
|
-
XCTAssertFalse(articles.isEmpty, "Migration should preserve existing articles")
|
|
483
|
-
|
|
484
|
-
// 4. Verify new properties have defaults
|
|
485
|
-
for article in articles {
|
|
486
|
-
XCTAssertTrue(article.isDraft, "New isDraft property should default to true")
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
// Cleanup
|
|
490
|
-
try FileManager.default.removeItem(at: tempDir)
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
```
|
|
494
|
-
|
|
495
|
-
### Migration Checklist
|
|
496
|
-
|
|
497
|
-
- [ ] Every Core Data entity has a matching `@Model` class with identical property names and types
|
|
498
|
-
- [ ] Relationship inverse properties are specified in both directions
|
|
499
|
-
- [ ] `VersionedSchema` and `SchemaMigrationPlan` defined for non-trivial schema changes
|
|
500
|
-
- [ ] `ModelConfiguration` points to the existing Core Data SQLite file
|
|
501
|
-
- [ ] Tested migration with a copy of production data
|
|
502
|
-
- [ ] Only one stack writes to each entity during coexistence
|
|
503
|
-
- [ ] `automaticallyMergesChangesFromParent` enabled on Core Data's `viewContext`
|
|
504
|
-
- [ ] `.xcdatamodeld` removed only after full migration is verified
|
|
1
|
+
# Core Data Coexistence
|
|
2
|
+
|
|
3
|
+
Standalone Core Data patterns for projects not yet on SwiftData, strategies
|
|
4
|
+
for running Core Data and SwiftData side by side against the same store, and
|
|
5
|
+
migration guidance for transitioning from Core Data to SwiftData.
|
|
6
|
+
|
|
7
|
+
## Contents
|
|
8
|
+
|
|
9
|
+
- [Standalone Core Data Stack](#standalone-core-data-stack)
|
|
10
|
+
- [Core Data + SwiftData Coexistence](#core-data--swiftdata-coexistence)
|
|
11
|
+
- [Migration from Core Data to SwiftData](#migration-from-core-data-to-swiftdata)
|
|
12
|
+
|
|
13
|
+
## Standalone Core Data Stack
|
|
14
|
+
|
|
15
|
+
For teams that haven't adopted SwiftData, Core Data remains a fully supported
|
|
16
|
+
persistence framework.
|
|
17
|
+
|
|
18
|
+
Docs: [NSPersistentContainer](https://sosumi.ai/documentation/coredata/nspersistentcontainer),
|
|
19
|
+
[Setting up a Core Data stack](https://sosumi.ai/documentation/coredata/setting-up-a-core-data-stack)
|
|
20
|
+
|
|
21
|
+
### NSPersistentContainer Setup
|
|
22
|
+
|
|
23
|
+
`NSPersistentContainer` encapsulates the Core Data stack: the managed object
|
|
24
|
+
model, the persistent store coordinator, and the managed object context.
|
|
25
|
+
|
|
26
|
+
```swift
|
|
27
|
+
import CoreData
|
|
28
|
+
|
|
29
|
+
final class CoreDataStack: @unchecked Sendable {
|
|
30
|
+
static let shared = CoreDataStack()
|
|
31
|
+
|
|
32
|
+
let container: NSPersistentContainer
|
|
33
|
+
|
|
34
|
+
private init() {
|
|
35
|
+
// Name must match the .xcdatamodeld file name
|
|
36
|
+
container = NSPersistentContainer(name: "MyAppModel")
|
|
37
|
+
|
|
38
|
+
container.loadPersistentStores { description, error in
|
|
39
|
+
if let error {
|
|
40
|
+
fatalError("Core Data store failed to load: \(error)")
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Automatically merge changes from background contexts
|
|
45
|
+
container.viewContext.automaticallyMergesChangesFromParent = true
|
|
46
|
+
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/// The main-thread context for UI reads
|
|
50
|
+
var viewContext: NSManagedObjectContext {
|
|
51
|
+
container.viewContext
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/// A new background context for writes
|
|
55
|
+
func newBackgroundContext() -> NSManagedObjectContext {
|
|
56
|
+
container.newBackgroundContext()
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### NSManagedObjectContext Usage
|
|
62
|
+
|
|
63
|
+
The `viewContext` is bound to the main queue; use it for reads and UI. Use
|
|
64
|
+
background contexts for writes and batch operations.
|
|
65
|
+
|
|
66
|
+
```swift
|
|
67
|
+
// Reading on the main context
|
|
68
|
+
func fetchTrips() throws -> [CDTrip] {
|
|
69
|
+
let context = CoreDataStack.shared.viewContext
|
|
70
|
+
let request = CDTrip.fetchRequest()
|
|
71
|
+
request.sortDescriptors = [NSSortDescriptor(keyPath: \CDTrip.startDate, ascending: true)]
|
|
72
|
+
return try context.fetch(request)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Writing on a background context
|
|
76
|
+
func createTrip(name: String, destination: String) async throws {
|
|
77
|
+
let context = CoreDataStack.shared.newBackgroundContext()
|
|
78
|
+
try await context.perform {
|
|
79
|
+
let trip = CDTrip(context: context)
|
|
80
|
+
trip.name = name
|
|
81
|
+
trip.destination = destination
|
|
82
|
+
trip.startDate = Date.now
|
|
83
|
+
trip.id = UUID()
|
|
84
|
+
try context.save()
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### NSFetchRequest with NSPredicate and NSSortDescriptor
|
|
90
|
+
|
|
91
|
+
```swift
|
|
92
|
+
import CoreData
|
|
93
|
+
|
|
94
|
+
func fetchUpcomingTrips(destination: String) throws -> [CDTrip] {
|
|
95
|
+
let context = CoreDataStack.shared.viewContext
|
|
96
|
+
let request: NSFetchRequest<CDTrip> = CDTrip.fetchRequest()
|
|
97
|
+
|
|
98
|
+
// Predicate: filter by destination and future start date
|
|
99
|
+
request.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [
|
|
100
|
+
NSPredicate(format: "destination ==[cd] %@", destination),
|
|
101
|
+
NSPredicate(format: "startDate > %@", Date.now as NSDate)
|
|
102
|
+
])
|
|
103
|
+
|
|
104
|
+
// Sort: newest first
|
|
105
|
+
request.sortDescriptors = [
|
|
106
|
+
NSSortDescriptor(keyPath: \CDTrip.startDate, ascending: false)
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
// Performance: limit results and prefetch relationships
|
|
110
|
+
request.fetchLimit = 20
|
|
111
|
+
request.relationshipKeyPathsForPrefetching = ["accommodation"]
|
|
112
|
+
|
|
113
|
+
return try context.fetch(request)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Counting without loading objects
|
|
117
|
+
func countFavoriteTrips() throws -> Int {
|
|
118
|
+
let request: NSFetchRequest<CDTrip> = CDTrip.fetchRequest()
|
|
119
|
+
request.predicate = NSPredicate(format: "isFavorite == YES")
|
|
120
|
+
return try CoreDataStack.shared.viewContext.count(for: request)
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Saving Context and Error Handling
|
|
125
|
+
|
|
126
|
+
```swift
|
|
127
|
+
func saveContext(_ context: NSManagedObjectContext) throws {
|
|
128
|
+
guard context.hasChanges else { return }
|
|
129
|
+
|
|
130
|
+
do {
|
|
131
|
+
try context.save()
|
|
132
|
+
} catch {
|
|
133
|
+
// Roll back unsaved changes to prevent inconsistent state
|
|
134
|
+
context.rollback()
|
|
135
|
+
|
|
136
|
+
if let nsError = error as NSError? {
|
|
137
|
+
// Check for common Core Data errors
|
|
138
|
+
switch nsError.code {
|
|
139
|
+
case NSManagedObjectConstraintMergeError:
|
|
140
|
+
// Unique constraint violation -- handle merge conflict
|
|
141
|
+
throw PersistenceError.constraintViolation(nsError)
|
|
142
|
+
case NSValidationMissingMandatoryPropertyError:
|
|
143
|
+
// Required property is nil
|
|
144
|
+
throw PersistenceError.validationFailed(nsError)
|
|
145
|
+
default:
|
|
146
|
+
throw PersistenceError.saveFailed(nsError)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
throw error
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
enum PersistenceError: Error {
|
|
154
|
+
case constraintViolation(NSError)
|
|
155
|
+
case validationFailed(NSError)
|
|
156
|
+
case saveFailed(NSError)
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Background Processing Pattern
|
|
161
|
+
|
|
162
|
+
```swift
|
|
163
|
+
func importTrips(_ records: [TripRecord]) async throws {
|
|
164
|
+
let context = CoreDataStack.shared.newBackgroundContext()
|
|
165
|
+
try await context.perform {
|
|
166
|
+
// Batch insert for performance (iOS 13+)
|
|
167
|
+
let batchInsert = NSBatchInsertRequest(
|
|
168
|
+
entity: CDTrip.entity(),
|
|
169
|
+
objects: records.map { record in
|
|
170
|
+
[
|
|
171
|
+
"id": record.id,
|
|
172
|
+
"name": record.name,
|
|
173
|
+
"destination": record.destination,
|
|
174
|
+
"startDate": record.startDate
|
|
175
|
+
] as [String: Any]
|
|
176
|
+
}
|
|
177
|
+
)
|
|
178
|
+
batchInsert.resultType = .count
|
|
179
|
+
let result = try context.execute(batchInsert) as? NSBatchInsertResult
|
|
180
|
+
print("Inserted \(result?.result as? Int ?? 0) trips")
|
|
181
|
+
|
|
182
|
+
// Merge changes into viewContext
|
|
183
|
+
NSManagedObjectContext.mergeChanges(
|
|
184
|
+
fromRemoteContextSave: [NSInsertedObjectsKey: []],
|
|
185
|
+
into: [CoreDataStack.shared.viewContext]
|
|
186
|
+
)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Core Data + SwiftData Coexistence
|
|
192
|
+
|
|
193
|
+
Core Data and SwiftData can share the same underlying SQLite store. This
|
|
194
|
+
enables gradual migration: keep existing Core Data code running while
|
|
195
|
+
introducing SwiftData for new features.
|
|
196
|
+
|
|
197
|
+
Docs: [Adopting SwiftData for a Core Data app](https://sosumi.ai/documentation/coredata/adopting_swiftdata_for_a_core_data_app)
|
|
198
|
+
|
|
199
|
+
### Using the Same Underlying Store
|
|
200
|
+
|
|
201
|
+
Both stacks must point to the same SQLite file and agree on the schema. The
|
|
202
|
+
Core Data `.xcdatamodeld` and SwiftData `@Model` classes must describe the
|
|
203
|
+
same entities and properties.
|
|
204
|
+
|
|
205
|
+
```swift
|
|
206
|
+
import SwiftData
|
|
207
|
+
import CoreData
|
|
208
|
+
|
|
209
|
+
// 1. Determine the store URL that Core Data already uses
|
|
210
|
+
let storeURL = NSPersistentContainer.defaultDirectoryURL()
|
|
211
|
+
.appendingPathComponent("MyAppModel.sqlite")
|
|
212
|
+
|
|
213
|
+
// 2. Point SwiftData at the same store
|
|
214
|
+
let config = ModelConfiguration(
|
|
215
|
+
"MyAppModel",
|
|
216
|
+
url: storeURL
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
let container = try ModelContainer(
|
|
220
|
+
for: Trip.self,
|
|
221
|
+
configurations: config
|
|
222
|
+
)
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### ModelConfiguration Pointing to Existing Core Data Store
|
|
226
|
+
|
|
227
|
+
Key rules for coexistence:
|
|
228
|
+
|
|
229
|
+
1. The `@Model` class name must match the Core Data entity name.
|
|
230
|
+
2. Property names and types must match exactly.
|
|
231
|
+
3. Use `@Attribute(originalName:)` if you renamed properties.
|
|
232
|
+
4. Both stacks should use the same store file.
|
|
233
|
+
|
|
234
|
+
```swift
|
|
235
|
+
// Core Data entity: CDTrip (entity name "Trip" in .xcdatamodeld)
|
|
236
|
+
// Attributes: name (String), destination (String), startDate (Date),
|
|
237
|
+
// isFavorite (Boolean), imageData (Binary Data)
|
|
238
|
+
|
|
239
|
+
// Matching SwiftData model
|
|
240
|
+
@Model
|
|
241
|
+
class Trip {
|
|
242
|
+
var name: String
|
|
243
|
+
var destination: String
|
|
244
|
+
var startDate: Date
|
|
245
|
+
var isFavorite: Bool = false
|
|
246
|
+
@Attribute(.externalStorage) var imageData: Data?
|
|
247
|
+
|
|
248
|
+
init(name: String, destination: String, startDate: Date) {
|
|
249
|
+
self.name = name
|
|
250
|
+
self.destination = destination
|
|
251
|
+
self.startDate = startDate
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Gradual Coexistence Strategy
|
|
257
|
+
|
|
258
|
+
```swift
|
|
259
|
+
// Phase 1: Core Data stack still handles writes;
|
|
260
|
+
// SwiftData reads the same store for new UI
|
|
261
|
+
@main
|
|
262
|
+
struct MyApp: App {
|
|
263
|
+
let coreDataStack = CoreDataStack.shared // Existing Core Data
|
|
264
|
+
|
|
265
|
+
var body: some Scene {
|
|
266
|
+
WindowGroup {
|
|
267
|
+
ContentView()
|
|
268
|
+
}
|
|
269
|
+
// SwiftData reads from the same store
|
|
270
|
+
.modelContainer(for: Trip.self, configurations:
|
|
271
|
+
ModelConfiguration(url: coreDataStack.storeURL)
|
|
272
|
+
)
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Phase 2: New features use SwiftData for both reads and writes
|
|
277
|
+
// Phase 3: Migrate remaining Core Data code to SwiftData
|
|
278
|
+
// Phase 4: Remove Core Data stack and .xcdatamodeld
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Important Coexistence Rules
|
|
282
|
+
|
|
283
|
+
- **Do not write to the same entity from both stacks simultaneously.** Pick
|
|
284
|
+
one stack per entity for writes to avoid conflicts.
|
|
285
|
+
- Core Data's `automaticallyMergesChangesFromParent` and
|
|
286
|
+
`NSPersistentStoreRemoteChangeNotification` help detect changes from the
|
|
287
|
+
other stack.
|
|
288
|
+
- Test thoroughly -- schema mismatches between the `.xcdatamodeld` and
|
|
289
|
+
`@Model` cause crashes.
|
|
290
|
+
|
|
291
|
+
## Migration from Core Data to SwiftData
|
|
292
|
+
|
|
293
|
+
### Step 1: Map Core Data Entities to @Model Classes
|
|
294
|
+
|
|
295
|
+
Create a `@Model` class for each Core Data entity. Property names and types
|
|
296
|
+
must align with the `.xcdatamodeld` definition.
|
|
297
|
+
|
|
298
|
+
```swift
|
|
299
|
+
// Core Data entity "Article"
|
|
300
|
+
// Attributes: id (UUID), title (String), body (String),
|
|
301
|
+
// createdAt (Date), isDraft (Boolean)
|
|
302
|
+
// Relationships: author (to-one → Author), tags (to-many → Tag)
|
|
303
|
+
|
|
304
|
+
@Model
|
|
305
|
+
class Article {
|
|
306
|
+
@Attribute(.unique) var id: UUID
|
|
307
|
+
var title: String
|
|
308
|
+
var body: String
|
|
309
|
+
var createdAt: Date
|
|
310
|
+
var isDraft: Bool = true
|
|
311
|
+
|
|
312
|
+
@Relationship(deleteRule: .nullify, inverse: \Author.articles)
|
|
313
|
+
var author: Author?
|
|
314
|
+
|
|
315
|
+
@Relationship(deleteRule: .nullify, inverse: \Tag.articles)
|
|
316
|
+
var tags: [Tag] = []
|
|
317
|
+
|
|
318
|
+
init(id: UUID = UUID(), title: String, body: String, createdAt: Date = .now) {
|
|
319
|
+
self.id = id
|
|
320
|
+
self.title = title
|
|
321
|
+
self.body = body
|
|
322
|
+
self.createdAt = createdAt
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
@Model
|
|
327
|
+
class Author {
|
|
328
|
+
@Attribute(.unique) var id: UUID
|
|
329
|
+
var name: String
|
|
330
|
+
var articles: [Article] = []
|
|
331
|
+
|
|
332
|
+
init(id: UUID = UUID(), name: String) {
|
|
333
|
+
self.id = id
|
|
334
|
+
self.name = name
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
@Model
|
|
339
|
+
class Tag {
|
|
340
|
+
@Attribute(.unique) var id: UUID
|
|
341
|
+
var name: String
|
|
342
|
+
var articles: [Article] = []
|
|
343
|
+
|
|
344
|
+
init(id: UUID = UUID(), name: String) {
|
|
345
|
+
self.id = id
|
|
346
|
+
self.name = name
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Type Mapping Reference
|
|
352
|
+
|
|
353
|
+
| Core Data Type | SwiftData Type |
|
|
354
|
+
|---|---|
|
|
355
|
+
| String | String |
|
|
356
|
+
| Boolean | Bool |
|
|
357
|
+
| Integer 16/32/64 | Int |
|
|
358
|
+
| Float / Double | Float / Double |
|
|
359
|
+
| Date | Date |
|
|
360
|
+
| Binary Data | Data |
|
|
361
|
+
| UUID | UUID |
|
|
362
|
+
| URI | URL |
|
|
363
|
+
| Decimal | Decimal |
|
|
364
|
+
| Transformable | Codable struct (composite, iOS 18+) |
|
|
365
|
+
| To-one relationship | Optional reference to @Model |
|
|
366
|
+
| To-many relationship | Array of @Model |
|
|
367
|
+
|
|
368
|
+
### Step 2: Schema Versioning Considerations
|
|
369
|
+
|
|
370
|
+
If the Core Data store has existing data, SwiftData must be able to open it.
|
|
371
|
+
Use `VersionedSchema` and `SchemaMigrationPlan` for non-trivial changes.
|
|
372
|
+
|
|
373
|
+
```swift
|
|
374
|
+
// If the SwiftData model exactly matches the Core Data schema,
|
|
375
|
+
// no migration is needed -- SwiftData opens the store directly.
|
|
376
|
+
|
|
377
|
+
// For schema differences, define versioned schemas:
|
|
378
|
+
enum SchemaV1: VersionedSchema {
|
|
379
|
+
static var versionIdentifier = Schema.Version(1, 0, 0)
|
|
380
|
+
static var models: [any PersistentModel.Type] { [Article.self, Author.self] }
|
|
381
|
+
|
|
382
|
+
@Model class Article {
|
|
383
|
+
var id: UUID
|
|
384
|
+
var title: String
|
|
385
|
+
var body: String
|
|
386
|
+
var createdAt: Date
|
|
387
|
+
init(id: UUID, title: String, body: String, createdAt: Date) {
|
|
388
|
+
self.id = id; self.title = title
|
|
389
|
+
self.body = body; self.createdAt = createdAt
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
@Model class Author {
|
|
394
|
+
var id: UUID
|
|
395
|
+
var name: String
|
|
396
|
+
init(id: UUID, name: String) { self.id = id; self.name = name }
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
enum SchemaV2: VersionedSchema {
|
|
401
|
+
static var versionIdentifier = Schema.Version(2, 0, 0)
|
|
402
|
+
static var models: [any PersistentModel.Type] { [Article.self, Author.self, Tag.self] }
|
|
403
|
+
|
|
404
|
+
@Model class Article {
|
|
405
|
+
var id: UUID
|
|
406
|
+
var title: String
|
|
407
|
+
var body: String
|
|
408
|
+
var createdAt: Date
|
|
409
|
+
var isDraft: Bool = true // New property
|
|
410
|
+
init(id: UUID, title: String, body: String, createdAt: Date) {
|
|
411
|
+
self.id = id; self.title = title
|
|
412
|
+
self.body = body; self.createdAt = createdAt
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
@Model class Author {
|
|
417
|
+
var id: UUID
|
|
418
|
+
var name: String
|
|
419
|
+
init(id: UUID, name: String) { self.id = id; self.name = name }
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
@Model class Tag {
|
|
423
|
+
var id: UUID
|
|
424
|
+
var name: String
|
|
425
|
+
init(id: UUID, name: String) { self.id = id; self.name = name }
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
enum ArticleMigrationPlan: SchemaMigrationPlan {
|
|
430
|
+
static var schemas: [any VersionedSchema.Type] { [SchemaV1.self, SchemaV2.self] }
|
|
431
|
+
static var stages: [MigrationStage] {
|
|
432
|
+
[MigrationStage.lightweight(fromVersion: SchemaV1.self, toVersion: SchemaV2.self)]
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### Step 3: Testing Migration Paths
|
|
438
|
+
|
|
439
|
+
Always test migration with real production data copies before shipping.
|
|
440
|
+
|
|
441
|
+
```swift
|
|
442
|
+
import XCTest
|
|
443
|
+
import SwiftData
|
|
444
|
+
|
|
445
|
+
final class MigrationTests: XCTestCase {
|
|
446
|
+
|
|
447
|
+
func testCoreDataToSwiftDataMigration() throws {
|
|
448
|
+
// 1. Copy a known Core Data store into the test bundle
|
|
449
|
+
let sourceURL = Bundle(for: type(of: self))
|
|
450
|
+
.url(forResource: "TestStore", withExtension: "sqlite")!
|
|
451
|
+
|
|
452
|
+
let tempDir = FileManager.default.temporaryDirectory
|
|
453
|
+
.appendingPathComponent(UUID().uuidString)
|
|
454
|
+
try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)
|
|
455
|
+
|
|
456
|
+
let destURL = tempDir.appendingPathComponent("TestStore.sqlite")
|
|
457
|
+
try FileManager.default.copyItem(at: sourceURL, to: destURL)
|
|
458
|
+
|
|
459
|
+
// Copy WAL and SHM if they exist
|
|
460
|
+
for ext in ["-wal", "-shm"] {
|
|
461
|
+
let src = sourceURL.deletingLastPathComponent()
|
|
462
|
+
.appendingPathComponent("TestStore.sqlite\(ext)")
|
|
463
|
+
if FileManager.default.fileExists(atPath: src.path) {
|
|
464
|
+
try FileManager.default.copyItem(
|
|
465
|
+
at: src,
|
|
466
|
+
to: tempDir.appendingPathComponent("TestStore.sqlite\(ext)")
|
|
467
|
+
)
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// 2. Open with SwiftData
|
|
472
|
+
let config = ModelConfiguration(url: destURL)
|
|
473
|
+
let container = try ModelContainer(
|
|
474
|
+
for: SchemaV2.Article.self,
|
|
475
|
+
migrationPlan: ArticleMigrationPlan.self,
|
|
476
|
+
configurations: config
|
|
477
|
+
)
|
|
478
|
+
|
|
479
|
+
// 3. Verify data survived migration
|
|
480
|
+
let context = ModelContext(container)
|
|
481
|
+
let articles = try context.fetch(FetchDescriptor<SchemaV2.Article>())
|
|
482
|
+
XCTAssertFalse(articles.isEmpty, "Migration should preserve existing articles")
|
|
483
|
+
|
|
484
|
+
// 4. Verify new properties have defaults
|
|
485
|
+
for article in articles {
|
|
486
|
+
XCTAssertTrue(article.isDraft, "New isDraft property should default to true")
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// Cleanup
|
|
490
|
+
try FileManager.default.removeItem(at: tempDir)
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
### Migration Checklist
|
|
496
|
+
|
|
497
|
+
- [ ] Every Core Data entity has a matching `@Model` class with identical property names and types
|
|
498
|
+
- [ ] Relationship inverse properties are specified in both directions
|
|
499
|
+
- [ ] `VersionedSchema` and `SchemaMigrationPlan` defined for non-trivial schema changes
|
|
500
|
+
- [ ] `ModelConfiguration` points to the existing Core Data SQLite file
|
|
501
|
+
- [ ] Tested migration with a copy of production data
|
|
502
|
+
- [ ] Only one stack writes to each entity during coexistence
|
|
503
|
+
- [ ] `automaticallyMergesChangesFromParent` enabled on Core Data's `viewContext`
|
|
504
|
+
- [ ] `.xcdatamodeld` removed only after full migration is verified
|