@mmerterden/multi-agent-pipeline 16.18.0 → 16.19.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 +45 -0
- package/README.md +5 -5
- package/README.tr.md +2 -2
- package/docs/FIGMA_PIPELINE.md +1 -1
- package/docs/adr/0001-three-model-triage.md +4 -2
- package/docs/architecture.md +2 -2
- package/docs/ecosystem.md +13 -11
- package/docs/features.md +2 -2
- package/index.js +1 -1
- package/install/_common.mjs +25 -1
- package/install/_dev-only-files.mjs +2 -2
- package/install/_mcp-register.mjs +4 -3
- package/install/_plugin-skills.mjs +1 -3
- package/install/copilot.mjs +18 -9
- package/install/index.mjs +2 -4
- package/install/templates/copilot-instructions.md +7 -7
- package/package.json +1 -1
- package/pipeline/claude-md-template.md +2 -2
- package/pipeline/commands/multi-agent/SKILL.md +5 -5
- package/pipeline/commands/multi-agent/complaint-analysis/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/design-check/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/help/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/local-autopilot/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/review/SKILL.md +27 -14
- package/pipeline/commands/multi-agent/review-analysis/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/store-ready/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/sync/SKILL.md +2 -2
- package/pipeline/commands/sim-test.md +54 -15
- package/pipeline/lib/credential-inventory.sh +15 -2
- package/pipeline/lib/credential-store-resolver.sh +14 -4
- package/pipeline/lib/credential-store.sh +8 -2
- package/pipeline/lib/extract-conventions.sh +1 -14
- package/pipeline/lib/fetch-confluence.sh +12 -4
- package/pipeline/lib/fetch-crashlytics.sh +11 -8
- package/pipeline/lib/fetch-document.sh +1 -1
- package/pipeline/lib/fetch-figma-annotations.sh +7 -5
- package/pipeline/lib/fetch-fortify.sh +5 -3
- package/pipeline/lib/fetch-graylog.sh +5 -3
- package/pipeline/lib/figma-mcp-refresh.sh +1 -1
- package/pipeline/lib/figma-screenshot.sh +27 -24
- package/pipeline/lib/figma-token.sh +8 -4
- package/pipeline/lib/issue-fetcher.sh +0 -1
- package/pipeline/lib/jira-publish.sh +7 -5
- package/pipeline/lib/md2confluence-v3.py +13 -7
- package/pipeline/lib/multi-repo-pipeline.sh +18 -8
- package/pipeline/lib/plan-todos.sh +11 -0
- package/pipeline/lib/post-pr-review.sh +9 -2
- package/pipeline/lib/repo-cache.sh +18 -10
- package/pipeline/lib/review-watch.sh +60 -14
- package/pipeline/lib/shadow-git.sh +8 -4
- package/pipeline/lib/vercel-deploy.sh +2 -2
- package/pipeline/multi-agent-refs/_dev-context.md +5 -2
- package/pipeline/multi-agent-refs/analysis/locked.md +4 -4
- package/pipeline/multi-agent-refs/analysis/render.md +1 -1
- package/pipeline/multi-agent-refs/cross-cli-contract.md +1 -1
- package/pipeline/multi-agent-refs/outside-the-pipeline.md +6 -6
- package/pipeline/multi-agent-refs/phases/log-format.md +1 -1
- package/pipeline/multi-agent-refs/phases/modes.md +1 -1
- package/pipeline/multi-agent-refs/phases/phase-0-init.md +4 -2
- package/pipeline/multi-agent-refs/phases/phase-1-analysis.md +3 -3
- package/pipeline/multi-agent-refs/phases/phase-2-planning.md +5 -5
- package/pipeline/multi-agent-refs/phases/phase-4-review.md +21 -16
- package/pipeline/multi-agent-refs/tracker-contract.md +1 -1
- package/pipeline/rules/figma-pipeline.md +18 -72
- package/pipeline/rules/outside-the-pipeline.md +4 -3
- package/pipeline/schemas/agent-state.schema.json +1 -1
- package/pipeline/schemas/token-budget.json +1 -1
- package/pipeline/scripts/_stack-routing.mjs +1 -1
- package/pipeline/scripts/agent-guard.py +102 -21
- package/pipeline/scripts/anonymize-findings.mjs +7 -6
- package/pipeline/scripts/build-skills-index.mjs +14 -3
- package/pipeline/scripts/cost-budget-check.mjs +5 -3
- package/pipeline/scripts/cost-lib.sh +0 -15
- package/pipeline/scripts/diff-explain.mjs +22 -12
- package/pipeline/scripts/gc-refs.sh +6 -2
- package/pipeline/scripts/gc-tmp.sh +1 -1
- package/pipeline/scripts/gc-worktrees.sh +1 -1
- package/pipeline/scripts/gen-mode-dispatch.mjs +3 -3
- package/pipeline/scripts/github-ssh-setup.sh +7 -2
- package/pipeline/scripts/graph-build.mjs +2 -2
- package/pipeline/scripts/jira-wiki-escape.mjs +2 -1
- package/pipeline/scripts/keychain.py +12 -11
- package/pipeline/scripts/learning-curve.mjs +1 -1
- package/pipeline/scripts/migrate-prefs.mjs +1 -1
- package/pipeline/scripts/output-quality-check.sh +3 -1
- package/pipeline/scripts/phase-tracker.sh +1 -1
- package/pipeline/scripts/phase0-exit-gate.mjs +2 -1
- package/pipeline/scripts/plan-coverage-gate.mjs +2 -1
- package/pipeline/scripts/pre-commit-check.sh +23 -13
- package/pipeline/scripts/prune-logs.sh +1 -1
- package/pipeline/scripts/render-agent-log-cost.sh +3 -1
- package/pipeline/scripts/render-cost-summary.sh +4 -2
- package/pipeline/scripts/render-work-summary.sh +5 -3
- package/pipeline/scripts/repo-map.mjs +3 -2
- package/pipeline/scripts/scan-skills.sh +6 -2
- package/pipeline/scripts/search-logs.sh +8 -6
- package/pipeline/scripts/sign-skills.sh +3 -1
- package/pipeline/scripts/smoke-cross-cli-behavior.sh +1 -1
- package/pipeline/scripts/triage-memory.mjs +25 -4
- package/pipeline/scripts/uninstall.mjs +20 -12
- package/pipeline/scripts/update-check.sh +2 -2
- package/pipeline/scripts/update-issue-progress.sh +6 -5
- package/pipeline/scripts/validate-analysis-doc.mjs +6 -6
- package/pipeline/scripts/verify-skills.sh +3 -1
- package/pipeline/scripts/worktree-finalize.sh +22 -10
- package/pipeline/skills/.skill-manifest.json +81 -57
- package/pipeline/skills/.skills-index.json +19 -19
- package/pipeline/skills/shared/README.md +8 -8
- package/pipeline/skills/shared/core/multi-agent/SKILL.md +7 -7
- package/pipeline/skills/shared/core/multi-agent-design-check/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +2 -2
- package/pipeline/skills/shared/core/multi-agent-local/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-local-autopilot/SKILL.md +2 -2
- package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +23 -14
- package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +2 -2
- package/pipeline/skills/shared/external/NOTICE-dimillian-skills.md +56 -0
- package/pipeline/skills/shared/external/accessibility-compliance-accessibility-audit/SKILL.md +0 -4
- package/pipeline/skills/shared/external/api-patterns/SKILL.md +12 -24
- package/pipeline/skills/shared/external/app-store-changelog/references/release-notes-guidelines.md +34 -0
- package/pipeline/skills/shared/external/app-store-changelog/scripts/collect_release_changes.sh +33 -0
- package/pipeline/skills/shared/external/architecture/SKILL.md +7 -9
- package/pipeline/skills/shared/external/debugging-strategies/SKILL.md +0 -4
- package/pipeline/skills/shared/external/fastapi-pro/SKILL.md +0 -1
- package/pipeline/skills/shared/external/github-actions-templates/SKILL.md +0 -14
- package/pipeline/skills/shared/external/hig-components-content/SKILL.md +13 -13
- package/pipeline/skills/shared/external/hig-components-layout/SKILL.md +16 -16
- package/pipeline/skills/shared/external/hig-components-status/SKILL.md +6 -6
- package/pipeline/skills/shared/external/hig-components-system/SKILL.md +13 -13
- package/pipeline/skills/shared/external/hig-foundations/SKILL.md +23 -23
- package/pipeline/skills/shared/external/hig-inputs/SKILL.md +18 -18
- package/pipeline/skills/shared/external/hig-patterns/SKILL.md +30 -30
- package/pipeline/skills/shared/external/hig-platforms/SKILL.md +11 -11
- package/pipeline/skills/shared/external/hig-technologies/SKILL.md +33 -33
- package/pipeline/skills/shared/external/ios-coding-standard/references/STANDARD.md +52 -52
- package/pipeline/skills/shared/external/ios-coding-standard/references/lint-local.sh +1 -1
- package/pipeline/skills/shared/external/ios-coding-standard/references/rules.yml +11 -11
- package/pipeline/skills/shared/external/ios-developer/SKILL.md +0 -1
- package/pipeline/skills/shared/external/ios-module-structure/SKILL.md +7 -3
- package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +9 -15
- package/pipeline/skills/shared/external/macos-spm-app-packaging/SKILL.md +0 -5
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/bootstrap/Package.swift +17 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/bootstrap/Sources/MyApp/Resources/.keep +0 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/bootstrap/Sources/MyApp/main.swift +11 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/bootstrap/version.env +2 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/build_icon.sh +49 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/compile_and_run.sh +63 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/launch.sh +28 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/make_appcast.sh +82 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/package_app.sh +206 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/setup_dev_signing.sh +52 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/sign-and-notarize.sh +52 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/version.env +2 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/references/packaging.md +17 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/references/release.md +32 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/references/scaffold.md +79 -0
- package/pipeline/skills/shared/external/monorepo-architect/SKILL.md +0 -1
- package/pipeline/skills/shared/external/nodejs-backend-patterns/SKILL.md +0 -4
- package/pipeline/skills/shared/external/swift-concurrency-expert/references/approachable-concurrency.md +63 -0
- package/pipeline/skills/shared/external/swift-concurrency-expert/references/swift-6-2-concurrency.md +272 -0
- package/pipeline/skills/shared/external/swift-concurrency-expert/references/swiftui-concurrency-tour-wwdc.md +33 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/code-smells.md +150 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/demystify-swiftui-performance-wwdc23.md +46 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/optimizing-swiftui-performance-instruments.md +29 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/profiling-intake.md +44 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/report-template.md +47 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/understanding-hangs-in-your-app.md +33 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/understanding-improving-swiftui-performance.md +52 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/app-wiring.md +201 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/async-state.md +96 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/components-index.md +46 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/controls.md +57 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/deeplinks.md +66 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/focus.md +90 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/form.md +97 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/grids.md +71 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/haptics.md +71 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/input-toolbar.md +51 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/lightweight-clients.md +93 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/list.md +86 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/loading-placeholders.md +38 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/macos-settings.md +71 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/matched-transitions.md +59 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/media.md +73 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/menu-bar.md +101 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/navigationstack.md +159 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/overlay.md +45 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/performance.md +62 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/previews.md +48 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/scroll-reveal.md +133 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/scrollview.md +87 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/searchable.md +71 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/sheets.md +155 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/split-views.md +72 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/tabview.md +114 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/theming.md +71 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/title-menus.md +93 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/top-bar.md +49 -0
- package/pipeline/skills/shared/external/swiftui-view-refactor/references/mv-patterns.md +161 -0
- package/pipeline/skills/skills-index.md +8 -8
- package/pipeline/skills/shared/external/help-skills/SKILL.md +0 -166
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: hig-inputs
|
|
3
|
-
description: "
|
|
3
|
+
description: "Apple Human Interface Guidelines for input methods: touch gestures, keyboards, Apple Pencil, pointing devices, game controllers, Digital Crown and spatial input. Use when designing or reviewing input controls, forms or text entry on an Apple platform."
|
|
4
4
|
risk: unknown
|
|
5
5
|
source: community
|
|
6
6
|
date_added: '2026-02-27'
|
|
@@ -64,23 +64,23 @@ Check for `.claude/apple-design-context.md` before asking questions. Use existin
|
|
|
64
64
|
|
|
65
65
|
15. **Gyroscope, accelerometer, UWB: use judiciously.** Suits gaming, fitness, AR. Not for essential tasks. Provide calibration and reset. For UWB, communicate distance and direction with visual or haptic cues.
|
|
66
66
|
|
|
67
|
-
##
|
|
68
|
-
|
|
69
|
-
|
|
|
70
|
-
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
|
|
|
75
|
-
|
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
|
|
|
79
|
-
|
|
|
80
|
-
|
|
|
81
|
-
|
|
|
82
|
-
|
|
|
83
|
-
|
|
|
67
|
+
## Topics
|
|
68
|
+
|
|
69
|
+
| Topic | Key content |
|
|
70
|
+
|---|---|
|
|
71
|
+
| Touch gestures | Tap, swipe, pinch, long press, drag, system gestures |
|
|
72
|
+
| Apple Pencil | Precision, pressure, tilt, hover, handwriting |
|
|
73
|
+
| Keyboards | Shortcuts, navigation, software keyboard, Command key |
|
|
74
|
+
| Game controllers | MFi, extended gamepad, remapping, fallbacks |
|
|
75
|
+
| Pointer/trackpad | Hover, cursor morphing, trackpad gestures |
|
|
76
|
+
| Digital Crown | Scrolling, value adjustment, haptic detents |
|
|
77
|
+
| Eye tracking | Look and tap, gaze targeting, hit target sizing |
|
|
78
|
+
| Spatial input | Hand gestures, direct manipulation, immersive input |
|
|
79
|
+
| Focus system | tvOS/visionOS navigation, focus indicators, groups |
|
|
80
|
+
| Remotes | Touch surface, clickpad, simple interactions |
|
|
81
|
+
| Motion sensors | Gyroscope, accelerometer, calibration, gaming |
|
|
82
|
+
| Nearby interactions | U1 chip, directional finding, proximity triggers |
|
|
83
|
+
| Camera Control | iPhone camera hardware button, quick launch |
|
|
84
84
|
|
|
85
85
|
## Output Format
|
|
86
86
|
|
|
@@ -28,35 +28,35 @@ Check for `.claude/apple-design-context.md` before asking questions. Use existin
|
|
|
28
28
|
|
|
29
29
|
8. **Respect user attention.** Consolidate notifications, minimize interruptions, give users control over alerts. Never use notifications for marketing.
|
|
30
30
|
|
|
31
|
-
##
|
|
32
|
-
|
|
33
|
-
|
|
|
34
|
-
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
|
41
|
-
|
|
|
42
|
-
|
|
|
43
|
-
|
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
|
|
|
57
|
-
|
|
|
58
|
-
|
|
|
59
|
-
|
|
|
31
|
+
## Topics
|
|
32
|
+
|
|
33
|
+
| Topic | Key content |
|
|
34
|
+
|---|---|
|
|
35
|
+
| Charting Data | Data visualization patterns, accessible charts, interactive elements |
|
|
36
|
+
| Collaboration & Sharing | Share sheets, activity views, collaborative editing, SharePlay |
|
|
37
|
+
| Drag and Drop | Drag sources, drop targets, spring loading, multi-item drag, visual feedback |
|
|
38
|
+
| Entering Data | Text fields, pickers, steppers, input validation, keyboard types, autofill |
|
|
39
|
+
| Feedback | Alerts, action sheets, haptic patterns, sound feedback, visual indicators |
|
|
40
|
+
| File Management | Document browser, file providers, iCloud integration, document lifecycle |
|
|
41
|
+
| Going Full Screen | Full-screen transitions, immersive content, exiting full screen |
|
|
42
|
+
| Launching | Launch screens, state restoration, cold vs warm launch |
|
|
43
|
+
| Live Viewing Apps | Live content display, real-time updates, Live Activities, Dynamic Island |
|
|
44
|
+
| Loading | Activity indicators, progress views, skeleton screens, lazy loading, placeholders |
|
|
45
|
+
| Managing Accounts | Sign in with Apple, passkeys, account creation, credential autofill, account deletion |
|
|
46
|
+
| Managing Notifications | Permission requests, grouping, actionable notifications, provisional delivery |
|
|
47
|
+
| Modality | Sheets, alerts, popovers, full-screen modals, when to use each |
|
|
48
|
+
| Multitasking | iPad Split View, Slide Over, Stage Manager, responsive layout, size class transitions |
|
|
49
|
+
| Offering Help | Contextual tips, onboarding hints, help menus, support links |
|
|
50
|
+
| Onboarding | Welcome screens, feature highlights, progressive onboarding, skip options |
|
|
51
|
+
| Playing Audio | Audio sessions, background audio, Now Playing, audio routing, interruptions |
|
|
52
|
+
| Playing Haptics | Core Haptics, UIFeedbackGenerator, haptic patterns, custom haptics |
|
|
53
|
+
| Playing Video | Video player controls, picture-in-picture, AirPlay, full-screen video |
|
|
54
|
+
| Printing | Print dialogs, page setup, AirPrint integration |
|
|
55
|
+
| Ratings & Reviews | SKStoreReviewController, timing, frequency limits, in-app feedback |
|
|
56
|
+
| Searching | Search bars, suggestions, scoped search, results display, recents |
|
|
57
|
+
| Settings | In-app vs Settings app, preference organization, toggles, defaults |
|
|
58
|
+
| Undo and Redo | Shake to undo, undo/redo stack, multi-level undo |
|
|
59
|
+
| Workouts | Workout sessions, live metrics, Always On display, summaries, HealthKit |
|
|
60
60
|
|
|
61
61
|
## Pattern Selection Guide
|
|
62
62
|
|
|
@@ -72,7 +72,7 @@ Check for `.claude/apple-design-context.md` before asking questions. Use existin
|
|
|
72
72
|
|
|
73
73
|
## Output Format
|
|
74
74
|
|
|
75
|
-
1. **Recommended pattern with rationale**, citing the relevant
|
|
75
|
+
1. **Recommended pattern with rationale**, citing the relevant HIG topic.
|
|
76
76
|
2. **Step-by-step implementation** covering each screen or state.
|
|
77
77
|
3. **Platform variations** for targeted platforms.
|
|
78
78
|
4. **Common pitfalls** that violate HIG for this pattern.
|
|
@@ -28,17 +28,17 @@ Check for `.claude/apple-design-context.md` before asking questions. Use existin
|
|
|
28
28
|
|
|
29
29
|
8. **Games: own paradigm.** Free to define in-game interaction models, but still respect platform conventions for system interactions (notifications, accessibility, controllers).
|
|
30
30
|
|
|
31
|
-
##
|
|
32
|
-
|
|
33
|
-
|
|
|
34
|
-
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
|
41
|
-
|
|
|
31
|
+
## Topics
|
|
32
|
+
|
|
33
|
+
| Topic | Key content |
|
|
34
|
+
|---|---|
|
|
35
|
+
| iOS | Touch, tab bars, navigation stacks, gestures, screen sizes, safe areas |
|
|
36
|
+
| iPadOS | Multitasking, sidebars, pointer, keyboard, Apple Pencil, Stage Manager |
|
|
37
|
+
| macOS | Menu bars, toolbars, window management, keyboard shortcuts, dense layouts, Dock |
|
|
38
|
+
| tvOS | Focus engine, Siri Remote, lean-back experience, content-forward, parallax |
|
|
39
|
+
| visionOS | Spatial computing, windows/volumes/spaces, eye tracking, hand gestures, depth |
|
|
40
|
+
| watchOS | Glanceable UI, Digital Crown, complications, notifications, haptics |
|
|
41
|
+
| Games | Controllers, immersive experiences, platform-specific conventions, accessibility |
|
|
42
42
|
|
|
43
43
|
## Decision Framework
|
|
44
44
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: hig-technologies
|
|
3
|
-
description: "
|
|
3
|
+
description: "Apple Human Interface Guidelines for Apple technologies: Siri, Apple Pay, Wallet, HealthKit, CarPlay, iCloud, Maps, in-app purchase and Sign in with Apple. Use when designing or reviewing a feature built on an Apple technology such as Sign in with Apple, Wallet or Maps."
|
|
4
4
|
risk: unknown
|
|
5
5
|
source: community
|
|
6
6
|
date_added: '2026-02-27'
|
|
@@ -62,38 +62,38 @@ Check for `.claude/apple-design-context.md` before asking questions. Use existin
|
|
|
62
62
|
|
|
63
63
|
13. **Baseline requirement.** Every element has a meaningful VoiceOver label, trait, and action. Support Dynamic Type, Switch Control, and other assistive technologies. Test entirely with VoiceOver enabled.
|
|
64
64
|
|
|
65
|
-
##
|
|
66
|
-
|
|
67
|
-
|
|
|
68
|
-
|
|
69
|
-
|
|
|
70
|
-
|
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
|
|
|
75
|
-
|
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
|
|
|
79
|
-
|
|
|
80
|
-
|
|
|
81
|
-
|
|
|
82
|
-
|
|
|
83
|
-
|
|
|
84
|
-
|
|
|
85
|
-
|
|
|
86
|
-
|
|
|
87
|
-
|
|
|
88
|
-
|
|
|
89
|
-
|
|
|
90
|
-
|
|
|
91
|
-
|
|
|
92
|
-
|
|
|
93
|
-
|
|
|
94
|
-
|
|
|
95
|
-
|
|
|
96
|
-
|
|
|
65
|
+
## Topics
|
|
66
|
+
|
|
67
|
+
| Topic | Key content |
|
|
68
|
+
|---|---|
|
|
69
|
+
| Siri | Intents, shortcuts, voice interaction, App Shortcuts |
|
|
70
|
+
| Apple Pay | Payment buttons, checkout flow, security |
|
|
71
|
+
| Tap to Pay | Merchant flows, contactless payment |
|
|
72
|
+
| In-app purchase | Subscriptions, one-time purchases, transparency |
|
|
73
|
+
| HealthKit | Health data access, privacy, permissions |
|
|
74
|
+
| CareKit | Care plans, tasks, health management |
|
|
75
|
+
| ResearchKit | Studies, informed consent, data collection |
|
|
76
|
+
| HomeKit | Smart home control, device state, scenes |
|
|
77
|
+
| ARKit | Spatial context, surface detection, setup |
|
|
78
|
+
| Core ML | Predictions, smart features, confidence handling |
|
|
79
|
+
| Generative AI | Attribution, editing, responsible AI, uncertainty |
|
|
80
|
+
| iCloud | CloudKit, cross-device sync, conflict resolution |
|
|
81
|
+
| Sign in with Apple | Authentication, privacy, button styles |
|
|
82
|
+
| ID Verifier | Identity verification, document scanning |
|
|
83
|
+
| SharePlay | Shared experiences, participant presence |
|
|
84
|
+
| AirPlay | Media streaming, Now Playing, wireless display |
|
|
85
|
+
| CarPlay | Driver safety, permitted app types, large targets |
|
|
86
|
+
| Game Center | Achievements, leaderboards, multiplayer |
|
|
87
|
+
| VoiceOver | Screen reader, labels, traits, accessibility |
|
|
88
|
+
| Wallet | Passes, tickets, loyalty cards |
|
|
89
|
+
| NFC | Tag reading, quick interactions, App Clips |
|
|
90
|
+
| Maps | Location display, annotations, directions |
|
|
91
|
+
| Mac Catalyst | iPad to Mac, menu bar, keyboard, pointer |
|
|
92
|
+
| Live Photos | Motion capture, playback, editing |
|
|
93
|
+
| iMessage apps | Messages extension, stickers, compact UI |
|
|
94
|
+
| ShazamKit | Audio recognition, music identification |
|
|
95
|
+
| Always-on display | Dimmed state, power efficiency, reduced updates |
|
|
96
|
+
| Photo editing | System photo editor, filters, adjustments |
|
|
97
97
|
|
|
98
98
|
## Output Format
|
|
99
99
|
|
|
@@ -44,19 +44,19 @@ Most sensitive values in a flow are used and dropped, and those must not be pers
|
|
|
44
44
|
// ✗ over-persistence - a value the flow throws away in 30 seconds now outlives logout
|
|
45
45
|
// and nobody owns deleting it
|
|
46
46
|
try credentialStore.save(oneTimeCode, for: .verificationCode)
|
|
47
|
-
UserDefaults.standard.set(
|
|
47
|
+
UserDefaults.standard.set(cardNumber, forKey: "checkoutCard")
|
|
48
48
|
```
|
|
49
49
|
```swift
|
|
50
50
|
// ✓ transient: held by the flow's model, gone when the flow ends
|
|
51
|
-
@Observable final class
|
|
52
|
-
private var
|
|
51
|
+
@Observable final class CheckoutFormViewModel {
|
|
52
|
+
private var cardNumber: String = "" // never leaves memory
|
|
53
53
|
}
|
|
54
54
|
```
|
|
55
55
|
```swift
|
|
56
56
|
// ✓ persisted, because it must survive an app restart - Keychain, explicit accessibility,
|
|
57
57
|
// no iCloud sync
|
|
58
58
|
try credentialStore.save(
|
|
59
|
-
|
|
59
|
+
sessionToken,
|
|
60
60
|
for: .authToken,
|
|
61
61
|
accessibility: .whenUnlockedThisDeviceOnly
|
|
62
62
|
)
|
|
@@ -129,19 +129,19 @@ Testability is a property of the production code. You cannot add it later by wri
|
|
|
129
129
|
|
|
130
130
|
```swift
|
|
131
131
|
// ✗ untestable by construction - the assertion depends on today's date
|
|
132
|
-
struct
|
|
133
|
-
func
|
|
134
|
-
Date()
|
|
132
|
+
struct ReturnEligibility {
|
|
133
|
+
func canReturn(order: Order) -> Bool {
|
|
134
|
+
Date() < order.deliveredAt.addingTimeInterval(30 * 24 * 3600)
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
```
|
|
138
138
|
```swift
|
|
139
139
|
// ✓ the seam is one parameter wide
|
|
140
|
-
struct
|
|
140
|
+
struct ReturnEligibility {
|
|
141
141
|
let now: () -> Date
|
|
142
142
|
|
|
143
|
-
func
|
|
144
|
-
now()
|
|
143
|
+
func canReturn(order: Order) -> Bool {
|
|
144
|
+
now() < order.deliveredAt.addingTimeInterval(30 * 24 * 3600)
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
```
|
|
@@ -154,21 +154,21 @@ test can decide instead. A type that reaches for it has no seam, and no test dis
|
|
|
154
154
|
```swift
|
|
155
155
|
// ✗ the rule is trapped inside the view model, behind a network call and a singleton
|
|
156
156
|
func submit() async {
|
|
157
|
-
guard Session.shared.isLoggedIn,
|
|
157
|
+
guard Session.shared.isLoggedIn, items.allSatisfy(\.isInStock) else { return }
|
|
158
158
|
...
|
|
159
159
|
}
|
|
160
160
|
```
|
|
161
161
|
```swift
|
|
162
162
|
// ✓ the decision is a value-returning function; the view model orchestrates
|
|
163
|
-
func submitGate(for
|
|
163
|
+
func submitGate(for items: [CartItem], isLoggedIn: Bool) -> SubmitGate {
|
|
164
164
|
guard isLoggedIn else { return .requiresLogin }
|
|
165
|
-
guard
|
|
165
|
+
guard items.allSatisfy(\.isInStock) else { return .outOfStock }
|
|
166
166
|
return .allowed
|
|
167
167
|
}
|
|
168
168
|
```
|
|
169
169
|
**Why:** the second version is one line to test and reads as the business rule it is. The first
|
|
170
|
-
needs a session, a network stub and a view model instance to answer "what happens when
|
|
171
|
-
is
|
|
170
|
+
needs a session, a network stub and a view model instance to answer "what happens when an item
|
|
171
|
+
is out of stock".
|
|
172
172
|
|
|
173
173
|
Also: name test doubles for what they do - stub, spy, fake, mock, **builder** - one kind per file,
|
|
174
174
|
and keep the signature identical to the real type, because a drifted double is the first thing the
|
|
@@ -185,22 +185,22 @@ answer is screen policy rather than entity state** → a named rule namespace.
|
|
|
185
185
|
|
|
186
186
|
```swift
|
|
187
187
|
// ✗ a private computed property on the scene; the next screen needing this re-derives it
|
|
188
|
-
private var showsStrikethrough: Bool { viewModel.
|
|
188
|
+
private var showsStrikethrough: Bool { viewModel.item.priceInfo?.discounted == true }
|
|
189
189
|
```
|
|
190
190
|
```swift
|
|
191
191
|
// ✓ a caseless enum of pure statics in the domain layer, each citing what it enforces
|
|
192
|
-
enum
|
|
193
|
-
/// BR-21: the
|
|
194
|
-
///
|
|
195
|
-
static func shouldRenderStrikethrough(_
|
|
196
|
-
|
|
192
|
+
enum OrderRules {
|
|
193
|
+
/// BR-21: the list price strikes ONLY when `priceInfo.discounted` is true. When it is false the
|
|
194
|
+
/// price fields may still be populated (a list price with no promotion) - do not strike then.
|
|
195
|
+
static func shouldRenderStrikethrough(_ item: OrderItem) -> Bool {
|
|
196
|
+
item.priceInfo?.discounted == true
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
199
|
```
|
|
200
200
|
```swift
|
|
201
201
|
// ✓ and the test repeats the citation token, so one grep reaches spec, code and test
|
|
202
|
-
@Test("BR_21: no strikethrough when the
|
|
203
|
-
func
|
|
202
|
+
@Test("BR_21: no strikethrough when the item is not discounted")
|
|
203
|
+
func test_BR_21_noStrikethrough_whenNotDiscounted() { ... }
|
|
204
204
|
```
|
|
205
205
|
**Why:** the citation is not decoration, it is the rule's own measurement. A namespace whose
|
|
206
206
|
functions cite nothing cannot be checked against anything, and a cited requirement with no test of
|
|
@@ -242,7 +242,7 @@ tangle - that reads worse, and it is a finding in the same way the opposite is
|
|
|
242
242
|
|
|
243
243
|
```swift
|
|
244
244
|
// ✗ a date formatter living on the scene that happened to need it first
|
|
245
|
-
extension
|
|
245
|
+
extension OrderReviewScene {
|
|
246
246
|
func formattedDate(_ raw: String?) -> String { ... } // and again, later, in a mapper
|
|
247
247
|
}
|
|
248
248
|
```
|
|
@@ -261,31 +261,31 @@ typed they get written a second time somewhere else, with a slightly different e
|
|
|
261
261
|
```swift
|
|
262
262
|
// ✗ a component hiding as a computed property: cannot be previewed, cannot be reused,
|
|
263
263
|
// and it reads the whole view model so it never could be
|
|
264
|
-
private var
|
|
264
|
+
private var categoryTabs: some View {
|
|
265
265
|
HStack {
|
|
266
|
-
ForEach(viewModel.
|
|
267
|
-
Button { Task { await viewModel.
|
|
266
|
+
ForEach(viewModel.categories) { category in
|
|
267
|
+
Button { Task { await viewModel.onCategorySelected(category.index) } } label: { ... }
|
|
268
268
|
}
|
|
269
269
|
}
|
|
270
270
|
}
|
|
271
271
|
```
|
|
272
272
|
```swift
|
|
273
|
-
// ✓
|
|
274
|
-
struct
|
|
275
|
-
let
|
|
276
|
-
let
|
|
273
|
+
// ✓ CategoryTabBar.swift - data in, callbacks out, previewable on its own
|
|
274
|
+
struct CategoryTabBar: View {
|
|
275
|
+
let categories: [CatalogCategory]
|
|
276
|
+
let activeCategoryIndex: Int
|
|
277
277
|
let onSelect: (Int) -> Void
|
|
278
278
|
var body: some View { ... }
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
#Preview {
|
|
282
|
-
|
|
282
|
+
CategoryTabBar(categories: [.featured, .sale], activeCategoryIndex: 0, onSelect: { _ in })
|
|
283
283
|
}
|
|
284
284
|
|
|
285
285
|
// ✓ the scene keeps the composition - which component shows, in what order
|
|
286
286
|
@ViewBuilder
|
|
287
287
|
var content: some View {
|
|
288
|
-
if viewModel.loadError { errorRetryView } else {
|
|
288
|
+
if viewModel.loadError { errorRetryView } else { CategoryTabBar(...) }
|
|
289
289
|
}
|
|
290
290
|
```
|
|
291
291
|
**Why:** the canvas is the fastest way to check a visual piece, and it only works when the piece
|
|
@@ -298,22 +298,22 @@ it never gets looked at until the whole flow is run on a device.
|
|
|
298
298
|
// ✗ a response model nested inside another - invisible to a filename search,
|
|
299
299
|
// and moving it later renames every reference
|
|
300
300
|
struct OrderResponseModel {
|
|
301
|
-
struct
|
|
301
|
+
struct OrderItemModel { ... }
|
|
302
302
|
}
|
|
303
303
|
```
|
|
304
304
|
```swift
|
|
305
305
|
// ✓ data types are top level, one per file
|
|
306
306
|
struct OrderResponseModel { let items: [OrderItemModel] } // OrderResponseModel.swift
|
|
307
|
-
struct
|
|
307
|
+
struct OrderItemModel { ... } // OrderItemModel.swift
|
|
308
308
|
|
|
309
309
|
// ✓ still fine - an owned detail with exactly one owner
|
|
310
|
-
@Observable final class
|
|
310
|
+
@Observable final class CatalogViewModel {
|
|
311
311
|
enum ViewState { case loading, loaded, failed }
|
|
312
312
|
}
|
|
313
313
|
|
|
314
314
|
// ✓ also fine - a pure constants namespace; the nesting IS the grouping
|
|
315
315
|
enum AppConstant {
|
|
316
|
-
enum Phone { static let defaultDialCode = "+
|
|
316
|
+
enum Phone { static let defaultDialCode = "+1" }
|
|
317
317
|
enum DeepLink { static let scheme = "myapp" }
|
|
318
318
|
}
|
|
319
319
|
```
|
|
@@ -328,17 +328,17 @@ grouping and buys no discoverability.
|
|
|
328
328
|
// ✗ transport verbs invented by the client - the name says what the code does
|
|
329
329
|
// (which the signature already says), not which service will fire
|
|
330
330
|
func fetchOpenStatus(_ request: CheckOpenStatusRequestModel) async -> Result
|
|
331
|
-
func
|
|
331
|
+
func loadOrderItems(...) async -> Result
|
|
332
332
|
```
|
|
333
333
|
```swift
|
|
334
334
|
// ✓ `send` + the endpoint path, segments in the backend's own order
|
|
335
335
|
func sendCheckOpenStatus(_ request: CheckOpenStatusRequestModel) async -> Result // check-open-status
|
|
336
336
|
func sendOrderItemsSave(...) async -> Result // order/items/save
|
|
337
|
-
func
|
|
337
|
+
func sendSessionExtend() async -> Result // session/extend
|
|
338
338
|
|
|
339
339
|
// ✗ the generated client's method name is not the service name: `get` is the generator's
|
|
340
340
|
// HTTP-verb prefix and it reorders the path the backend chose
|
|
341
|
-
func
|
|
341
|
+
func sendGetCatalogPageInfo() async -> Result // catalog/page-info -> sendCatalogPageInfo
|
|
342
342
|
|
|
343
343
|
// ✓ variants over one service: the single caller is named, the variants sit above it
|
|
344
344
|
func sendGetCountryList() async throws -> CountryLookupResponse // private, the one call
|
|
@@ -365,7 +365,7 @@ struct SummaryMapper: Sendable {
|
|
|
365
365
|
func map(dto: SummaryDto) -> SummaryData {
|
|
366
366
|
SummaryData(
|
|
367
367
|
sessionTimeout: dto.sessionTimeout.map { TimeInterval($0) / 1000.0 },
|
|
368
|
-
variant: dto.info?.status == .error ? .
|
|
368
|
+
variant: dto.info?.status == .error ? .orderError : .standard,
|
|
369
369
|
otpTimeout: dto.timeout ?? 180
|
|
370
370
|
)
|
|
371
371
|
}
|
|
@@ -378,8 +378,8 @@ SummaryData(sessionTimeoutMs: dto.sessionTimeout, isFailure: dto.info?.status ==
|
|
|
378
378
|
|
|
379
379
|
// ✓ the view model decides, in its own business-rules section
|
|
380
380
|
var variant: SummaryVariant {
|
|
381
|
-
if data.isFailure { return
|
|
382
|
-
return data.
|
|
381
|
+
if data.isFailure { return anyPaymentRedirect ? .paymentError : .orderError }
|
|
382
|
+
return data.isMultiShipment ? .splitShipment : .standard
|
|
383
383
|
}
|
|
384
384
|
```
|
|
385
385
|
**Why:** the mapper is the one type with no screen context. A rule buried in it is invisible
|
|
@@ -398,12 +398,12 @@ every call site that reads it.
|
|
|
398
398
|
|
|
399
399
|
```swift
|
|
400
400
|
// ✗ the parameter list is a request model nobody wrote
|
|
401
|
-
func
|
|
401
|
+
func saveOrderItems(orderNumber: String, email: String, items: [CartItem],
|
|
402
402
|
contact: ContactInfo?, acceptsTerms: Bool) async throws -> Bool
|
|
403
403
|
```
|
|
404
404
|
```swift
|
|
405
405
|
// ✓
|
|
406
|
-
public func
|
|
406
|
+
public func saveOrderItems(
|
|
407
407
|
_ request: SaveOrderItemsRequestModel
|
|
408
408
|
) async -> OrderServiceResult<SaveOrderItemsResponseModel> {
|
|
409
409
|
```
|
|
@@ -420,8 +420,8 @@ func checkAccess(identifier: String) async throws -> AccessResponse
|
|
|
420
420
|
```swift
|
|
421
421
|
// ✓ one type enumerating every outcome the caller must handle
|
|
422
422
|
enum AccessOutcome: Equatable, Sendable {
|
|
423
|
-
case dashboard(
|
|
424
|
-
case
|
|
423
|
+
case dashboard(orderNumber: String?) // a success case may name a DESTINATION
|
|
424
|
+
case orderEntrance(orderNumber: String?)
|
|
425
425
|
case serviceError(referenceCode: String?, message: String?)
|
|
426
426
|
case offline
|
|
427
427
|
case timeout
|
|
@@ -451,17 +451,17 @@ shape.
|
|
|
451
451
|
```swift
|
|
452
452
|
// ✗ four properties; `isLoading` with data present and an error set is a state nothing rejects
|
|
453
453
|
var isLoading = false
|
|
454
|
-
var
|
|
454
|
+
var order: Order?
|
|
455
455
|
var errorMessage: String?
|
|
456
456
|
var isOffline = false
|
|
457
457
|
```
|
|
458
458
|
```swift
|
|
459
459
|
// ✓ the payload hangs off the case, and the enum answers questions so the view never destructures
|
|
460
460
|
struct LoadedContent: Hashable {
|
|
461
|
-
let
|
|
462
|
-
/// `nil` when the
|
|
463
|
-
/// renders its
|
|
464
|
-
let
|
|
461
|
+
let order: Order
|
|
462
|
+
/// `nil` when the recommendations request failed but the order loaded - the screen still
|
|
463
|
+
/// renders its items, the recommendation area is simply not drawn.
|
|
464
|
+
let recommendations: RecommendationArea?
|
|
465
465
|
}
|
|
466
466
|
|
|
467
467
|
enum ScreenState: Hashable {
|
|
@@ -91,7 +91,7 @@ if [ -f "$INVENTORY" ]; then
|
|
|
91
91
|
fi
|
|
92
92
|
|
|
93
93
|
# SENSITIVE / TRANSIENT: alternations of the module's own symbol names.
|
|
94
|
-
: "${SENSITIVE:=token|password|passcode|secret|credential|passport|nationalId|identityNumber|
|
|
94
|
+
: "${SENSITIVE:=token|password|passcode|secret|credential|passport|nationalId|identityNumber|orderNumber|reservationCode|ticketNumber|membershipNumber|cardNumber|cvv|dateOfBirth}"
|
|
95
95
|
: "${TRANSIENT:=oneTimeCode|otp|verificationCode|draft}"
|
|
96
96
|
|
|
97
97
|
# SIBLINGS: every other module that lives beside this one - the MOD-01 import guard.
|
|
@@ -198,10 +198,10 @@ sensitive_data_classes:
|
|
|
198
198
|
at_rest: keychain-required
|
|
199
199
|
loggable: never
|
|
200
200
|
- id: booking-reference
|
|
201
|
-
covers: reservation code, ticket number,
|
|
201
|
+
covers: order number, reservation code, ticket number, confirmation barcode payload
|
|
202
202
|
at_rest: keychain-or-protected
|
|
203
203
|
loggable: never
|
|
204
|
-
note: individually low-value, but it authorises access to a
|
|
204
|
+
note: individually low-value, but it authorises access to a customer record
|
|
205
205
|
- id: membership-identity
|
|
206
206
|
covers: loyalty or programme membership number, tier, account identifier
|
|
207
207
|
at_rest: keychain-or-protected
|
|
@@ -338,7 +338,7 @@ rules:
|
|
|
338
338
|
rationale: testability
|
|
339
339
|
check: >
|
|
340
340
|
A `private var x: Bool/String/Int` in a scene that reads the view model and decides
|
|
341
|
-
something - "is the header shown", "which
|
|
341
|
+
something - "is the header shown", "which tab is active", "what does the CTA say" - is a
|
|
342
342
|
business rule in the view layer. It belongs on the view model, in its business-rules
|
|
343
343
|
section, where a unit test can reach it. The scene reads `viewModel.x`.
|
|
344
344
|
Not this rule: building a design-system `Configuration` value. Moving those to the view
|
|
@@ -653,8 +653,8 @@ rules:
|
|
|
653
653
|
Form/validation rules are the classic silent duplication: each one is small enough to
|
|
654
654
|
re-type in ten seconds, so every module does, and the copies then drift. Before adding one,
|
|
655
655
|
grep the shared rule library AND every sibling module for the CONCEPT, not the name - the
|
|
656
|
-
same rule appears as `EmailFormatRule` / `EmailRule`, `
|
|
657
|
-
`
|
|
656
|
+
same rule appears as `EmailFormatRule` / `EmailRule`, `NationalIdRule` / `NationalIdChecksumRule` /
|
|
657
|
+
`IdentityNumberRule`, `OrderNumberRule` / `OrderNumberOrEmailFormatRule` / `<Screen>OrderNumberOrEmailFormatRule`.
|
|
658
658
|
Name-matching alone finds none of those.
|
|
659
659
|
|
|
660
660
|
Placement follows STRUCT-05, with one addition: the error copy is NOT part of the rule.
|
|
@@ -745,10 +745,10 @@ rules:
|
|
|
745
745
|
`send` + the endpoint path, segments in their own order, camel-cased, path parameters
|
|
746
746
|
dropped: `check-open-status` → `sendCheckOpenStatus`, `order/items/save` →
|
|
747
747
|
`sendOrderItemsSave`, `session/extend` → `sendSessionExtend`,
|
|
748
|
-
`lookup/{
|
|
748
|
+
`lookup/{brand}/product` → `sendLookupProduct`.
|
|
749
749
|
The path is the name, not the generated client method. A generator prefixes GET
|
|
750
|
-
endpoints with `get` and appends parameter suffixes (`
|
|
751
|
-
`
|
|
750
|
+
endpoints with `get` and appends parameter suffixes (`getCatalogPageInfo`,
|
|
751
|
+
`getProductListByBrand`) - both are artifacts of the generator, and `get`
|
|
752
752
|
also reorders the segments the backend chose. Copying the generated name silently
|
|
753
753
|
renames the service; copying the path keeps one spelling on both sides of the wire.
|
|
754
754
|
The HTTP verb is never part of the name: the endpoint already implies it, and `send`
|
|
@@ -803,7 +803,7 @@ rules:
|
|
|
803
803
|
A past deadline meaning "no countdown" is a product decision, not a cast.
|
|
804
804
|
- **Choosing a screen state.** Resolving a variant, an enum case, or an error message
|
|
805
805
|
from a combination of flags. Carry the flags; decide in the view model.
|
|
806
|
-
- **A policy default.** `?? 180` seconds, `??
|
|
806
|
+
- **A policy default.** `?? 180` seconds, `?? items.count`. A number nobody can
|
|
807
807
|
derive from the payload is policy and belongs next to the code that lives with it.
|
|
808
808
|
- **Dropping or promoting records.** Filtering a code out of a list, or turning one code
|
|
809
809
|
into a different field, encodes what that code MEANS. That meaning belongs on the
|
|
@@ -824,7 +824,7 @@ rules:
|
|
|
824
824
|
review is that deleting the decision also deletes the data it was computed from: the mapper
|
|
825
825
|
stored `isFailure: Bool` and dropped `info.status`, so no later layer can re-derive it.
|
|
826
826
|
So: first make the entity CARRY the raw inputs the decision reads (`info: Info?`,
|
|
827
|
-
`hasPrevention: Bool`, `
|
|
827
|
+
`hasPrevention: Bool`, `stepCompletions: [Bool]`), then express the decision as a computed
|
|
828
828
|
property. Where that property lives:
|
|
829
829
|
- **On the entity**, under a `// MARK: - Derived` - when more than one screen, or the
|
|
830
830
|
screen AND its mocks, ask the same question. This is also what keeps the mock
|
|
@@ -1332,7 +1332,7 @@ rules:
|
|
|
1332
1332
|
removes it from the store build, and "it is only referenced by the mock path" is not an
|
|
1333
1333
|
answer.
|
|
1334
1334
|
Distinguish by payload, never by name: a `Mock` that returns nothing is a null object with
|
|
1335
|
-
the wrong name (rename it), and a `Noop` that returns three sample
|
|
1335
|
+
the wrong name (rename it), and a `Noop` that returns three sample orders is a double in
|
|
1336
1336
|
the wrong target (move it).
|
|
1337
1337
|
**The measurement:** per module, the count of double-named types under the production source
|
|
1338
1338
|
root, split into carries-payload and returns-empty. The first number is the finding; the
|
|
@@ -21,7 +21,6 @@ date_added: '2026-02-27'
|
|
|
21
21
|
- Clarify goals, constraints, and required inputs.
|
|
22
22
|
- Apply relevant best practices and validate outcomes.
|
|
23
23
|
- Provide actionable steps and verification.
|
|
24
|
-
- If detailed examples are required, open `resources/implementation-playbook.md`.
|
|
25
24
|
|
|
26
25
|
You are an iOS development expert specializing in native iOS app development with comprehensive knowledge of the Apple ecosystem.
|
|
27
26
|
|
|
@@ -52,10 +52,14 @@ becoming a hundred findings.
|
|
|
52
52
|
|
|
53
53
|
## Running it
|
|
54
54
|
|
|
55
|
+
Paths are relative to this skill's own directory (the directory this SKILL.md lives in, wherever
|
|
56
|
+
the skill is installed); set `SKILL_DIR` to it first.
|
|
57
|
+
|
|
55
58
|
```bash
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
--
|
|
59
|
+
SKILL_DIR="<directory containing this SKILL.md>"
|
|
60
|
+
python3 "$SKILL_DIR/scripts/check_structure.py" \
|
|
61
|
+
--rules "$SKILL_DIR/references/rules.yml" \
|
|
62
|
+
--overlay "$SKILL_DIR/modules/<Module>.yml" \
|
|
59
63
|
--root "<path/to/module>"
|
|
60
64
|
```
|
|
61
65
|
|