buildanything 1.7.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +9 -3
- package/CHANGELOG.md +112 -0
- package/README.md +2 -2
- package/agents/a11y-architect.md +166 -0
- package/agents/business-model.md +80 -29
- package/agents/code-architect.md +75 -0
- package/agents/code-reviewer.md +255 -0
- package/agents/code-simplifier.md +64 -0
- package/agents/design-brand-guardian.md +293 -53
- package/agents/design-critic.md +139 -0
- package/agents/design-inclusive-visuals-specialist.md +6 -19
- package/agents/design-ui-designer.md +335 -56
- package/agents/design-ux-architect.md +403 -55
- package/agents/design-ux-researcher.md +264 -49
- package/agents/engineering-ai-engineer.md +26 -36
- package/agents/engineering-backend-architect.md +185 -36
- package/agents/engineering-data-engineer.md +225 -43
- package/agents/engineering-devops-automator.md +227 -74
- package/agents/engineering-frontend-developer.md +210 -34
- package/agents/engineering-mobile-app-builder.md +6 -1
- package/agents/engineering-rapid-prototyper.md +30 -9
- package/agents/engineering-security-engineer.md +263 -61
- package/agents/engineering-senior-developer.md +128 -19
- package/agents/engineering-sre.md +84 -0
- package/agents/engineering-technical-writer.md +285 -41
- package/agents/feature-intel.md +110 -0
- package/agents/ios-app-review-guardian.md +66 -0
- package/agents/ios-foundation-models-specialist.md +64 -0
- package/agents/ios-storekit-specialist.md +59 -0
- package/agents/ios-swift-architect.md +129 -0
- package/agents/ios-swift-search.md +137 -0
- package/agents/ios-swift-ui-design.md +136 -0
- package/agents/marketing-app-store-optimizer.md +246 -64
- package/agents/planner.md +216 -0
- package/agents/pr-test-analyzer.md +63 -0
- package/agents/product-feedback-synthesizer.md +8 -2
- package/agents/refactor-cleaner.md +102 -0
- package/agents/security-reviewer.md +128 -0
- package/agents/silent-failure-hunter.md +54 -0
- package/agents/swift-build-resolver.md +119 -0
- package/agents/swift-reviewer.md +112 -0
- package/agents/tech-feasibility.md +21 -1
- package/agents/testing-api-tester.md +236 -59
- package/agents/testing-evidence-collector.md +26 -1
- package/agents/testing-performance-benchmarker.md +21 -1
- package/agents/testing-reality-checker.md +6 -1
- package/agents/visual-research.md +116 -0
- package/bin/adapters/cycle-counter-tool.ts +155 -0
- package/bin/adapters/scribe-tool.ts +71 -0
- package/bin/adapters/state-save-tool.ts +130 -0
- package/bin/adapters/write-lease-tool.ts +127 -0
- package/bin/buildanything-runtime.js +15 -0
- package/bin/buildanything-runtime.ts +328 -0
- package/bin/setup.js +83 -8
- package/commands/add-feature.md +2 -0
- package/commands/build.md +752 -332
- package/commands/fix.md +65 -0
- package/commands/self-check.md +121 -0
- package/commands/setup.md +114 -0
- package/commands/ux-review.md +63 -0
- package/commands/verify.md +69 -0
- package/docs/migration/agents.yaml +729 -0
- package/docs/migration/phase-graph.yaml +1088 -0
- package/docs/migration/sdk-host-compat.md +18 -0
- package/hooks/compile-writer-owner-cache.ts +171 -0
- package/hooks/hooks.json +36 -0
- package/hooks/pre-tool-use +19 -0
- package/hooks/pre-tool-use.ts +776 -0
- package/hooks/record-mode-transitions.ts +178 -0
- package/hooks/session-start +89 -2
- package/hooks/subagent-start +17 -0
- package/hooks/subagent-start.ts +471 -0
- package/hooks/subagent-stop +17 -0
- package/hooks/subagent-stop.ts +153 -0
- package/package.json +28 -5
- package/protocols/architecture-schema.md +171 -0
- package/protocols/build-fix.md +52 -0
- package/protocols/cleanup.md +54 -0
- package/protocols/decision-log.md +131 -0
- package/protocols/eval-harness.md +61 -0
- package/protocols/fake-data-detector.md +64 -0
- package/protocols/ios-context.md +234 -0
- package/protocols/ios-frameworks-map.md +323 -0
- package/protocols/ios-phase-branches.md +337 -0
- package/protocols/ios-preflight.md +27 -0
- package/protocols/launch-readiness.md +258 -0
- package/protocols/metric-loop.md +153 -0
- package/protocols/smoke-test.md +118 -0
- package/protocols/state-schema.json +388 -0
- package/protocols/state-schema.md +172 -0
- package/protocols/verify.md +127 -0
- package/protocols/visual-dna.md +185 -0
- package/protocols/web-phase-branches.md +351 -0
- package/skills/ios/_VENDORED.md +62 -0
- package/skills/ios/activitykit/LICENSE +131 -0
- package/skills/ios/activitykit/SKILL.md +505 -0
- package/skills/ios/activitykit/references/activitykit-patterns.md +868 -0
- package/skills/ios/app-intents/LICENSE +131 -0
- package/skills/ios/app-intents/SKILL.md +494 -0
- package/skills/ios/app-intents/references/appintents-advanced.md +1076 -0
- package/skills/ios/app-store-connect-metadata/SKILL.md +148 -0
- package/skills/ios/apple-on-device-ai/LICENSE +131 -0
- package/skills/ios/apple-on-device-ai/SKILL.md +505 -0
- package/skills/ios/apple-on-device-ai/references/coreml-conversion.md +425 -0
- package/skills/ios/apple-on-device-ai/references/coreml-optimization.md +344 -0
- package/skills/ios/apple-on-device-ai/references/foundation-models.md +508 -0
- package/skills/ios/apple-on-device-ai/references/mlx-swift.md +285 -0
- package/skills/ios/asc-privacy-manifest/SKILL.md +350 -0
- package/skills/ios/hig-components-content/SKILL.md +86 -0
- package/skills/ios/hig-components-content/references/activity-views.md +79 -0
- package/skills/ios/hig-components-content/references/charts.md +180 -0
- package/skills/ios/hig-components-content/references/collections.md +48 -0
- package/skills/ios/hig-components-content/references/color-wells.md +42 -0
- package/skills/ios/hig-components-content/references/image-views.md +82 -0
- package/skills/ios/hig-components-content/references/image-wells.md +34 -0
- package/skills/ios/hig-components-content/references/lockups.md +78 -0
- package/skills/ios/hig-components-content/references/web-views.md +36 -0
- package/skills/ios/hig-components-controls/SKILL.md +88 -0
- package/skills/ios/hig-components-controls/references/combo-boxes.md +40 -0
- package/skills/ios/hig-components-controls/references/controls.md +112 -0
- package/skills/ios/hig-components-controls/references/gauges.md +74 -0
- package/skills/ios/hig-components-controls/references/labels.md +92 -0
- package/skills/ios/hig-components-controls/references/pickers.md +128 -0
- package/skills/ios/hig-components-controls/references/rating-indicators.md +38 -0
- package/skills/ios/hig-components-controls/references/segmented-controls.md +94 -0
- package/skills/ios/hig-components-controls/references/sliders.md +92 -0
- package/skills/ios/hig-components-controls/references/steppers.md +40 -0
- package/skills/ios/hig-components-controls/references/text-fields.md +88 -0
- package/skills/ios/hig-components-controls/references/text-views.md +56 -0
- package/skills/ios/hig-components-controls/references/toggles.md +127 -0
- package/skills/ios/hig-components-controls/references/token-fields.md +48 -0
- package/skills/ios/hig-components-controls/references/virtual-keyboards.md +156 -0
- package/skills/ios/hig-components-dialogs/SKILL.md +76 -0
- package/skills/ios/hig-components-dialogs/references/action-sheets.md +74 -0
- package/skills/ios/hig-components-dialogs/references/alerts.md +158 -0
- package/skills/ios/hig-components-dialogs/references/digit-entry-views.md +32 -0
- package/skills/ios/hig-components-dialogs/references/popovers.md +81 -0
- package/skills/ios/hig-components-dialogs/references/sheets.md +157 -0
- package/skills/ios/hig-components-layout/SKILL.md +99 -0
- package/skills/ios/hig-components-layout/references/boxes.md +48 -0
- package/skills/ios/hig-components-layout/references/column-views.md +44 -0
- package/skills/ios/hig-components-layout/references/lists-and-tables.md +99 -0
- package/skills/ios/hig-components-layout/references/ornaments.md +56 -0
- package/skills/ios/hig-components-layout/references/outline-views.md +64 -0
- package/skills/ios/hig-components-layout/references/panels.md +75 -0
- package/skills/ios/hig-components-layout/references/scroll-views.md +123 -0
- package/skills/ios/hig-components-layout/references/sidebars.md +109 -0
- package/skills/ios/hig-components-layout/references/split-views.md +110 -0
- package/skills/ios/hig-components-layout/references/tab-bars.md +173 -0
- package/skills/ios/hig-components-layout/references/tab-views.md +68 -0
- package/skills/ios/hig-components-layout/references/windows.md +188 -0
- package/skills/ios/hig-components-menus/SKILL.md +81 -0
- package/skills/ios/hig-components-menus/references/action-button.md +61 -0
- package/skills/ios/hig-components-menus/references/buttons.md +261 -0
- package/skills/ios/hig-components-menus/references/context-menus.md +105 -0
- package/skills/ios/hig-components-menus/references/disclosure-controls.md +84 -0
- package/skills/ios/hig-components-menus/references/dock-menus.md +40 -0
- package/skills/ios/hig-components-menus/references/edit-menus.md +88 -0
- package/skills/ios/hig-components-menus/references/menus.md +171 -0
- package/skills/ios/hig-components-menus/references/pop-up-buttons.md +70 -0
- package/skills/ios/hig-components-menus/references/pull-down-buttons.md +77 -0
- package/skills/ios/hig-components-menus/references/the-menu-bar.md +303 -0
- package/skills/ios/hig-components-menus/references/toolbars.md +256 -0
- package/skills/ios/hig-components-search/SKILL.md +68 -0
- package/skills/ios/hig-components-search/references/page-controls.md +120 -0
- package/skills/ios/hig-components-search/references/path-controls.md +40 -0
- package/skills/ios/hig-components-search/references/search-fields.md +189 -0
- package/skills/ios/hig-components-status/SKILL.md +80 -0
- package/skills/ios/hig-components-status/references/activity-rings.md +105 -0
- package/skills/ios/hig-components-status/references/progress-indicators.md +116 -0
- package/skills/ios/hig-components-status/references/status-bars.md +38 -0
- package/skills/ios/hig-components-system/SKILL.md +88 -0
- package/skills/ios/hig-components-system/references/app-clips.md +387 -0
- package/skills/ios/hig-components-system/references/app-shortcuts.md +114 -0
- package/skills/ios/hig-components-system/references/complications.md +425 -0
- package/skills/ios/hig-components-system/references/home-screen-quick-actions.md +42 -0
- package/skills/ios/hig-components-system/references/live-activities.md +442 -0
- package/skills/ios/hig-components-system/references/notifications.md +153 -0
- package/skills/ios/hig-components-system/references/top-shelf.md +135 -0
- package/skills/ios/hig-components-system/references/watch-faces.md +40 -0
- package/skills/ios/hig-components-system/references/widgets.md +517 -0
- package/skills/ios/hig-foundations/SKILL.md +98 -0
- package/skills/ios/hig-foundations/references/accessibility.md +291 -0
- package/skills/ios/hig-foundations/references/app-icons.md +210 -0
- package/skills/ios/hig-foundations/references/branding.md +44 -0
- package/skills/ios/hig-foundations/references/color.md +274 -0
- package/skills/ios/hig-foundations/references/dark-mode.md +116 -0
- package/skills/ios/hig-foundations/references/icons.md +263 -0
- package/skills/ios/hig-foundations/references/images.md +176 -0
- package/skills/ios/hig-foundations/references/immersive-experiences.md +174 -0
- package/skills/ios/hig-foundations/references/inclusion.md +189 -0
- package/skills/ios/hig-foundations/references/layout.md +425 -0
- package/skills/ios/hig-foundations/references/materials.md +238 -0
- package/skills/ios/hig-foundations/references/motion.md +103 -0
- package/skills/ios/hig-foundations/references/privacy.md +231 -0
- package/skills/ios/hig-foundations/references/right-to-left.md +206 -0
- package/skills/ios/hig-foundations/references/sf-symbols.md +310 -0
- package/skills/ios/hig-foundations/references/spatial-layout.md +142 -0
- package/skills/ios/hig-foundations/references/typography.md +1146 -0
- package/skills/ios/hig-foundations/references/writing.md +91 -0
- package/skills/ios/hig-inputs/SKILL.md +94 -0
- package/skills/ios/hig-inputs/references/apple-pencil-and-scribble.md +148 -0
- package/skills/ios/hig-inputs/references/camera-control.md +107 -0
- package/skills/ios/hig-inputs/references/digital-crown.md +83 -0
- package/skills/ios/hig-inputs/references/eyes.md +120 -0
- package/skills/ios/hig-inputs/references/focus-and-selection.md +120 -0
- package/skills/ios/hig-inputs/references/game-controls.md +156 -0
- package/skills/ios/hig-inputs/references/gestures.md +208 -0
- package/skills/ios/hig-inputs/references/gyro-and-accelerometer.md +40 -0
- package/skills/ios/hig-inputs/references/keyboards.md +234 -0
- package/skills/ios/hig-inputs/references/nearby-interactions.md +70 -0
- package/skills/ios/hig-inputs/references/pointing-devices.md +237 -0
- package/skills/ios/hig-inputs/references/remotes.md +67 -0
- package/skills/ios/hig-inputs/references/spatial-interactions.md +70 -0
- package/skills/ios/hig-patterns/SKILL.md +104 -0
- package/skills/ios/hig-patterns/references/charting-data.md +81 -0
- package/skills/ios/hig-patterns/references/collaboration-and-sharing.md +86 -0
- package/skills/ios/hig-patterns/references/drag-and-drop.md +134 -0
- package/skills/ios/hig-patterns/references/entering-data.md +69 -0
- package/skills/ios/hig-patterns/references/feedback.md +67 -0
- package/skills/ios/hig-patterns/references/file-management.md +135 -0
- package/skills/ios/hig-patterns/references/going-full-screen.md +79 -0
- package/skills/ios/hig-patterns/references/launching.md +81 -0
- package/skills/ios/hig-patterns/references/live-viewing-apps.md +79 -0
- package/skills/ios/hig-patterns/references/loading.md +59 -0
- package/skills/ios/hig-patterns/references/managing-accounts.md +107 -0
- package/skills/ios/hig-patterns/references/managing-notifications.md +99 -0
- package/skills/ios/hig-patterns/references/modality.md +82 -0
- package/skills/ios/hig-patterns/references/multitasking.md +131 -0
- package/skills/ios/hig-patterns/references/offering-help.md +117 -0
- package/skills/ios/hig-patterns/references/onboarding.md +69 -0
- package/skills/ios/hig-patterns/references/playing-audio.md +124 -0
- package/skills/ios/hig-patterns/references/playing-haptics.md +280 -0
- package/skills/ios/hig-patterns/references/playing-video.md +180 -0
- package/skills/ios/hig-patterns/references/printing.md +50 -0
- package/skills/ios/hig-patterns/references/ratings-and-reviews.md +48 -0
- package/skills/ios/hig-patterns/references/searching.md +70 -0
- package/skills/ios/hig-patterns/references/settings.md +84 -0
- package/skills/ios/hig-patterns/references/undo-and-redo.md +58 -0
- package/skills/ios/hig-patterns/references/workouts.md +76 -0
- package/skills/ios/hig-platforms/SKILL.md +84 -0
- package/skills/ios/hig-platforms/references/designing-for-games.md +159 -0
- package/skills/ios/hig-platforms/references/designing-for-ios.md +66 -0
- package/skills/ios/hig-platforms/references/designing-for-ipados.md +64 -0
- package/skills/ios/hig-platforms/references/designing-for-macos.md +70 -0
- package/skills/ios/hig-platforms/references/designing-for-tvos.md +68 -0
- package/skills/ios/hig-platforms/references/designing-for-visionos.md +85 -0
- package/skills/ios/hig-platforms/references/designing-for-watchos.md +74 -0
- package/skills/ios/hig-project-context/SKILL.md +133 -0
- package/skills/ios/hig-technologies/SKILL.md +107 -0
- package/skills/ios/hig-technologies/references/airplay.md +125 -0
- package/skills/ios/hig-technologies/references/always-on.md +62 -0
- package/skills/ios/hig-technologies/references/apple-pay.md +441 -0
- package/skills/ios/hig-technologies/references/augmented-reality.md +247 -0
- package/skills/ios/hig-technologies/references/carekit.md +224 -0
- package/skills/ios/hig-technologies/references/carplay.md +119 -0
- package/skills/ios/hig-technologies/references/game-center.md +343 -0
- package/skills/ios/hig-technologies/references/generative-ai.md +110 -0
- package/skills/ios/hig-technologies/references/healthkit.md +120 -0
- package/skills/ios/hig-technologies/references/homekit.md +343 -0
- package/skills/ios/hig-technologies/references/icloud.md +52 -0
- package/skills/ios/hig-technologies/references/id-verifier.md +73 -0
- package/skills/ios/hig-technologies/references/imessage-apps-and-stickers.md +105 -0
- package/skills/ios/hig-technologies/references/in-app-purchase.md +263 -0
- package/skills/ios/hig-technologies/references/live-photos.md +54 -0
- package/skills/ios/hig-technologies/references/mac-catalyst.md +216 -0
- package/skills/ios/hig-technologies/references/machine-learning.md +394 -0
- package/skills/ios/hig-technologies/references/maps.md +221 -0
- package/skills/ios/hig-technologies/references/nfc.md +51 -0
- package/skills/ios/hig-technologies/references/photo-editing.md +40 -0
- package/skills/ios/hig-technologies/references/researchkit.md +134 -0
- package/skills/ios/hig-technologies/references/shareplay.md +142 -0
- package/skills/ios/hig-technologies/references/shazamkit.md +47 -0
- package/skills/ios/hig-technologies/references/sign-in-with-apple.md +288 -0
- package/skills/ios/hig-technologies/references/siri.md +523 -0
- package/skills/ios/hig-technologies/references/tap-to-pay-on-iphone.md +208 -0
- package/skills/ios/hig-technologies/references/voiceover.md +90 -0
- package/skills/ios/hig-technologies/references/wallet.md +420 -0
- package/skills/ios/ios-26-platform/SKILL.md +53 -0
- package/skills/ios/ios-26-platform/references/automatic-adoption.md +161 -0
- package/skills/ios/ios-26-platform/references/backward-compat.md +238 -0
- package/skills/ios/ios-26-platform/references/liquid-glass.md +255 -0
- package/skills/ios/ios-26-platform/references/swiftui-apis.md +277 -0
- package/skills/ios/ios-26-platform/references/toolbar-navigation.md +250 -0
- package/skills/ios/ios-bootstrap/SKILL.md +107 -0
- package/skills/ios/ios-bootstrap/references/apple-docs-mcp-config.md +28 -0
- package/skills/ios/ios-bootstrap/references/new-project-dialog.md +41 -0
- package/skills/ios/ios-bootstrap/references/xcode-mcp-config.md +29 -0
- package/skills/ios/ios-debugger-agent/LICENSE +21 -0
- package/skills/ios/ios-debugger-agent/SKILL.md +58 -0
- package/skills/ios/ios-debugger-agent/agents/openai.yaml +4 -0
- package/skills/ios/ios-entitlements-generator/SKILL.md +47 -0
- package/skills/ios/ios-info-plist-hardening/SKILL.md +130 -0
- package/skills/ios/ios-maestro-flow-author/SKILL.md +68 -0
- package/skills/ios/ios-maestro-flow-author/references/input-and-scroll.yaml +17 -0
- package/skills/ios/ios-maestro-flow-author/references/modal-and-dismiss.yaml +14 -0
- package/skills/ios/ios-maestro-flow-author/references/onboarding-flow.yaml +16 -0
- package/skills/ios/ios-maestro-flow-author/references/tab-navigation.yaml +13 -0
- package/skills/ios/ios-maestro-flow-author/references/tap-and-assert.yaml +9 -0
- package/skills/ios/swift-accessibility/LICENSE +21 -0
- package/skills/ios/swift-accessibility/SKILL.md +371 -0
- package/skills/ios/swift-accessibility/examples/before-after-appkit.md +446 -0
- package/skills/ios/swift-accessibility/examples/before-after-swiftui.md +441 -0
- package/skills/ios/swift-accessibility/examples/before-after-uikit.md +464 -0
- package/skills/ios/swift-accessibility/references/assistive-access.md +441 -0
- package/skills/ios/swift-accessibility/references/display-settings.md +491 -0
- package/skills/ios/swift-accessibility/references/dynamic-type.md +420 -0
- package/skills/ios/swift-accessibility/references/media-accessibility.md +421 -0
- package/skills/ios/swift-accessibility/references/motor-input.md +393 -0
- package/skills/ios/swift-accessibility/references/nutrition-labels.md +362 -0
- package/skills/ios/swift-accessibility/references/platform-specifics.md +515 -0
- package/skills/ios/swift-accessibility/references/semantic-structure.md +585 -0
- package/skills/ios/swift-accessibility/references/testing-auditing.md +507 -0
- package/skills/ios/swift-accessibility/references/voice-control.md +317 -0
- package/skills/ios/swift-accessibility/references/voiceover-swiftui.md +584 -0
- package/skills/ios/swift-accessibility/references/voiceover-uikit.md +519 -0
- package/skills/ios/swift-accessibility/references/wcag-mapping.md +167 -0
- package/skills/ios/swift-accessibility/resources/audit-template.swift +128 -0
- package/skills/ios/swift-accessibility/resources/qa-checklist.md +258 -0
- package/skills/ios/swift-actor-persistence/SKILL.md +143 -0
- package/skills/ios/swift-concurrency/LICENSE +21 -0
- package/skills/ios/swift-concurrency/SKILL.md +171 -0
- package/skills/ios/swift-concurrency/references/_index.md +50 -0
- package/skills/ios/swift-concurrency/references/actors.md +660 -0
- package/skills/ios/swift-concurrency/references/async-algorithms.md +847 -0
- package/skills/ios/swift-concurrency/references/async-await-basics.md +266 -0
- package/skills/ios/swift-concurrency/references/async-sequences.md +710 -0
- package/skills/ios/swift-concurrency/references/core-data.md +560 -0
- package/skills/ios/swift-concurrency/references/glossary.md +135 -0
- package/skills/ios/swift-concurrency/references/linting.md +155 -0
- package/skills/ios/swift-concurrency/references/memory-management.md +569 -0
- package/skills/ios/swift-concurrency/references/migration.md +1104 -0
- package/skills/ios/swift-concurrency/references/performance.md +593 -0
- package/skills/ios/swift-concurrency/references/sendable.md +598 -0
- package/skills/ios/swift-concurrency/references/tasks.md +636 -0
- package/skills/ios/swift-concurrency/references/testing.md +592 -0
- package/skills/ios/swift-concurrency/references/threading.md +495 -0
- package/skills/ios/swift-concurrency-6-2/SKILL.md +216 -0
- package/skills/ios/swift-protocol-di-testing/SKILL.md +190 -0
- package/skills/ios/swift-security-expert/LICENSE +21 -0
- package/skills/ios/swift-security-expert/SKILL.md +470 -0
- package/skills/ios/swift-security-expert/references/biometric-authentication.md +565 -0
- package/skills/ios/swift-security-expert/references/certificate-trust.md +592 -0
- package/skills/ios/swift-security-expert/references/common-anti-patterns.md +690 -0
- package/skills/ios/swift-security-expert/references/compliance-owasp-mapping.md +537 -0
- package/skills/ios/swift-security-expert/references/credential-storage-patterns.md +721 -0
- package/skills/ios/swift-security-expert/references/cryptokit-public-key.md +505 -0
- package/skills/ios/swift-security-expert/references/cryptokit-symmetric.md +497 -0
- package/skills/ios/swift-security-expert/references/keychain-access-control.md +508 -0
- package/skills/ios/swift-security-expert/references/keychain-fundamentals.md +596 -0
- package/skills/ios/swift-security-expert/references/keychain-item-classes.md +476 -0
- package/skills/ios/swift-security-expert/references/keychain-sharing.md +458 -0
- package/skills/ios/swift-security-expert/references/migration-legacy-stores.md +727 -0
- package/skills/ios/swift-security-expert/references/secure-enclave.md +539 -0
- package/skills/ios/swift-security-expert/references/testing-security-code.md +781 -0
- package/skills/ios/swift-testing-expert/LICENSE +21 -0
- package/skills/ios/swift-testing-expert/SKILL.md +79 -0
- package/skills/ios/swift-testing-expert/references/_index.md +12 -0
- package/skills/ios/swift-testing-expert/references/async-testing-and-waiting.md +127 -0
- package/skills/ios/swift-testing-expert/references/expectations.md +145 -0
- package/skills/ios/swift-testing-expert/references/fundamentals.md +141 -0
- package/skills/ios/swift-testing-expert/references/migration-from-xctest.md +127 -0
- package/skills/ios/swift-testing-expert/references/parallelization-and-isolation.md +95 -0
- package/skills/ios/swift-testing-expert/references/parameterized-testing.md +284 -0
- package/skills/ios/swift-testing-expert/references/performance-and-best-practices.md +187 -0
- package/skills/ios/swift-testing-expert/references/traits-and-tags.md +114 -0
- package/skills/ios/swift-testing-expert/references/xcode-workflows.md +70 -0
- package/skills/ios/swiftdata-pro/LICENSE +21 -0
- package/skills/ios/swiftdata-pro/SKILL.md +102 -0
- package/skills/ios/swiftdata-pro/agents/openai.yaml +10 -0
- package/skills/ios/swiftdata-pro/assets/swiftdata-pro-icon.png +0 -0
- package/skills/ios/swiftdata-pro/assets/swiftdata-pro-icon.svg +29 -0
- package/skills/ios/swiftdata-pro/references/class-inheritance.md +104 -0
- package/skills/ios/swiftdata-pro/references/cloudkit.md +10 -0
- package/skills/ios/swiftdata-pro/references/core-rules.md +20 -0
- package/skills/ios/swiftdata-pro/references/indexing.md +27 -0
- package/skills/ios/swiftdata-pro/references/predicates.md +73 -0
- package/skills/ios/swiftui-design-principles/AGENTS.md +21 -0
- package/skills/ios/swiftui-design-principles/LICENSE +21 -0
- package/skills/ios/swiftui-design-principles/README.md +41 -0
- package/skills/ios/swiftui-design-principles/SKILL.md +605 -0
- package/skills/ios/swiftui-design-principles/metadata.json +10 -0
- package/skills/ios/swiftui-design-tokens/SKILL.md +475 -0
- package/skills/ios/swiftui-liquid-glass/LICENSE +21 -0
- package/skills/ios/swiftui-liquid-glass/SKILL.md +95 -0
- package/skills/ios/swiftui-liquid-glass/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-liquid-glass/references/liquid-glass.md +280 -0
- package/skills/ios/swiftui-performance-audit/LICENSE +21 -0
- package/skills/ios/swiftui-performance-audit/SKILL.md +111 -0
- package/skills/ios/swiftui-performance-audit/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-performance-audit/references/code-smells.md +150 -0
- package/skills/ios/swiftui-performance-audit/references/demystify-swiftui-performance-wwdc23.md +46 -0
- package/skills/ios/swiftui-performance-audit/references/optimizing-swiftui-performance-instruments.md +29 -0
- package/skills/ios/swiftui-performance-audit/references/profiling-intake.md +44 -0
- package/skills/ios/swiftui-performance-audit/references/report-template.md +47 -0
- package/skills/ios/swiftui-performance-audit/references/understanding-hangs-in-your-app.md +33 -0
- package/skills/ios/swiftui-performance-audit/references/understanding-improving-swiftui-performance.md +52 -0
- package/skills/ios/swiftui-pro/LICENSE +21 -0
- package/skills/ios/swiftui-pro/SKILL.md +108 -0
- package/skills/ios/swiftui-pro/agents/openai.yaml +10 -0
- package/skills/ios/swiftui-pro/assets/swiftui-pro-icon.png +0 -0
- package/skills/ios/swiftui-pro/assets/swiftui-pro-icon.svg +29 -0
- package/skills/ios/swiftui-pro/references/accessibility.md +13 -0
- package/skills/ios/swiftui-pro/references/api.md +39 -0
- package/skills/ios/swiftui-pro/references/data.md +43 -0
- package/skills/ios/swiftui-pro/references/design.md +31 -0
- package/skills/ios/swiftui-pro/references/hygiene.md +9 -0
- package/skills/ios/swiftui-pro/references/navigation.md +14 -0
- package/skills/ios/swiftui-pro/references/performance.md +46 -0
- package/skills/ios/swiftui-pro/references/swift.md +56 -0
- package/skills/ios/swiftui-pro/references/views.md +35 -0
- package/skills/ios/swiftui-ui-patterns/LICENSE +21 -0
- package/skills/ios/swiftui-ui-patterns/SKILL.md +100 -0
- package/skills/ios/swiftui-ui-patterns/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-ui-patterns/references/app-wiring.md +201 -0
- package/skills/ios/swiftui-ui-patterns/references/async-state.md +96 -0
- package/skills/ios/swiftui-ui-patterns/references/components-index.md +50 -0
- package/skills/ios/swiftui-ui-patterns/references/controls.md +57 -0
- package/skills/ios/swiftui-ui-patterns/references/deeplinks.md +66 -0
- package/skills/ios/swiftui-ui-patterns/references/focus.md +90 -0
- package/skills/ios/swiftui-ui-patterns/references/form.md +97 -0
- package/skills/ios/swiftui-ui-patterns/references/grids.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/haptics.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/input-toolbar.md +51 -0
- package/skills/ios/swiftui-ui-patterns/references/lightweight-clients.md +93 -0
- package/skills/ios/swiftui-ui-patterns/references/list.md +86 -0
- package/skills/ios/swiftui-ui-patterns/references/loading-placeholders.md +38 -0
- package/skills/ios/swiftui-ui-patterns/references/macos-settings.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/matched-transitions.md +59 -0
- package/skills/ios/swiftui-ui-patterns/references/media.md +73 -0
- package/skills/ios/swiftui-ui-patterns/references/menu-bar.md +101 -0
- package/skills/ios/swiftui-ui-patterns/references/navigationstack.md +159 -0
- package/skills/ios/swiftui-ui-patterns/references/overlay.md +45 -0
- package/skills/ios/swiftui-ui-patterns/references/performance.md +62 -0
- package/skills/ios/swiftui-ui-patterns/references/previews.md +48 -0
- package/skills/ios/swiftui-ui-patterns/references/scroll-reveal.md +133 -0
- package/skills/ios/swiftui-ui-patterns/references/scrollview.md +87 -0
- package/skills/ios/swiftui-ui-patterns/references/searchable.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/sheets.md +155 -0
- package/skills/ios/swiftui-ui-patterns/references/split-views.md +72 -0
- package/skills/ios/swiftui-ui-patterns/references/tabview.md +114 -0
- package/skills/ios/swiftui-ui-patterns/references/theming.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/title-menus.md +93 -0
- package/skills/ios/swiftui-ui-patterns/references/top-bar.md +49 -0
- package/skills/ios/swiftui-view-refactor/LICENSE +21 -0
- package/skills/ios/swiftui-view-refactor/SKILL.md +207 -0
- package/skills/ios/swiftui-view-refactor/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-view-refactor/references/mv-patterns.md +161 -0
- package/skills/ios/widgetkit/LICENSE +131 -0
- package/skills/ios/widgetkit/SKILL.md +502 -0
- package/skills/ios/widgetkit/references/widgetkit-advanced.md +871 -0
- package/skills/ios/writing-for-interfaces/SKILL.md +75 -0
- package/skills/web/accessibility/SKILL.md +146 -0
- package/skills/web/aceternity-ui/SKILL.md +719 -0
- package/skills/web/aceternity-ui/metadata.json +10 -0
- package/skills/web/api-design/SKILL.md +523 -0
- package/skills/web/chart-accessibility/SKILL.md +332 -0
- package/skills/web/composition-patterns/AGENTS.md +946 -0
- package/skills/web/composition-patterns/README.md +60 -0
- package/skills/web/composition-patterns/SKILL.md +89 -0
- package/skills/web/composition-patterns/metadata.json +11 -0
- package/skills/web/composition-patterns/rules/_sections.md +29 -0
- package/skills/web/composition-patterns/rules/_template.md +24 -0
- package/skills/web/composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
- package/skills/web/composition-patterns/rules/architecture-compound-components.md +112 -0
- package/skills/web/composition-patterns/rules/patterns-children-over-render-props.md +87 -0
- package/skills/web/composition-patterns/rules/patterns-explicit-variants.md +100 -0
- package/skills/web/composition-patterns/rules/react19-no-forwardref.md +42 -0
- package/skills/web/composition-patterns/rules/state-context-interface.md +191 -0
- package/skills/web/composition-patterns/rules/state-decouple-implementation.md +113 -0
- package/skills/web/composition-patterns/rules/state-lift-state.md +125 -0
- package/skills/web/cost-aware-llm-pipeline/SKILL.md +183 -0
- package/skills/web/database-migrations/SKILL.md +429 -0
- package/skills/web/deployment-patterns/SKILL.md +427 -0
- package/skills/web/docker-patterns/SKILL.md +364 -0
- package/skills/web/e2e-testing/SKILL.md +326 -0
- package/skills/web/lighthouse-ci/SKILL.md +361 -0
- package/skills/web/mcp-server-patterns/SKILL.md +69 -0
- package/skills/web/next-best-practices/SKILL.md +153 -0
- package/skills/web/next-best-practices/async-patterns.md +87 -0
- package/skills/web/next-best-practices/bundling.md +180 -0
- package/skills/web/next-best-practices/data-patterns.md +297 -0
- package/skills/web/next-best-practices/debug-tricks.md +105 -0
- package/skills/web/next-best-practices/directives.md +73 -0
- package/skills/web/next-best-practices/error-handling.md +227 -0
- package/skills/web/next-best-practices/file-conventions.md +140 -0
- package/skills/web/next-best-practices/font.md +245 -0
- package/skills/web/next-best-practices/functions.md +108 -0
- package/skills/web/next-best-practices/hydration-error.md +91 -0
- package/skills/web/next-best-practices/image.md +173 -0
- package/skills/web/next-best-practices/metadata.md +301 -0
- package/skills/web/next-best-practices/parallel-routes.md +287 -0
- package/skills/web/next-best-practices/route-handlers.md +146 -0
- package/skills/web/next-best-practices/rsc-boundaries.md +159 -0
- package/skills/web/next-best-practices/runtime-selection.md +39 -0
- package/skills/web/next-best-practices/scripts.md +141 -0
- package/skills/web/next-best-practices/self-hosting.md +371 -0
- package/skills/web/next-best-practices/suspense-boundaries.md +67 -0
- package/skills/web/next-cache-components/SKILL.md +411 -0
- package/skills/web/postgres-best-practices/SKILL.md +14 -0
- package/skills/web/postgres-best-practices/references/schema-design.md +9 -0
- package/skills/web/react-best-practices/AGENTS.md +3810 -0
- package/skills/web/react-best-practices/README.md +123 -0
- package/skills/web/react-best-practices/SKILL.md +149 -0
- package/skills/web/react-best-practices/metadata.json +15 -0
- package/skills/web/react-best-practices/rules/_sections.md +46 -0
- package/skills/web/react-best-practices/rules/_template.md +28 -0
- package/skills/web/react-best-practices/rules/advanced-effect-event-deps.md +56 -0
- package/skills/web/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/skills/web/react-best-practices/rules/advanced-init-once.md +42 -0
- package/skills/web/react-best-practices/rules/advanced-use-latest.md +39 -0
- package/skills/web/react-best-practices/rules/async-api-routes.md +38 -0
- package/skills/web/react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
- package/skills/web/react-best-practices/rules/async-defer-await.md +82 -0
- package/skills/web/react-best-practices/rules/async-dependencies.md +51 -0
- package/skills/web/react-best-practices/rules/async-parallel.md +28 -0
- package/skills/web/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/skills/web/react-best-practices/rules/bundle-analyzable-paths.md +63 -0
- package/skills/web/react-best-practices/rules/bundle-barrel-imports.md +60 -0
- package/skills/web/react-best-practices/rules/bundle-conditional.md +31 -0
- package/skills/web/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/skills/web/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/skills/web/react-best-practices/rules/bundle-preload.md +50 -0
- package/skills/web/react-best-practices/rules/client-event-listeners.md +74 -0
- package/skills/web/react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/skills/web/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/skills/web/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/skills/web/react-best-practices/rules/js-batch-dom-css.md +107 -0
- package/skills/web/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/skills/web/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/skills/web/react-best-practices/rules/js-cache-storage.md +70 -0
- package/skills/web/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/skills/web/react-best-practices/rules/js-early-exit.md +50 -0
- package/skills/web/react-best-practices/rules/js-flatmap-filter.md +60 -0
- package/skills/web/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/skills/web/react-best-practices/rules/js-index-maps.md +37 -0
- package/skills/web/react-best-practices/rules/js-length-check-first.md +49 -0
- package/skills/web/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/skills/web/react-best-practices/rules/js-request-idle-callback.md +105 -0
- package/skills/web/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/skills/web/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/skills/web/react-best-practices/rules/rendering-activity.md +26 -0
- package/skills/web/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/skills/web/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/skills/web/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/skills/web/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/skills/web/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/skills/web/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
- package/skills/web/react-best-practices/rules/rendering-resource-hints.md +85 -0
- package/skills/web/react-best-practices/rules/rendering-script-defer-async.md +68 -0
- package/skills/web/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/skills/web/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/skills/web/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/skills/web/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/skills/web/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/skills/web/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/skills/web/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/skills/web/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/skills/web/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
- package/skills/web/react-best-practices/rules/rerender-memo.md +44 -0
- package/skills/web/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/skills/web/react-best-practices/rules/rerender-no-inline-components.md +82 -0
- package/skills/web/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/skills/web/react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
- package/skills/web/react-best-practices/rules/rerender-transitions.md +40 -0
- package/skills/web/react-best-practices/rules/rerender-use-deferred-value.md +59 -0
- package/skills/web/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/skills/web/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/skills/web/react-best-practices/rules/server-auth-actions.md +96 -0
- package/skills/web/react-best-practices/rules/server-cache-lru.md +41 -0
- package/skills/web/react-best-practices/rules/server-cache-react.md +76 -0
- package/skills/web/react-best-practices/rules/server-dedup-props.md +65 -0
- package/skills/web/react-best-practices/rules/server-hoist-static-io.md +149 -0
- package/skills/web/react-best-practices/rules/server-no-shared-module-state.md +50 -0
- package/skills/web/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/skills/web/react-best-practices/rules/server-parallel-nested-fetching.md +34 -0
- package/skills/web/react-best-practices/rules/server-serialization.md +38 -0
- package/skills/web/seo/SKILL.md +154 -0
- package/skills/web/web-design-guidelines/SKILL.md +39 -0
- package/skills/web/zap-scan-config/SKILL.md +444 -0
- package/skills/web/zap-scan-config/assets/.gitkeep +9 -0
- package/skills/web/zap-scan-config/assets/github_action.yml +207 -0
- package/skills/web/zap-scan-config/assets/gitlab_ci.yml +226 -0
- package/skills/web/zap-scan-config/assets/zap_automation.yaml +196 -0
- package/skills/web/zap-scan-config/assets/zap_context.xml +192 -0
- package/skills/web/zap-scan-config/references/EXAMPLE.md +40 -0
- package/skills/web/zap-scan-config/references/api_testing_guide.md +475 -0
- package/skills/web/zap-scan-config/references/authentication_guide.md +431 -0
- package/skills/web/zap-scan-config/references/false_positive_handling.md +427 -0
- package/skills/web/zap-scan-config/references/owasp_mapping.md +255 -0
- package/src/lrr/aggregator.ts +80 -0
- package/src/orchestrator/hooks/context-header.ts +95 -0
- package/src/orchestrator/hooks/token-accounting-emitter.ts +77 -0
- package/src/orchestrator/hooks/token-accounting.ts +101 -0
- package/src/orchestrator/mcp/cycle-counter.ts +129 -0
- package/src/orchestrator/mcp/scribe.ts +283 -0
- package/src/orchestrator/mcp/state-save.ts +149 -0
- package/src/orchestrator/mcp/write-lease.ts +167 -0
- package/src/orchestrator/phase4-shared-context.ts +41 -0
- package/src/orchestrator/schemas/backward-edge.ts +46 -0
- package/agents/agentic-identity-trust.md +0 -121
- package/agents/data-consolidation-agent.md +0 -39
- package/agents/design-image-prompt-engineer.md +0 -105
- package/agents/design-visual-storyteller.md +0 -147
- package/agents/design-whimsy-injector.md +0 -89
- package/agents/engineering-autonomous-optimization-architect.md +0 -105
- package/agents/market-intel.md +0 -35
- package/agents/marketing-instagram-curator.md +0 -111
- package/agents/marketing-reddit-community-builder.md +0 -121
- package/agents/marketing-social-media-strategist.md +0 -74
- package/agents/marketing-tiktok-strategist.md +0 -123
- package/agents/marketing-twitter-engager.md +0 -124
- package/agents/marketing-wechat-official-account.md +0 -143
- package/agents/marketing-xiaohongshu-specialist.md +0 -136
- package/agents/marketing-zhihu-strategist.md +0 -160
- package/agents/product-behavioral-nudge-engine.md +0 -78
- package/agents/project-management-experiment-tracker.md +0 -102
- package/agents/report-distribution-agent.md +0 -43
- package/agents/risk-analysis.md +0 -45
- package/agents/sales-data-extraction-agent.md +0 -46
- package/agents/specialized-cultural-intelligence-strategist.md +0 -65
- package/agents/specialized-developer-advocate.md +0 -146
- package/agents/support-analytics-reporter.md +0 -133
- package/agents/support-executive-summary-generator.md +0 -64
- package/agents/support-finance-tracker.md +0 -145
- package/agents/support-legal-compliance-checker.md +0 -129
- package/agents/support-support-responder.md +0 -91
- package/agents/testing-accessibility-auditor.md +0 -110
- package/agents/testing-test-results-analyzer.md +0 -97
- package/agents/testing-tool-evaluator.md +0 -76
- package/agents/testing-workflow-optimizer.md +0 -99
- package/agents/user-research.md +0 -40
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// AccessibilityAuditTests.swift
|
|
2
|
+
// Drop-in XCUITest file for automated accessibility auditing.
|
|
3
|
+
// Requires a platform that supports performAccessibilityAudit().
|
|
4
|
+
// The helper methods below skip gracefully on older deployment targets.
|
|
5
|
+
//
|
|
6
|
+
// Usage:
|
|
7
|
+
// 1. Add this file to your UI test target
|
|
8
|
+
// 2. Add navigation steps for each screen in your app
|
|
9
|
+
// 3. Run tests — failures indicate accessibility issues
|
|
10
|
+
//
|
|
11
|
+
// These tests use performAccessibilityAudit() to catch:
|
|
12
|
+
// - Missing accessibility labels
|
|
13
|
+
// - Low color contrast (WCAG thresholds)
|
|
14
|
+
// - Touch targets below 44x44pt
|
|
15
|
+
// - Text that doesn't scale with Dynamic Type
|
|
16
|
+
// - Clipped or truncated text
|
|
17
|
+
// - Incorrect accessibility traits
|
|
18
|
+
|
|
19
|
+
import XCTest
|
|
20
|
+
|
|
21
|
+
final class AccessibilityAuditTests: XCTestCase {
|
|
22
|
+
|
|
23
|
+
let app = XCUIApplication()
|
|
24
|
+
|
|
25
|
+
override func setUpWithError() throws {
|
|
26
|
+
continueAfterFailure = false
|
|
27
|
+
app.launch()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// MARK: - Full Audit (All Checks)
|
|
31
|
+
|
|
32
|
+
/// Audits the launch screen with all accessibility checks.
|
|
33
|
+
/// Add one test method per key screen in your app.
|
|
34
|
+
func testLaunchScreenAccessibility() throws {
|
|
35
|
+
try performAudit()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// MARK: - Per-Screen Audits
|
|
39
|
+
//
|
|
40
|
+
// Copy this pattern for each screen. Navigate to the screen,
|
|
41
|
+
// then run the audit.
|
|
42
|
+
//
|
|
43
|
+
// func testSettingsScreenAccessibility() throws {
|
|
44
|
+
// app.tabBars.buttons["Settings"].tap()
|
|
45
|
+
// try performAudit()
|
|
46
|
+
// }
|
|
47
|
+
//
|
|
48
|
+
// func testProfileScreenAccessibility() throws {
|
|
49
|
+
// app.tabBars.buttons["Profile"].tap()
|
|
50
|
+
// try performAudit()
|
|
51
|
+
// }
|
|
52
|
+
|
|
53
|
+
// MARK: - Filtered Audits
|
|
54
|
+
|
|
55
|
+
/// Contrast and labels only — the two most common failures.
|
|
56
|
+
func testContrastAndLabels() throws {
|
|
57
|
+
try performAudit([.contrast, .sufficientElementDescription])
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/// Touch targets and element detection.
|
|
61
|
+
func testHitRegionsAndDetection() throws {
|
|
62
|
+
try performAudit([.hitRegion, .elementDetection])
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/// Dynamic Type scaling and text clipping.
|
|
66
|
+
func testDynamicTypeSupport() throws {
|
|
67
|
+
try performAudit([.dynamicType, .textClipped])
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// MARK: - Audit with Known Issue Exclusions
|
|
71
|
+
|
|
72
|
+
/// Full audit that ignores specific known issues.
|
|
73
|
+
/// Replace the example exclusion with your own.
|
|
74
|
+
func testAuditWithExclusions() throws {
|
|
75
|
+
try performAudit(.all) { issue in
|
|
76
|
+
// Example: ignore contrast issues on branded splash logo
|
|
77
|
+
// if issue.auditType == .contrast,
|
|
78
|
+
// issue.element?.identifier == "splashLogo" {
|
|
79
|
+
// return true // true = ignore this issue
|
|
80
|
+
// }
|
|
81
|
+
return false // false = fail on this issue
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// MARK: - Multi-Screen Regression Test
|
|
86
|
+
|
|
87
|
+
/// Navigates through key screens and audits each one.
|
|
88
|
+
/// Customize the navigation steps for your app's tab bar or flow.
|
|
89
|
+
func testFullAppAccessibilityRegression() throws {
|
|
90
|
+
// Screen 1: Launch / Home
|
|
91
|
+
try performAudit()
|
|
92
|
+
|
|
93
|
+
// Screen 2: Navigate to second tab (customize for your app)
|
|
94
|
+
// app.tabBars.buttons["Search"].tap()
|
|
95
|
+
// try performAudit()
|
|
96
|
+
|
|
97
|
+
// Screen 3: Navigate to third tab
|
|
98
|
+
// app.tabBars.buttons["Settings"].tap()
|
|
99
|
+
// try performAudit()
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private func performAudit(
|
|
103
|
+
_ auditTypes: XCUIAccessibilityAuditType = .all
|
|
104
|
+
) throws {
|
|
105
|
+
try requireAccessibilityAuditSupport()
|
|
106
|
+
if #available(iOS 17, macOS 14, tvOS 17, watchOS 10, visionOS 1, *) {
|
|
107
|
+
try app.performAccessibilityAudit(for: auditTypes)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private func performAudit(
|
|
112
|
+
_ auditTypes: XCUIAccessibilityAuditType = .all,
|
|
113
|
+
issueHandler: @escaping (XCUIAccessibilityAuditIssue) throws -> Bool
|
|
114
|
+
) throws {
|
|
115
|
+
try requireAccessibilityAuditSupport()
|
|
116
|
+
if #available(iOS 17, macOS 14, tvOS 17, watchOS 10, visionOS 1, *) {
|
|
117
|
+
try app.performAccessibilityAudit(for: auditTypes, issueHandler)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private func requireAccessibilityAuditSupport() throws {
|
|
122
|
+
guard #available(iOS 17, macOS 14, tvOS 17, watchOS 10, visionOS 1, *) else {
|
|
123
|
+
throw XCTSkip(
|
|
124
|
+
"performAccessibilityAudit() requires iOS 17+, macOS 14+, tvOS 17+, watchOS 10+, or visionOS 1+."
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
# Accessibility QA Checklist
|
|
2
|
+
|
|
3
|
+
Standalone checklist for manual accessibility testing. Hand this to QA testers — no skill or Claude knowledge required.
|
|
4
|
+
|
|
5
|
+
Aligned with Apple's 9 App Store Accessibility Nutrition Labels and WCAG 2.2 Level AA.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## How to Use This Checklist
|
|
10
|
+
|
|
11
|
+
1. Test on a **real device** — Simulator doesn't fully support VoiceOver, Voice Control, or Switch Control
|
|
12
|
+
2. Test **every key user flow**: launch, onboarding, login, main feature, settings, purchase (if applicable)
|
|
13
|
+
3. Mark each item: Pass / Fail / N/A
|
|
14
|
+
4. A single Fail in a Nutrition Label category means that label **cannot be claimed** on the App Store
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Before You Start: Xcode Tools
|
|
19
|
+
|
|
20
|
+
### Xcode Canvas Variants (during development)
|
|
21
|
+
In the preview canvas, click the **Variants** button (grid icon) at the bottom:
|
|
22
|
+
- **Dynamic Type Variants** — renders the view at all 12 text sizes
|
|
23
|
+
- **Color Scheme Variants** — shows light and dark mode side by side
|
|
24
|
+
- **Orientation Variants** — portrait and landscape
|
|
25
|
+
|
|
26
|
+
### Xcode Canvas Device Settings (during development)
|
|
27
|
+
Click the **Device Settings** button (slider icon) at the bottom of the canvas:
|
|
28
|
+
- Set color scheme, Dynamic Type size, and orientation for a single preview
|
|
29
|
+
- Combine settings to test specific scenarios (e.g., dark mode + large text)
|
|
30
|
+
|
|
31
|
+
### Accessibility Inspector (Simulator or device)
|
|
32
|
+
Xcode menu → Open Developer Tool → Accessibility Inspector
|
|
33
|
+
- **Inspection tab** — point at any element to see its label, traits, value, and frame size
|
|
34
|
+
- **Audit tab** — run automated checks on the current screen (missing labels, low contrast, small targets)
|
|
35
|
+
- **Settings tab** — toggle Increase Contrast, Reduce Motion, Bold Text, Reduce Transparency on the Simulator without changing device settings
|
|
36
|
+
|
|
37
|
+
### performAccessibilityAudit() (automated tests)
|
|
38
|
+
Add to XCUITest target (iOS 17+). Catches missing labels, low contrast, small hit regions, clipped text, and Dynamic Type failures in CI. See `resources/audit-template.swift` for a drop-in template.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 1. VoiceOver
|
|
43
|
+
|
|
44
|
+
**Enable:** Settings → Accessibility → VoiceOver (or triple-click Side button if configured)
|
|
45
|
+
|
|
46
|
+
| # | Test | How to verify | Pass criteria |
|
|
47
|
+
|---|---|---|---|
|
|
48
|
+
| 1.1 | Navigate all elements | Swipe right repeatedly through entire screen | Every interactive element is reachable |
|
|
49
|
+
| 1.2 | Labels are meaningful | Tap each element, listen to announcement | Label describes the element concisely, not "button" or "image" |
|
|
50
|
+
| 1.3 | No redundant type in label | Listen for "button button" or "image image" | VoiceOver adds type automatically — label should not include it |
|
|
51
|
+
| 1.4 | State as traits | Toggle a switch, select a tab | VoiceOver says "selected" / "on" / "off" — not embedded in the label text |
|
|
52
|
+
| 1.5 | Decorative images hidden | Swipe through screen | Decorative images are skipped |
|
|
53
|
+
| 1.6 | Reading order is logical | Use "Read All" (two-finger swipe up) | Content reads in visual order, top-to-bottom, left-to-right |
|
|
54
|
+
| 1.7 | Focus after navigation | Push a new screen | Focus moves to first element of new screen (usually title or back button) |
|
|
55
|
+
| 1.8 | Focus after modal dismiss | Dismiss a sheet/alert | Focus returns to the element that triggered it |
|
|
56
|
+
| 1.9 | Adjustable controls work | Swipe up/down on slider or stepper | Value changes and is announced |
|
|
57
|
+
| 1.10 | Dynamic changes announced | Trigger a loading state or error | VoiceOver announces the change ("Loading complete", "Error: …") |
|
|
58
|
+
| 1.11 | Complete a key flow | Do the main task start-to-finish with VoiceOver | Task completes without sighted assistance |
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 2. Voice Control
|
|
63
|
+
|
|
64
|
+
**Enable:** Settings → Accessibility → Voice Control
|
|
65
|
+
|
|
66
|
+
| # | Test | How to verify | Pass criteria |
|
|
67
|
+
|---|---|---|---|
|
|
68
|
+
| 2.1 | Show numbers | Say "Show numbers" | Every interactive element has a number overlay |
|
|
69
|
+
| 2.2 | Tap by number | Say "Tap [number]" | Correct element activates |
|
|
70
|
+
| 2.3 | Show names | Say "Show names" | Every element shows its visible text label |
|
|
71
|
+
| 2.4 | Tap by name | Say "Tap [label]" | Element activates — label must match visible text exactly |
|
|
72
|
+
| 2.5 | Text input | Say "Type [text]" in a text field | Text is entered correctly |
|
|
73
|
+
| 2.6 | Scrolling | Say "Scroll down" / "Scroll up" | Content scrolls |
|
|
74
|
+
| 2.7 | Icon-only elements | Say "Tap Share" (or the label) for icon-only buttons | Button activates — requires `.accessibilityInputLabels` |
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 3. Larger Text (Dynamic Type)
|
|
79
|
+
|
|
80
|
+
**Enable:** Settings → Accessibility → Display & Text Size → Larger Text → drag slider to max
|
|
81
|
+
|
|
82
|
+
| # | Test | How to verify | Pass criteria |
|
|
83
|
+
|---|---|---|---|
|
|
84
|
+
| 3.1 | Text scales | Set to Accessibility 5 (max) | All text is larger |
|
|
85
|
+
| 3.2 | No clipping | Navigate all screens at max size | No text cut off without "..." affordance |
|
|
86
|
+
| 3.3 | No overlapping | Check all screens at max size | No elements overlap |
|
|
87
|
+
| 3.4 | Layout adapts | Check horizontal layouts | Rows/columns reflow to vertical when needed |
|
|
88
|
+
| 3.5 | Fixed UI chrome | Long-press on tab bar icons or toolbar items | Large Content Viewer shows enlarged version |
|
|
89
|
+
| 3.6 | Small text readable | Set to smallest size | Text is still readable |
|
|
90
|
+
|
|
91
|
+
**Quick check with Xcode:** Use Canvas Dynamic Type Variants to see all 12 sizes at once.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 4. Sufficient Contrast
|
|
96
|
+
|
|
97
|
+
**Tool:** Accessibility Inspector → Inspection tab → Color contrast
|
|
98
|
+
|
|
99
|
+
| # | Test | How to verify | Pass criteria |
|
|
100
|
+
|---|---|---|---|
|
|
101
|
+
| 4.1 | Normal text | Check body text against background | ≥ 4.5:1 contrast ratio |
|
|
102
|
+
| 4.2 | Large text | Check headings (≥ 18pt or 14pt bold) | ≥ 3:1 contrast ratio |
|
|
103
|
+
| 4.3 | Non-text elements | Check icons, borders, focus rings | ≥ 3:1 contrast ratio |
|
|
104
|
+
| 4.4 | Both modes | Repeat all checks in Dark Mode | Passes in both light and dark |
|
|
105
|
+
| 4.5 | Increased Contrast | Enable Increase Contrast in Accessibility Inspector Settings | Borders and separators become more visible |
|
|
106
|
+
| 4.6 | Placeholder text | Check text field placeholders | ≥ 4.5:1 against background |
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 5. Dark Interface
|
|
111
|
+
|
|
112
|
+
**Enable:** Settings → Display & Brightness → Dark
|
|
113
|
+
|
|
114
|
+
| # | Test | How to verify | Pass criteria |
|
|
115
|
+
|---|---|---|---|
|
|
116
|
+
| 5.1 | All text readable | Navigate all screens | No white-on-white or invisible text |
|
|
117
|
+
| 5.2 | Borders visible | Check cards, sections, separators | Borders and dividers are visible |
|
|
118
|
+
| 5.3 | Images correct | Check photos, icons | No white halo; images aren't inverted incorrectly |
|
|
119
|
+
| 5.4 | Status indicators | Check colored status elements | Still distinguishable in dark mode |
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 6. Differentiate Without Color
|
|
124
|
+
|
|
125
|
+
**Enable:** Settings → Accessibility → Display & Text Size → Color Filters → Grayscale
|
|
126
|
+
|
|
127
|
+
| # | Test | How to verify | Pass criteria |
|
|
128
|
+
|---|---|---|---|
|
|
129
|
+
| 6.1 | Status indicators | Check error/success/warning states | Distinguishable by shape, icon, or text — not color alone |
|
|
130
|
+
| 6.2 | Charts and graphs | Check data visualizations | Data series distinguishable by pattern, shape, or label |
|
|
131
|
+
| 6.3 | Links | Check link text | Underlined or otherwise distinguishable from body text |
|
|
132
|
+
| 6.4 | Form validation | Trigger an error state | Error is indicated by icon or text, not just red color |
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 7. Reduced Motion
|
|
137
|
+
|
|
138
|
+
**Enable:** Settings → Accessibility → Motion → Reduce Motion
|
|
139
|
+
|
|
140
|
+
| # | Test | How to verify | Pass criteria |
|
|
141
|
+
|---|---|---|---|
|
|
142
|
+
| 7.1 | Navigation transitions | Push/pop screens | No sliding animation — dissolve or instant |
|
|
143
|
+
| 7.2 | UI animations | Trigger state changes, loading | Animations removed or replaced with fade/opacity |
|
|
144
|
+
| 7.3 | Auto-playing content | Check for auto-playing animations/video | Stopped or has manual play control |
|
|
145
|
+
| 7.4 | Parallax effects | Scroll content | No parallax or motion effects |
|
|
146
|
+
|
|
147
|
+
**Quick check:** Toggle Reduce Motion in Accessibility Inspector Settings tab while running in Simulator.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 8. Captions
|
|
152
|
+
|
|
153
|
+
**Applies to:** Apps with video or audio content
|
|
154
|
+
|
|
155
|
+
| # | Test | How to verify | Pass criteria |
|
|
156
|
+
|---|---|---|---|
|
|
157
|
+
| 8.1 | Captions available | Play a video with dialogue | Captions can be enabled via player controls |
|
|
158
|
+
| 8.2 | Auto-enable | Enable Closed Captions in Settings → Accessibility → Subtitles & Captioning | Captions appear automatically |
|
|
159
|
+
| 8.3 | Captions accurate | Read captions while watching | Captions match spoken content |
|
|
160
|
+
| 8.4 | Timing correct | Watch captions during video | Captions sync with audio |
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## 9. Audio Descriptions
|
|
165
|
+
|
|
166
|
+
**Applies to:** Apps with video content where visual information is important
|
|
167
|
+
|
|
168
|
+
| # | Test | How to verify | Pass criteria |
|
|
169
|
+
|---|---|---|---|
|
|
170
|
+
| 9.1 | Audio Descriptions available | Play a video | Audio Description track can be selected |
|
|
171
|
+
| 9.2 | Auto-enable | Enable Audio Descriptions in Settings → Accessibility → Audio Descriptions | Audio Descriptions play automatically |
|
|
172
|
+
| 9.3 | Content described | Listen to Audio Descriptions | Important visual information is narrated |
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## 10. Additional Checks
|
|
177
|
+
|
|
178
|
+
### Switch Control
|
|
179
|
+
|
|
180
|
+
**Enable:** Settings → Accessibility → Switch Control
|
|
181
|
+
|
|
182
|
+
| # | Test | How to verify | Pass criteria |
|
|
183
|
+
|---|---|---|---|
|
|
184
|
+
| 10.1 | Scanning | Enable auto-scan | Every element is highlighted in sequence |
|
|
185
|
+
| 10.2 | Activation | Select a highlighted element | Correct action triggers |
|
|
186
|
+
| 10.3 | Custom actions | Navigate to elements with swipe actions | Actions appear in scanning menu |
|
|
187
|
+
| 10.4 | No timeouts | Use the app slowly | Nothing times out or auto-advances |
|
|
188
|
+
|
|
189
|
+
### Full Keyboard Access (iPad / Mac)
|
|
190
|
+
|
|
191
|
+
**Enable:** Settings → Accessibility → Keyboards → Full Keyboard Access
|
|
192
|
+
|
|
193
|
+
| # | Test | How to verify | Pass criteria |
|
|
194
|
+
|---|---|---|---|
|
|
195
|
+
| 10.5 | Tab navigation | Press Tab repeatedly | Focus moves through all interactive elements |
|
|
196
|
+
| 10.6 | Reverse Tab | Press Shift+Tab | Focus moves backward |
|
|
197
|
+
| 10.7 | Activation | Press Space or Return on focused element | Element activates |
|
|
198
|
+
| 10.8 | Escape dismissal | Press Escape on modal | Modal dismisses |
|
|
199
|
+
| 10.9 | No focus traps | Tab through entire app | Focus never gets stuck |
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Summary Template
|
|
204
|
+
|
|
205
|
+
After testing, fill in:
|
|
206
|
+
|
|
207
|
+
| Nutrition Label | Status | Blocking Issues |
|
|
208
|
+
|---|---|---|
|
|
209
|
+
| VoiceOver | Pass / Fail | |
|
|
210
|
+
| Voice Control | Pass / Fail | |
|
|
211
|
+
| Larger Text | Pass / Fail | |
|
|
212
|
+
| Sufficient Contrast | Pass / Fail | |
|
|
213
|
+
| Dark Interface | Pass / Fail | |
|
|
214
|
+
| Differentiate Without Color | Pass / Fail | |
|
|
215
|
+
| Reduced Motion | Pass / Fail | |
|
|
216
|
+
| Captions | Pass / Fail / N/A | |
|
|
217
|
+
| Audio Descriptions | Pass / Fail / N/A | |
|
|
218
|
+
|
|
219
|
+
### App Store recommendation draft
|
|
220
|
+
|
|
221
|
+
Use the completed summary above to prepare an App Store Accessibility Nutrition Label recommendation:
|
|
222
|
+
|
|
223
|
+
- You could claim: every label marked Pass
|
|
224
|
+
- You should not claim: every label marked Fail
|
|
225
|
+
- Not applicable: every label marked N/A
|
|
226
|
+
- Add short reasons for both supported and unsupported labels
|
|
227
|
+
|
|
228
|
+
Example handoff:
|
|
229
|
+
|
|
230
|
+
```md
|
|
231
|
+
Accessibility Nutrition Label recommendation
|
|
232
|
+
|
|
233
|
+
You could claim:
|
|
234
|
+
- VoiceOver
|
|
235
|
+
- Voice Control
|
|
236
|
+
- Larger Text
|
|
237
|
+
- Sufficient Contrast
|
|
238
|
+
- Dark Interface
|
|
239
|
+
- Differentiate Without Color
|
|
240
|
+
- Reduced Motion
|
|
241
|
+
|
|
242
|
+
Why you could claim them:
|
|
243
|
+
- VoiceOver: all reviewed common tasks are reachable, labeled, and operable with VoiceOver
|
|
244
|
+
- Voice Control: all reviewed interactive elements can be activated by visible name or input label
|
|
245
|
+
- Larger Text: reviewed screens reflow correctly and remain readable at the largest supported sizes
|
|
246
|
+
- Sufficient Contrast: reviewed text and interactive elements meet contrast requirements in light and dark mode
|
|
247
|
+
- Dark Interface: reviewed screens support dark appearance without unreadable content or broken chrome
|
|
248
|
+
- Differentiate Without Color: reviewed states and status indicators remain understandable without color alone
|
|
249
|
+
- Reduced Motion: reviewed transitions and state changes respect Reduce Motion
|
|
250
|
+
|
|
251
|
+
You should not claim:
|
|
252
|
+
- Captions
|
|
253
|
+
- Audio Descriptions
|
|
254
|
+
|
|
255
|
+
Why you should not claim them:
|
|
256
|
+
- Captions: the app has no primary video or long-form media experience in the reviewed scope
|
|
257
|
+
- Audio Descriptions: the app has no video content that would justify this label in the reviewed scope
|
|
258
|
+
```
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: swift-actor-persistence
|
|
3
|
+
description: Thread-safe data persistence in Swift using actors — in-memory cache with file-backed storage, eliminating data races by design.
|
|
4
|
+
origin: ECC
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Swift Actors for Thread-Safe Persistence
|
|
8
|
+
|
|
9
|
+
Patterns for building thread-safe data persistence layers using Swift actors. Combines in-memory caching with file-backed storage, leveraging the actor model to eliminate data races at compile time.
|
|
10
|
+
|
|
11
|
+
## When to Activate
|
|
12
|
+
|
|
13
|
+
- Building a data persistence layer in Swift 5.5+
|
|
14
|
+
- Need thread-safe access to shared mutable state
|
|
15
|
+
- Want to eliminate manual synchronization (locks, DispatchQueues)
|
|
16
|
+
- Building offline-first apps with local storage
|
|
17
|
+
|
|
18
|
+
## Core Pattern
|
|
19
|
+
|
|
20
|
+
### Actor-Based Repository
|
|
21
|
+
|
|
22
|
+
The actor model guarantees serialized access — no data races, enforced by the compiler.
|
|
23
|
+
|
|
24
|
+
```swift
|
|
25
|
+
public actor LocalRepository<T: Codable & Identifiable> where T.ID == String {
|
|
26
|
+
private var cache: [String: T] = [:]
|
|
27
|
+
private let fileURL: URL
|
|
28
|
+
|
|
29
|
+
public init(directory: URL = .documentsDirectory, filename: String = "data.json") {
|
|
30
|
+
self.fileURL = directory.appendingPathComponent(filename)
|
|
31
|
+
// Synchronous load during init (actor isolation not yet active)
|
|
32
|
+
self.cache = Self.loadSynchronously(from: fileURL)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// MARK: - Public API
|
|
36
|
+
|
|
37
|
+
public func save(_ item: T) throws {
|
|
38
|
+
cache[item.id] = item
|
|
39
|
+
try persistToFile()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public func delete(_ id: String) throws {
|
|
43
|
+
cache[id] = nil
|
|
44
|
+
try persistToFile()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public func find(by id: String) -> T? {
|
|
48
|
+
cache[id]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public func loadAll() -> [T] {
|
|
52
|
+
Array(cache.values)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// MARK: - Private
|
|
56
|
+
|
|
57
|
+
private func persistToFile() throws {
|
|
58
|
+
let data = try JSONEncoder().encode(Array(cache.values))
|
|
59
|
+
try data.write(to: fileURL, options: .atomic)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private static func loadSynchronously(from url: URL) -> [String: T] {
|
|
63
|
+
guard let data = try? Data(contentsOf: url),
|
|
64
|
+
let items = try? JSONDecoder().decode([T].self, from: data) else {
|
|
65
|
+
return [:]
|
|
66
|
+
}
|
|
67
|
+
return Dictionary(uniqueKeysWithValues: items.map { ($0.id, $0) })
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Usage
|
|
73
|
+
|
|
74
|
+
All calls are automatically async due to actor isolation:
|
|
75
|
+
|
|
76
|
+
```swift
|
|
77
|
+
let repository = LocalRepository<Question>()
|
|
78
|
+
|
|
79
|
+
// Read — fast O(1) lookup from in-memory cache
|
|
80
|
+
let question = await repository.find(by: "q-001")
|
|
81
|
+
let allQuestions = await repository.loadAll()
|
|
82
|
+
|
|
83
|
+
// Write — updates cache and persists to file atomically
|
|
84
|
+
try await repository.save(newQuestion)
|
|
85
|
+
try await repository.delete("q-001")
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Combining with @Observable ViewModel
|
|
89
|
+
|
|
90
|
+
```swift
|
|
91
|
+
@Observable
|
|
92
|
+
final class QuestionListViewModel {
|
|
93
|
+
private(set) var questions: [Question] = []
|
|
94
|
+
private let repository: LocalRepository<Question>
|
|
95
|
+
|
|
96
|
+
init(repository: LocalRepository<Question> = LocalRepository()) {
|
|
97
|
+
self.repository = repository
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
func load() async {
|
|
101
|
+
questions = await repository.loadAll()
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
func add(_ question: Question) async throws {
|
|
105
|
+
try await repository.save(question)
|
|
106
|
+
questions = await repository.loadAll()
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Key Design Decisions
|
|
112
|
+
|
|
113
|
+
| Decision | Rationale |
|
|
114
|
+
|----------|-----------|
|
|
115
|
+
| Actor (not class + lock) | Compiler-enforced thread safety, no manual synchronization |
|
|
116
|
+
| In-memory cache + file persistence | Fast reads from cache, durable writes to disk |
|
|
117
|
+
| Synchronous init loading | Avoids async initialization complexity |
|
|
118
|
+
| Dictionary keyed by ID | O(1) lookups by identifier |
|
|
119
|
+
| Generic over `Codable & Identifiable` | Reusable across any model type |
|
|
120
|
+
| Atomic file writes (`.atomic`) | Prevents partial writes on crash |
|
|
121
|
+
|
|
122
|
+
## Best Practices
|
|
123
|
+
|
|
124
|
+
- **Use `Sendable` types** for all data crossing actor boundaries
|
|
125
|
+
- **Keep the actor's public API minimal** — only expose domain operations, not persistence details
|
|
126
|
+
- **Use `.atomic` writes** to prevent data corruption if the app crashes mid-write
|
|
127
|
+
- **Load synchronously in `init`** — async initializers add complexity with minimal benefit for local files
|
|
128
|
+
- **Combine with `@Observable`** ViewModels for reactive UI updates
|
|
129
|
+
|
|
130
|
+
## Anti-Patterns to Avoid
|
|
131
|
+
|
|
132
|
+
- Using `DispatchQueue` or `NSLock` instead of actors for new Swift concurrency code
|
|
133
|
+
- Exposing the internal cache dictionary to external callers
|
|
134
|
+
- Making the file URL configurable without validation
|
|
135
|
+
- Forgetting that all actor method calls are `await` — callers must handle async context
|
|
136
|
+
- Using `nonisolated` to bypass actor isolation (defeats the purpose)
|
|
137
|
+
|
|
138
|
+
## When to Use
|
|
139
|
+
|
|
140
|
+
- Local data storage in iOS/macOS apps (user data, settings, cached content)
|
|
141
|
+
- Offline-first architectures that sync to a server later
|
|
142
|
+
- Any shared mutable state that multiple parts of the app access concurrently
|
|
143
|
+
- Replacing legacy `DispatchQueue`-based thread safety with modern Swift concurrency
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Antoine van der Lee
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|