@mmerterden/multi-agent-pipeline 20.6.0 → 20.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/LICENSE +0 -10
- package/docs/facts.json +1 -1
- package/manifest.json +328 -329
- package/package.json +2 -2
- package/pipeline/multi-agent-refs/features/design-conformance.md +62 -64
- package/pipeline/scripts/_notices.mjs +12 -1
- package/pipeline/scripts/gen-skills-index.mjs +1 -1
- package/pipeline/skills/.skill-manifest.json +106 -106
- package/pipeline/skills/shared/README.md +71 -71
- package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +1 -0
- package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
- package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
- package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
- package/pipeline/skills/shared/external/android-architecture/SKILL.md +2 -0
- package/pipeline/skills/shared/external/android-performance/SKILL.md +2 -0
- package/pipeline/skills/shared/external/android-security/SKILL.md +2 -0
- package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
- package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
- package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
- package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
- package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
- package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
- package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
- package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
- package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
- package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
- package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
- package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
- package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
- package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
- package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
- package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
- package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
- package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
- package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
- package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
- package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
- package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
- package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
- package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
- package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
- package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
- package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
- package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
- package/pipeline/skills/shared/external/backlog/BACKLOG.md +1 -1
- package/pipeline/skills/shared/external/backlog/SKILL.md +56 -33
- package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
- package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
- package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +1 -0
- package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
- package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
- package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
- package/pipeline/skills/shared/external/compose-components/SKILL.md +2 -0
- package/pipeline/skills/shared/external/compose-navigation/SKILL.md +3 -2
- package/pipeline/skills/shared/external/compose-testing/SKILL.md +2 -0
- package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
- package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
- package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
- package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
- package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
- package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
- package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
- package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
- package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
- package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
- package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
- package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
- package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
- package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
- package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
- package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
- package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
- package/pipeline/skills/shared/external/council/SKILL.md +1 -0
- package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
- package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
- package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
- package/pipeline/skills/shared/external/css-modern/SKILL.md +1 -0
- package/pipeline/skills/shared/external/database-patterns/SKILL.md +1 -0
- package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
- package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
- package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
- package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
- package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
- package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
- package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
- package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
- package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
- package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
- package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
- package/pipeline/skills/shared/external/evidence-github/SKILL.md +2 -0
- package/pipeline/skills/shared/external/evidence-registry/SKILL.md +2 -0
- package/pipeline/skills/shared/external/gradle-kotlin-dsl/SKILL.md +2 -0
- package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
- package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
- package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
- package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
- package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
- package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
- package/pipeline/skills/shared/external/html-semantic/SKILL.md +1 -0
- package/pipeline/skills/shared/external/humanizer/SKILL.md +1 -0
- package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
- package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
- package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
- package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
- package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
- package/pipeline/skills/shared/external/ios-coding-standard/SKILL.md +1 -0
- package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
- package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
- package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
- package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
- package/pipeline/skills/shared/external/ios-module-structure/SKILL.md +1 -0
- package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
- package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
- package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
- package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
- package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
- package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
- package/pipeline/skills/shared/external/ios-security/SKILL.md +2 -0
- package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
- package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
- package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
- package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
- package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +91 -283
- package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +119 -151
- package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +60 -90
- package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +119 -156
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +726 -787
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +253 -288
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +243 -304
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +88 -104
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +181 -235
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-key-shots.py +198 -263
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +461 -466
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +145 -151
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +123 -141
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +146 -157
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/snapshot-resources.sh +22 -19
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +156 -140
- package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
- package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
- package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
- package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
- package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
- package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
- package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
- package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
- package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
- package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
- package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +1 -0
- package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
- package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
- package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
- package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
- package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
- package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
- package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
- package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
- package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
- package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
- package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
- package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
- package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
- package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
- package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
- package/pipeline/skills/shared/external/play-store-review/SKILL.md +2 -0
- package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
- package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
- package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
- package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
- package/pipeline/skills/shared/external/python-patterns/SKILL.md +1 -0
- package/pipeline/skills/shared/external/react-best-practices/SKILL.md +1 -0
- package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
- package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
- package/pipeline/skills/shared/external/rest-api-design/SKILL.md +1 -0
- package/pipeline/skills/shared/external/retrofit-networking/SKILL.md +2 -0
- package/pipeline/skills/shared/external/room-database/SKILL.md +2 -0
- package/pipeline/skills/shared/external/search-first/SKILL.md +1 -0
- package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
- package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
- package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
- package/pipeline/skills/shared/external/signal-community/SKILL.md +2 -0
- package/pipeline/skills/shared/external/skill-creator/SKILL.md +80 -41
- package/pipeline/skills/shared/external/skill-creator/audit.md +63 -59
- package/pipeline/skills/shared/external/skill-creator/checklist.md +28 -20
- package/pipeline/skills/shared/external/skill-creator/examples.md +40 -40
- package/pipeline/skills/shared/external/skill-creator/label-check.md +48 -36
- package/pipeline/skills/shared/external/skill-creator/scripts/audit-panel.js +91 -100
- package/pipeline/skills/shared/external/skill-creator/template.md +51 -39
- package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
- package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
- package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
- package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
- package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
- package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
- package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
- package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
- package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
- package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
- package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
- package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
- package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
- package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
- package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
- package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
- package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
- package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
- package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
- package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
- package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
- package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
- package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
- package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
- package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
- package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
- package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
- package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
- package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
- package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
- package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
- package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
- package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
- package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
- package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
- package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
- package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
- package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
- package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
- package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
- package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
- package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
- package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
- package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
- package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
- package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
- package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
- package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
- package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
- package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
- package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
- package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
- package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
- package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
- package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
- package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
- package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
- package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
- package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
- package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
- package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
- package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
- package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
- package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
- package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
- package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
- package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
- package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
- package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
- package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
- package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
- package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
- package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
- package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
- package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
- package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
- package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
- package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
- package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
- package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
- package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
- package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
- package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
- package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
- package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
- package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
- package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
- package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
- package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
- package/pipeline/skills/shared/external/tailwind-css/SKILL.md +1 -0
- package/pipeline/skills/shared/external/testing-backend/SKILL.md +1 -0
- package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
- package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
- package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +1 -0
- package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
- package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
- package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
- package/pipeline/skills/shared/external/vue-composition/SKILL.md +1 -0
- package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
- package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
- package/pipeline/skills/shared/external/web-accessibility/SKILL.md +1 -0
- package/pipeline/skills/shared/external/web-performance/SKILL.md +1 -0
- package/pipeline/skills/shared/external/web-testing/SKILL.md +1 -0
- package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
- package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
- package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
|
@@ -1,275 +1,213 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Matter commissioning and HomeKit UI recipes
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Extended material for the `homekit-matter` skill ([../SKILL.md](../SKILL.md)):
|
|
4
|
+
a SwiftUI store, accessory screens, complete delegate wiring, service and
|
|
5
|
+
characteristic tables, a fuller MatterSupport handler, and simulator testing.
|
|
5
6
|
|
|
6
7
|
## Contents
|
|
7
8
|
|
|
8
|
-
- [SwiftUI
|
|
9
|
-
- [
|
|
10
|
-
- [
|
|
11
|
-
- [
|
|
12
|
-
- [
|
|
9
|
+
- [SwiftUI integration](#swiftui-integration)
|
|
10
|
+
- [Delegate wiring](#delegate-wiring)
|
|
11
|
+
- [Finding services by type](#finding-services-by-type)
|
|
12
|
+
- [A fuller MatterSupport handler](#a-fuller-mattersupport-handler)
|
|
13
|
+
- [Simulated accessories for testing](#simulated-accessories-for-testing)
|
|
13
14
|
|
|
14
|
-
## SwiftUI
|
|
15
|
+
## SwiftUI integration
|
|
15
16
|
|
|
16
|
-
###
|
|
17
|
+
### An observable store
|
|
18
|
+
|
|
19
|
+
One store owns the single `HMHomeManager`. HomeKit calls its delegates off the
|
|
20
|
+
main actor, so the callbacks are `nonisolated` and hop back before touching
|
|
21
|
+
state.
|
|
17
22
|
|
|
18
23
|
```swift
|
|
19
24
|
import HomeKit
|
|
20
|
-
import
|
|
25
|
+
import Observation
|
|
21
26
|
|
|
22
27
|
@Observable
|
|
23
28
|
@MainActor
|
|
24
|
-
final class
|
|
25
|
-
static let shared =
|
|
29
|
+
final class HouseStore: NSObject {
|
|
30
|
+
static let shared = HouseStore()
|
|
26
31
|
|
|
27
|
-
let
|
|
32
|
+
@ObservationIgnored private let manager = HMHomeManager()
|
|
33
|
+
private(set) var houses: [HMHome] = []
|
|
34
|
+
private(set) var mainHouse: HMHome?
|
|
35
|
+
private(set) var hasAccess = false
|
|
28
36
|
|
|
29
|
-
var
|
|
30
|
-
var
|
|
31
|
-
var isAuthorized = false
|
|
37
|
+
var devices: [HMAccessory] { mainHouse?.accessories ?? [] }
|
|
38
|
+
var spaces: [HMRoom] { mainHouse?.rooms ?? [] }
|
|
32
39
|
|
|
33
|
-
override init() {
|
|
40
|
+
private override init() {
|
|
34
41
|
super.init()
|
|
35
|
-
|
|
42
|
+
manager.delegate = self
|
|
36
43
|
}
|
|
37
44
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
primaryHome?.rooms ?? []
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
func addHome(name: String) async throws {
|
|
47
|
-
try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
|
|
48
|
-
homeManager.addHome(withName: name) { home, error in
|
|
49
|
-
if let error {
|
|
50
|
-
continuation.resume(throwing: error)
|
|
45
|
+
func createHouse(named name: String) async throws -> HMHome {
|
|
46
|
+
try await withCheckedThrowingContinuation { continuation in
|
|
47
|
+
manager.addHome(withName: name) { created, failure in
|
|
48
|
+
if let created {
|
|
49
|
+
continuation.resume(returning: created)
|
|
51
50
|
} else {
|
|
52
|
-
continuation.resume()
|
|
51
|
+
continuation.resume(throwing: failure ?? HMError(.genericError))
|
|
53
52
|
}
|
|
54
53
|
}
|
|
55
54
|
}
|
|
56
55
|
}
|
|
56
|
+
|
|
57
|
+
private func reload() {
|
|
58
|
+
houses = manager.homes
|
|
59
|
+
// primaryHome is deprecated since iOS 16.1; keep the user's own choice.
|
|
60
|
+
mainHouse = houses.first { $0 == mainHouse } ?? houses.first
|
|
61
|
+
}
|
|
57
62
|
}
|
|
58
63
|
|
|
59
|
-
extension
|
|
60
|
-
nonisolated func homeManagerDidUpdateHomes(_
|
|
61
|
-
Task { @MainActor in
|
|
62
|
-
homes = manager.homes
|
|
63
|
-
primaryHome = manager.primaryHome
|
|
64
|
-
}
|
|
64
|
+
extension HouseStore: HMHomeManagerDelegate {
|
|
65
|
+
nonisolated func homeManagerDidUpdateHomes(_ source: HMHomeManager) {
|
|
66
|
+
Task { @MainActor in reload() }
|
|
65
67
|
}
|
|
66
68
|
|
|
67
|
-
nonisolated func homeManager(
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
Task { @MainActor in
|
|
72
|
-
isAuthorized = status.contains(.authorized)
|
|
73
|
-
}
|
|
69
|
+
nonisolated func homeManager(_ source: HMHomeManager,
|
|
70
|
+
didUpdate status: HMHomeManagerAuthorizationStatus) {
|
|
71
|
+
let granted = status.contains(.authorized)
|
|
72
|
+
Task { @MainActor in hasAccess = granted }
|
|
74
73
|
}
|
|
75
74
|
|
|
76
|
-
nonisolated func homeManager(
|
|
77
|
-
|
|
78
|
-
didAdd home: HMHome
|
|
79
|
-
) {
|
|
80
|
-
Task { @MainActor in
|
|
81
|
-
homes = manager.homes
|
|
82
|
-
}
|
|
75
|
+
nonisolated func homeManager(_ source: HMHomeManager, didAdd home: HMHome) {
|
|
76
|
+
Task { @MainActor in reload() }
|
|
83
77
|
}
|
|
84
78
|
|
|
85
|
-
nonisolated func homeManager(
|
|
86
|
-
|
|
87
|
-
didRemove home: HMHome
|
|
88
|
-
) {
|
|
89
|
-
Task { @MainActor in
|
|
90
|
-
homes = manager.homes
|
|
91
|
-
}
|
|
79
|
+
nonisolated func homeManager(_ source: HMHomeManager, didRemove home: HMHome) {
|
|
80
|
+
Task { @MainActor in reload() }
|
|
92
81
|
}
|
|
93
82
|
}
|
|
94
83
|
```
|
|
95
84
|
|
|
96
|
-
###
|
|
85
|
+
### Accessories grouped by room
|
|
97
86
|
|
|
98
87
|
```swift
|
|
99
|
-
|
|
100
|
-
|
|
88
|
+
import SwiftUI
|
|
89
|
+
import HomeKit
|
|
90
|
+
|
|
91
|
+
struct DeviceBrowser: View {
|
|
92
|
+
let store = HouseStore.shared
|
|
101
93
|
|
|
102
94
|
var body: some View {
|
|
103
95
|
NavigationStack {
|
|
104
96
|
Group {
|
|
105
|
-
if !
|
|
106
|
-
ContentUnavailableView(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
)
|
|
111
|
-
} else if homeStore.accessories.isEmpty {
|
|
112
|
-
ContentUnavailableView(
|
|
113
|
-
"No Accessories",
|
|
114
|
-
systemImage: "lightbulb",
|
|
115
|
-
description: Text("Add accessories using the Home app.")
|
|
116
|
-
)
|
|
97
|
+
if !store.hasAccess {
|
|
98
|
+
ContentUnavailableView("Home access is off",
|
|
99
|
+
systemImage: "house.slash",
|
|
100
|
+
description: Text("Allow access in Settings."))
|
|
101
|
+
} else if store.devices.isEmpty {
|
|
102
|
+
ContentUnavailableView("No devices yet", systemImage: "lightbulb.slash")
|
|
117
103
|
} else {
|
|
118
|
-
|
|
104
|
+
List(store.spaces, id: \.uniqueIdentifier) { space in
|
|
105
|
+
Section(space.name) {
|
|
106
|
+
ForEach(devices(in: space), id: \.uniqueIdentifier) { device in
|
|
107
|
+
DeviceRow(device: device)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
119
111
|
}
|
|
120
112
|
}
|
|
121
|
-
.navigationTitle(
|
|
113
|
+
.navigationTitle("Devices")
|
|
122
114
|
}
|
|
123
115
|
}
|
|
124
116
|
|
|
125
|
-
private
|
|
126
|
-
|
|
127
|
-
ForEach(homeStore.rooms, id: \.uniqueIdentifier) { room in
|
|
128
|
-
Section(room.name) {
|
|
129
|
-
let roomAccessories = homeStore.accessories.filter {
|
|
130
|
-
$0.room?.uniqueIdentifier == room.uniqueIdentifier
|
|
131
|
-
}
|
|
132
|
-
ForEach(roomAccessories, id: \.uniqueIdentifier) { accessory in
|
|
133
|
-
AccessoryRow(accessory: accessory)
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
117
|
+
private func devices(in space: HMRoom) -> [HMAccessory] {
|
|
118
|
+
store.devices.filter { $0.room?.uniqueIdentifier == space.uniqueIdentifier }
|
|
138
119
|
}
|
|
139
120
|
}
|
|
140
121
|
|
|
141
|
-
struct
|
|
142
|
-
let
|
|
122
|
+
struct DeviceRow: View {
|
|
123
|
+
let device: HMAccessory
|
|
143
124
|
|
|
144
125
|
var body: some View {
|
|
145
|
-
|
|
146
|
-
Image(systemName: iconName)
|
|
126
|
+
Label {
|
|
147
127
|
VStack(alignment: .leading) {
|
|
148
|
-
Text(
|
|
149
|
-
|
|
150
|
-
Text(accessory.isReachable ? "Reachable" : "Not Reachable")
|
|
128
|
+
Text(device.name)
|
|
129
|
+
Text(device.isReachable ? "Online" : "Offline")
|
|
151
130
|
.font(.caption)
|
|
152
|
-
.foregroundStyle(
|
|
131
|
+
.foregroundStyle(.secondary)
|
|
153
132
|
}
|
|
133
|
+
} icon: {
|
|
134
|
+
Image(systemName: glyph)
|
|
154
135
|
}
|
|
155
136
|
}
|
|
156
137
|
|
|
157
|
-
private var
|
|
158
|
-
switch
|
|
159
|
-
case HMAccessoryCategoryTypeLightbulb:
|
|
160
|
-
case HMAccessoryCategoryTypeThermostat:
|
|
161
|
-
case
|
|
162
|
-
case HMAccessoryCategoryTypeSwitch:
|
|
163
|
-
default:
|
|
138
|
+
private var glyph: String {
|
|
139
|
+
switch device.category.categoryType {
|
|
140
|
+
case HMAccessoryCategoryTypeLightbulb: "lightbulb"
|
|
141
|
+
case HMAccessoryCategoryTypeThermostat: "thermometer"
|
|
142
|
+
case HMAccessoryCategoryTypeDoorLock: "lock"
|
|
143
|
+
case HMAccessoryCategoryTypeSwitch: "switch.2"
|
|
144
|
+
default: "questionmark.square"
|
|
164
145
|
}
|
|
165
146
|
}
|
|
166
147
|
}
|
|
167
148
|
```
|
|
168
149
|
|
|
169
|
-
###
|
|
150
|
+
### A lamp control screen
|
|
170
151
|
|
|
171
152
|
```swift
|
|
172
|
-
struct
|
|
173
|
-
let
|
|
153
|
+
struct LampPanel: View {
|
|
154
|
+
let lamp: HMAccessory
|
|
155
|
+
@State private var isLit = false
|
|
156
|
+
@State private var level = 50.0
|
|
174
157
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
private var lightbulbService: HMService? {
|
|
179
|
-
accessory.services.first {
|
|
180
|
-
$0.serviceType == HMServiceTypeLightbulb
|
|
181
|
-
}
|
|
158
|
+
private var bulb: HMService? {
|
|
159
|
+
lamp.services.first { $0.serviceType == HMServiceTypeLightbulb }
|
|
182
160
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
lightbulbService?.characteristics.first {
|
|
186
|
-
$0.characteristicType == HMCharacteristicTypePowerState
|
|
187
|
-
}
|
|
161
|
+
private var power: HMCharacteristic? {
|
|
162
|
+
bulb?.characteristics.first { $0.characteristicType == HMCharacteristicTypePowerState }
|
|
188
163
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
lightbulbService?.characteristics.first {
|
|
192
|
-
$0.characteristicType == HMCharacteristicTypeBrightness
|
|
193
|
-
}
|
|
164
|
+
private var dimmer: HMCharacteristic? {
|
|
165
|
+
bulb?.characteristics.first { $0.characteristicType == HMCharacteristicTypeBrightness }
|
|
194
166
|
}
|
|
195
167
|
|
|
196
168
|
var body: some View {
|
|
197
|
-
|
|
198
|
-
Toggle("
|
|
199
|
-
.onChange(of:
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
if isOn {
|
|
204
|
-
Slider(value: $brightness, in: 0...100, step: 1)
|
|
205
|
-
.onChange(of: brightness) { _, newValue in
|
|
206
|
-
brightnessCharacteristic?.writeValue(
|
|
207
|
-
Int(newValue)
|
|
208
|
-
) { _ in }
|
|
209
|
-
}
|
|
210
|
-
Text("Brightness: \(Int(brightness))%")
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
.padding()
|
|
214
|
-
.task { await readCurrentState() }
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
private func readCurrentState() async {
|
|
218
|
-
powerCharacteristic?.readValue { _ in
|
|
219
|
-
if let value = powerCharacteristic?.value as? Bool {
|
|
220
|
-
isOn = value
|
|
221
|
-
}
|
|
169
|
+
Form {
|
|
170
|
+
Toggle("Lit", isOn: $isLit)
|
|
171
|
+
.onChange(of: isLit) { _, lit in power?.writeValue(lit) { _ in } }
|
|
172
|
+
Slider(value: $level, in: 0...100, step: 1)
|
|
173
|
+
.onChange(of: level) { _, value in dimmer?.writeValue(Int(value)) { _ in } }
|
|
222
174
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
175
|
+
.task {
|
|
176
|
+
try? await power?.readValue()
|
|
177
|
+
try? await dimmer?.readValue()
|
|
178
|
+
isLit = power?.value as? Bool ?? false
|
|
179
|
+
level = Double(dimmer?.value as? Int ?? 0)
|
|
227
180
|
}
|
|
228
181
|
}
|
|
229
182
|
}
|
|
230
183
|
```
|
|
231
184
|
|
|
232
|
-
##
|
|
185
|
+
## Delegate wiring
|
|
233
186
|
|
|
234
187
|
### HMHomeDelegate
|
|
235
188
|
|
|
189
|
+
Set the accessory's delegate as soon as it appears so value pushes are not
|
|
190
|
+
lost.
|
|
191
|
+
|
|
236
192
|
```swift
|
|
237
|
-
extension
|
|
238
|
-
nonisolated func home(
|
|
239
|
-
_ home: HMHome,
|
|
240
|
-
didAdd accessory: HMAccessory
|
|
241
|
-
) {
|
|
242
|
-
accessory.delegate = self
|
|
193
|
+
extension HouseStore: HMHomeDelegate {
|
|
194
|
+
nonisolated func home(_ house: HMHome, didAdd device: HMAccessory) {
|
|
243
195
|
Task { @MainActor in
|
|
244
|
-
|
|
196
|
+
device.delegate = self
|
|
197
|
+
reload()
|
|
245
198
|
}
|
|
246
199
|
}
|
|
247
200
|
|
|
248
|
-
nonisolated func home(
|
|
249
|
-
|
|
250
|
-
didRemove accessory: HMAccessory
|
|
251
|
-
) {
|
|
252
|
-
Task { @MainActor in
|
|
253
|
-
// Refresh accessory list
|
|
254
|
-
}
|
|
201
|
+
nonisolated func home(_ house: HMHome, didRemove device: HMAccessory) {
|
|
202
|
+
Task { @MainActor in reload() }
|
|
255
203
|
}
|
|
256
204
|
|
|
257
|
-
nonisolated func home(
|
|
258
|
-
|
|
259
|
-
didAdd room: HMRoom
|
|
260
|
-
) {
|
|
261
|
-
Task { @MainActor in
|
|
262
|
-
// Refresh room list
|
|
263
|
-
}
|
|
205
|
+
nonisolated func home(_ house: HMHome, didAdd space: HMRoom) {
|
|
206
|
+
Task { @MainActor in reload() }
|
|
264
207
|
}
|
|
265
208
|
|
|
266
|
-
nonisolated func home(
|
|
267
|
-
|
|
268
|
-
didUpdateNameFor room: HMRoom
|
|
269
|
-
) {
|
|
270
|
-
Task { @MainActor in
|
|
271
|
-
// Update room name display
|
|
272
|
-
}
|
|
209
|
+
nonisolated func home(_ house: HMHome, didUpdateNameFor space: HMRoom) {
|
|
210
|
+
Task { @MainActor in reload() }
|
|
273
211
|
}
|
|
274
212
|
}
|
|
275
213
|
```
|
|
@@ -277,129 +215,83 @@ extension HomeStore: HMHomeDelegate {
|
|
|
277
215
|
### HMAccessoryDelegate
|
|
278
216
|
|
|
279
217
|
```swift
|
|
280
|
-
extension
|
|
281
|
-
nonisolated func accessory(
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
) {
|
|
286
|
-
Task { @MainActor in
|
|
287
|
-
// Update UI for the changed characteristic
|
|
288
|
-
let newValue = characteristic.value
|
|
289
|
-
print("\(accessory.name).\(characteristic.characteristicType) = \(newValue ?? "nil")")
|
|
290
|
-
}
|
|
218
|
+
extension HouseStore: HMAccessoryDelegate {
|
|
219
|
+
nonisolated func accessory(_ device: HMAccessory,
|
|
220
|
+
service: HMService,
|
|
221
|
+
didUpdateValueFor trait: HMCharacteristic) {
|
|
222
|
+
Task { @MainActor in reload() }
|
|
291
223
|
}
|
|
292
224
|
|
|
293
|
-
nonisolated func accessoryDidUpdateReachability(
|
|
294
|
-
|
|
295
|
-
) {
|
|
296
|
-
Task { @MainActor in
|
|
297
|
-
print("\(accessory.name) reachable: \(accessory.isReachable)")
|
|
298
|
-
}
|
|
225
|
+
nonisolated func accessoryDidUpdateReachability(_ device: HMAccessory) {
|
|
226
|
+
Task { @MainActor in reload() }
|
|
299
227
|
}
|
|
300
228
|
|
|
301
|
-
nonisolated func accessoryDidUpdateName(
|
|
302
|
-
|
|
303
|
-
) {
|
|
304
|
-
Task { @MainActor in
|
|
305
|
-
// Refresh name display
|
|
306
|
-
}
|
|
229
|
+
nonisolated func accessoryDidUpdateName(_ device: HMAccessory) {
|
|
230
|
+
Task { @MainActor in reload() }
|
|
307
231
|
}
|
|
308
232
|
}
|
|
309
233
|
```
|
|
310
234
|
|
|
311
|
-
##
|
|
312
|
-
|
|
313
|
-
### Finding Specific Service Types
|
|
235
|
+
## Finding services by type
|
|
314
236
|
|
|
315
237
|
```swift
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
$0.characteristicType == HMCharacteristicTypeCurrentTemperature
|
|
322
|
-
}
|
|
323
|
-
let targetTemp = service.characteristics.first {
|
|
324
|
-
$0.characteristicType == HMCharacteristicTypeTargetTemperature
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
currentTemp?.readValue { _ in
|
|
328
|
-
print("Current: \(currentTemp?.value ?? "?")")
|
|
329
|
-
}
|
|
238
|
+
let climate = house.servicesWithTypes([HMServiceTypeThermostat]) ?? []
|
|
239
|
+
for unit in climate {
|
|
240
|
+
let now = unit.characteristics.first { $0.characteristicType == HMCharacteristicTypeCurrentTemperature }
|
|
241
|
+
let goal = unit.characteristics.first { $0.characteristicType == HMCharacteristicTypeTargetTemperature }
|
|
242
|
+
print(now?.value ?? "?", "->", goal?.value ?? "?")
|
|
330
243
|
}
|
|
331
244
|
```
|
|
332
245
|
|
|
333
|
-
###
|
|
246
|
+
### Frequently used service types
|
|
334
247
|
|
|
335
|
-
| Constant |
|
|
248
|
+
| Constant | Typical device |
|
|
336
249
|
|---|---|
|
|
337
|
-
| `HMServiceTypeLightbulb` | Light
|
|
338
|
-
| `HMServiceTypeThermostat` |
|
|
250
|
+
| `HMServiceTypeLightbulb` | Light with power, brightness, colour |
|
|
251
|
+
| `HMServiceTypeThermostat` | Heating and cooling control |
|
|
339
252
|
| `HMServiceTypeLockMechanism` | Door lock |
|
|
340
253
|
| `HMServiceTypeGarageDoorOpener` | Garage door |
|
|
341
|
-
| `HMServiceTypeSwitch` |
|
|
342
|
-
| `HMServiceTypeMotionSensor` | Motion
|
|
343
|
-
| `HMServiceTypeTemperatureSensor` | Temperature
|
|
344
|
-
| `HMServiceTypeContactSensor` | Door
|
|
254
|
+
| `HMServiceTypeSwitch` | Plain on/off switch |
|
|
255
|
+
| `HMServiceTypeMotionSensor` | Motion detector |
|
|
256
|
+
| `HMServiceTypeTemperatureSensor` | Temperature probe |
|
|
257
|
+
| `HMServiceTypeContactSensor` | Door or window open/closed sensor |
|
|
345
258
|
|
|
346
|
-
###
|
|
259
|
+
### Frequently used characteristic types
|
|
347
260
|
|
|
348
|
-
| Constant |
|
|
261
|
+
| Constant | Swift value | Notes |
|
|
349
262
|
|---|---|---|
|
|
350
|
-
| `HMCharacteristicTypePowerState` | Bool |
|
|
351
|
-
| `HMCharacteristicTypeBrightness` | Int
|
|
352
|
-
| `HMCharacteristicTypeHue` | Float
|
|
353
|
-
| `HMCharacteristicTypeSaturation` | Float
|
|
354
|
-
| `HMCharacteristicTypeCurrentTemperature` | Float | Celsius
|
|
355
|
-
| `HMCharacteristicTypeTargetTemperature` | Float | Celsius
|
|
356
|
-
| `HMCharacteristicTypeLockCurrentState` | Int |
|
|
357
|
-
| `HMCharacteristicTypeLockTargetState` | Int |
|
|
263
|
+
| `HMCharacteristicTypePowerState` | `Bool` | on or off |
|
|
264
|
+
| `HMCharacteristicTypeBrightness` | `Int` | 0 to 100 percent |
|
|
265
|
+
| `HMCharacteristicTypeHue` | `Float` | 0 to 360 degrees |
|
|
266
|
+
| `HMCharacteristicTypeSaturation` | `Float` | 0 to 100 percent |
|
|
267
|
+
| `HMCharacteristicTypeCurrentTemperature` | `Float` | Celsius |
|
|
268
|
+
| `HMCharacteristicTypeTargetTemperature` | `Float` | Celsius |
|
|
269
|
+
| `HMCharacteristicTypeLockCurrentState` | `Int` | 0 means unsecured |
|
|
270
|
+
| `HMCharacteristicTypeLockTargetState` | `Int` | desired lock state |
|
|
358
271
|
|
|
359
|
-
##
|
|
360
|
-
|
|
361
|
-
### Full Handler with Network Selection
|
|
272
|
+
## A fuller MatterSupport handler
|
|
362
273
|
|
|
363
274
|
```swift
|
|
364
275
|
import MatterSupport
|
|
365
276
|
|
|
366
|
-
final class
|
|
367
|
-
|
|
277
|
+
final class CabinPairingHandler: MatterAddDeviceExtensionRequestHandler {
|
|
368
278
|
override func validateDeviceCredential(
|
|
369
|
-
_
|
|
370
|
-
MatterAddDeviceExtensionRequestHandler.DeviceCredential
|
|
279
|
+
_ credential: MatterAddDeviceExtensionRequestHandler.DeviceCredential
|
|
371
280
|
) async throws {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
let
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
// If validation fails, throw an error to reject the device
|
|
379
|
-
guard isValidCertificateChain(dac: dac, pai: pai, cd: cd) else {
|
|
380
|
-
throw MatterCommissioningError.invalidCredential
|
|
381
|
-
}
|
|
281
|
+
let dac = credential.deviceAttestationCertificate
|
|
282
|
+
let pai = credential.productAttestationIntermediateCertificate
|
|
283
|
+
let declaration = credential.certificationDeclaration
|
|
284
|
+
// Verify DAC -> PAI -> one of your trusted PAA roots, and check the
|
|
285
|
+
// certification declaration. Throw to stop pairing.
|
|
286
|
+
try AttestationChecker.verify(dac: dac, pai: pai, declaration: declaration)
|
|
382
287
|
}
|
|
383
288
|
|
|
384
289
|
override func rooms(
|
|
385
290
|
in home: MatterAddDeviceRequest.Home?
|
|
386
291
|
) async -> [MatterAddDeviceRequest.Room] {
|
|
387
|
-
// Fetch rooms from your backend for the given home
|
|
388
292
|
guard let home else { return [] }
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
return roomNames.map { MatterAddDeviceRequest.Room(displayName: $0) }
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
override func configureDevice(
|
|
395
|
-
named name: String,
|
|
396
|
-
in room: MatterAddDeviceRequest.Room?
|
|
397
|
-
) async {
|
|
398
|
-
// Save device configuration to your ecosystem backend
|
|
399
|
-
await saveDeviceToBackend(
|
|
400
|
-
deviceName: name,
|
|
401
|
-
roomName: room?.displayName
|
|
402
|
-
)
|
|
293
|
+
let names = await CabinBackend.roomNames(forHome: home.displayName)
|
|
294
|
+
return names.map { MatterAddDeviceRequest.Room(displayName: $0) }
|
|
403
295
|
}
|
|
404
296
|
|
|
405
297
|
override func commissionDevice(
|
|
@@ -407,52 +299,54 @@ final class MyMatterHandler: MatterAddDeviceExtensionRequestHandler {
|
|
|
407
299
|
onboardingPayload: String,
|
|
408
300
|
commissioningID: UUID
|
|
409
301
|
) async throws {
|
|
410
|
-
//
|
|
411
|
-
//
|
|
412
|
-
try await
|
|
413
|
-
payload: onboardingPayload,
|
|
414
|
-
commissioningID: commissioningID
|
|
415
|
-
)
|
|
302
|
+
// Use MTRDeviceController from the Matter framework to add the
|
|
303
|
+
// device to your fabric with this onboarding payload.
|
|
304
|
+
try await CabinFabric.commission(payload: onboardingPayload, id: commissioningID)
|
|
416
305
|
}
|
|
417
306
|
|
|
418
307
|
override func selectWiFiNetwork(
|
|
419
|
-
from
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
-> MatterAddDeviceExtensionRequestHandler.WiFiNetworkAssociation {
|
|
423
|
-
// Use the system default network or specify one
|
|
424
|
-
return .defaultSystemNetwork
|
|
308
|
+
from wifiScanResults: [MatterAddDeviceExtensionRequestHandler.WiFiScanResult]
|
|
309
|
+
) async throws -> MatterAddDeviceExtensionRequestHandler.WiFiNetworkAssociation {
|
|
310
|
+
.defaultSystemNetwork
|
|
425
311
|
}
|
|
426
312
|
|
|
427
313
|
override func selectThreadNetwork(
|
|
428
|
-
from
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
-> MatterAddDeviceExtensionRequestHandler.ThreadNetworkAssociation {
|
|
432
|
-
return .defaultSystemNetwork
|
|
314
|
+
from threadScanResults: [MatterAddDeviceExtensionRequestHandler.ThreadScanResult]
|
|
315
|
+
) async throws -> MatterAddDeviceExtensionRequestHandler.ThreadNetworkAssociation {
|
|
316
|
+
.defaultSystemNetwork
|
|
433
317
|
}
|
|
434
318
|
}
|
|
435
319
|
```
|
|
436
320
|
|
|
437
|
-
|
|
321
|
+
`AttestationChecker`, `CabinBackend` and `CabinFabric` stand for your own
|
|
322
|
+
code. The three attestation values are the Device Attestation Certificate
|
|
323
|
+
(DAC), the Product Attestation Intermediate (PAI) and the Certification
|
|
324
|
+
Declaration (CD). Returning `.defaultSystemNetwork` from either selector lets
|
|
325
|
+
the system choose the network.
|
|
326
|
+
|
|
327
|
+
## Simulated accessories for testing
|
|
328
|
+
|
|
329
|
+
The simulator is part of **Additional Tools for Xcode**, downloadable from the
|
|
330
|
+
Apple developer downloads page.
|
|
331
|
+
|
|
332
|
+
1. Open HomeKit Accessory Simulator.
|
|
333
|
+
2. Create a few virtual accessories: a light, a lock, a sensor.
|
|
334
|
+
3. Pair them with the app running on a device or in Simulator, then drive
|
|
335
|
+
scenes and triggers against them.
|
|
438
336
|
|
|
439
|
-
|
|
440
|
-
2. Launch **HomeKit Accessory Simulator**
|
|
441
|
-
3. Create simulated accessories (lights, locks, sensors)
|
|
442
|
-
4. Pair them with your app running in Simulator or on device
|
|
337
|
+
A debug-only dump helps when pairing looks wrong:
|
|
443
338
|
|
|
444
339
|
```swift
|
|
445
|
-
// Enable verbose logging during development
|
|
446
|
-
#if DEBUG
|
|
447
340
|
import os
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
341
|
+
|
|
342
|
+
#if DEBUG
|
|
343
|
+
let homeLog = Logger(subsystem: "com.example.cabin", category: "homekit")
|
|
344
|
+
|
|
345
|
+
func dumpDevices(in house: HMHome) {
|
|
346
|
+
for device in house.accessories {
|
|
347
|
+
homeLog.debug("\(device.name) reachable=\(device.isReachable)")
|
|
348
|
+
for service in device.services {
|
|
349
|
+
homeLog.debug(" \(service.localizedDescription) [\(service.serviceType)]")
|
|
456
350
|
}
|
|
457
351
|
}
|
|
458
352
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
name: html-semantic
|
|
3
3
|
description: "Semantic HTML5: elements, forms with validation and accessibility, SEO best practices, structured data, Open Graph, Twitter Cards. Use when writing or reviewing markup, forms or document structure for semantics, accessibility and SEO."
|
|
4
4
|
metadata:
|
|
5
|
+
source: multi-agent-pipeline
|
|
5
6
|
tags: [html, semantic, seo, forms, open-graph, structured-data, frontend]
|
|
6
7
|
version: "2025.1"
|
|
7
8
|
---
|