@leejungkiin/awkit 1.1.0 → 1.1.2

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.
Files changed (119) hide show
  1. package/README.md +3 -3
  2. package/VERSION +1 -1
  3. package/bin/awf.js +1 -1
  4. package/bin/awk.js +237 -26
  5. package/core/AGENTS.md +8 -9
  6. package/core/GEMINI.md +74 -199
  7. package/package.json +3 -2
  8. package/skill-packs/neural-memory/skills/nm-memory-sync/SKILL.md +2 -2
  9. package/skills/CATALOG.md +3 -2
  10. package/skills/README.md +109 -0
  11. package/skills/android-re-analyzer/SKILL.md +238 -0
  12. package/skills/android-re-analyzer/references/api-extraction-patterns.md +119 -0
  13. package/skills/android-re-analyzer/references/call-flow-analysis.md +176 -0
  14. package/skills/android-re-analyzer/references/fernflower-usage.md +115 -0
  15. package/skills/android-re-analyzer/references/jadx-usage.md +116 -0
  16. package/skills/android-re-analyzer/references/setup-guide.md +221 -0
  17. package/skills/android-re-analyzer/scripts/check-deps.sh +129 -0
  18. package/skills/android-re-analyzer/scripts/decompile.sh +375 -0
  19. package/skills/android-re-analyzer/scripts/find-api-calls.sh +118 -0
  20. package/skills/android-re-analyzer/scripts/install-dep.sh +448 -0
  21. package/skills/awf-session-restore/SKILL.md +108 -184
  22. package/skills/beads-manager/SKILL.md +2 -2
  23. package/skills/brainstorm-agent/SKILL.md +47 -2
  24. package/skills/gemini-conductor/SKILL.md +234 -0
  25. package/skills/memory-sync/SKILL.md +29 -1
  26. package/skills/nm-memory-sync/SKILL.md +2 -2
  27. package/skills/orchestrator/SKILL.md +29 -155
  28. package/skills/skills/nm-memory-sync/SKILL.md +2 -2
  29. package/skills/smali-to-kotlin/SKILL.md +1 -1
  30. package/skills/smali-to-swift/SKILL.md +1 -1
  31. package/skills/swiftui-pro/SKILL.md +108 -0
  32. package/skills/swiftui-pro/agents/openai.yaml +10 -0
  33. package/skills/swiftui-pro/assets/swiftui-pro-icon.png +0 -0
  34. package/skills/swiftui-pro/assets/swiftui-pro-icon.svg +29 -0
  35. package/skills/swiftui-pro/references/accessibility.md +13 -0
  36. package/skills/swiftui-pro/references/api.md +39 -0
  37. package/skills/swiftui-pro/references/data.md +43 -0
  38. package/skills/swiftui-pro/references/design.md +31 -0
  39. package/skills/swiftui-pro/references/hygiene.md +9 -0
  40. package/skills/swiftui-pro/references/navigation.md +14 -0
  41. package/skills/swiftui-pro/references/performance.md +46 -0
  42. package/skills/swiftui-pro/references/swift.md +56 -0
  43. package/skills/swiftui-pro/references/views.md +35 -0
  44. package/skills/symphony-enforcer/SKILL.md +362 -0
  45. package/skills/symphony-orchestrator/SKILL.md +301 -0
  46. package/skills/telegram-notify/SKILL.md +57 -0
  47. package/symphony/LICENSE +21 -0
  48. package/symphony/README.md +178 -0
  49. package/symphony/app/api/agents/route.js +152 -0
  50. package/symphony/app/api/events/route.js +22 -0
  51. package/symphony/app/api/knowledge/route.js +253 -0
  52. package/symphony/app/api/locks/route.js +29 -0
  53. package/symphony/app/api/notes/route.js +125 -0
  54. package/symphony/app/api/preflight/route.js +23 -0
  55. package/symphony/app/api/projects/route.js +116 -0
  56. package/symphony/app/api/roles/route.js +134 -0
  57. package/symphony/app/api/skills/route.js +82 -0
  58. package/symphony/app/api/status/route.js +18 -0
  59. package/symphony/app/api/tasks/route.js +157 -0
  60. package/symphony/app/api/workflows/route.js +61 -0
  61. package/symphony/app/api/workspaces/route.js +15 -0
  62. package/symphony/app/globals.css +2605 -0
  63. package/symphony/app/layout.js +20 -0
  64. package/symphony/app/page.js +2122 -0
  65. package/symphony/cli/index.js +1060 -0
  66. package/symphony/core/agent-manager.js +357 -0
  67. package/symphony/core/context-bus.js +100 -0
  68. package/symphony/core/db.js +223 -0
  69. package/symphony/core/file-lock-manager.js +154 -0
  70. package/symphony/core/merge-pipeline.js +234 -0
  71. package/symphony/core/orchestrator.js +236 -0
  72. package/symphony/core/task-manager.js +335 -0
  73. package/symphony/core/workspace-manager.js +168 -0
  74. package/symphony/jsconfig.json +7 -0
  75. package/symphony/lib/core.mjs +1034 -0
  76. package/symphony/mcp/index.js +29 -0
  77. package/symphony/mcp/server.js +110 -0
  78. package/symphony/mcp/tools/context.js +80 -0
  79. package/symphony/mcp/tools/locks.js +99 -0
  80. package/symphony/mcp/tools/status.js +82 -0
  81. package/symphony/mcp/tools/tasks.js +216 -0
  82. package/symphony/mcp/tools/workspace.js +143 -0
  83. package/symphony/next.config.mjs +7 -0
  84. package/symphony/package.json +53 -0
  85. package/symphony/scripts/postinstall.js +49 -0
  86. package/symphony/symphony.config.js +41 -0
  87. package/templates/conductor-tracks.md +38 -0
  88. package/templates/specs/PROJECT.md +50 -0
  89. package/templates/specs/ROADMAP.md +79 -0
  90. package/templates/specs/TECH-SPEC.md +81 -0
  91. package/templates/specs/task-spec-template.xml +65 -0
  92. package/templates/workflow_dual_mode_template.md +5 -5
  93. package/workflows/_uncategorized/AGENTS.md +38 -0
  94. package/workflows/_uncategorized/decompile.md +67 -0
  95. package/workflows/_uncategorized/skill-health.md +7 -7
  96. package/workflows/ads/ads-audit.md +5 -5
  97. package/workflows/ads/ads-optimize.md +10 -10
  98. package/workflows/ads/adsExpert.md +7 -7
  99. package/workflows/conductor.md +97 -0
  100. package/workflows/context/auto-implement.md +4 -4
  101. package/workflows/context/codebase-sync.md +19 -8
  102. package/workflows/context/next.md +27 -27
  103. package/workflows/context/user-intent-analysis-workflow.md +4 -4
  104. package/workflows/expert/codeExpert.md +28 -31
  105. package/workflows/expert/debugExpert.md +11 -11
  106. package/workflows/expert/planExpert.md +21 -36
  107. package/workflows/git/smart-git-ops.md +49 -6
  108. package/workflows/lifecycle/debug.md +7 -7
  109. package/workflows/lifecycle/deploy.md +10 -10
  110. package/workflows/lifecycle/init.md +103 -91
  111. package/workflows/lifecycle/master-code-workflow.md +3 -3
  112. package/workflows/lifecycle/plan.md +19 -21
  113. package/workflows/quality/audit.md +1 -1
  114. package/workflows/quality/project-audit.md +1 -1
  115. package/workflows/roles/vibe-coding-master-workflow.md +2 -2
  116. package/workflows/smart-git-ops.md +146 -0
  117. package/workflows/ui/app-screen-analyzer.md +4 -4
  118. package/workflows/ui/create-feature.md +8 -8
  119. package/workflows/ui/create-spec-architect.md +11 -11
@@ -224,6 +224,34 @@ Template saved to session:
224
224
  }
225
225
  ```
226
226
 
227
+ ### W7: Brainstorm / Analysis Artifact Persist (MỚI)
228
+ **Điều kiện:** Brainstorm-agent hoặc AI tạo brainstorm/analysis artifact
229
+ ```
230
+ Patterns detect:
231
+ - BRIEF.md tạo xong (qua brainstorm-agent)
232
+ - Analysis document tạo (pricing, market, competitor...)
233
+ - Brainstorm document tạo (feature ideas, architecture exploration...)
234
+
235
+ Action (SILENT):
236
+ 1. POST metadata vào Symphony Notes API (type: brainstorm hoặc analysis)
237
+ 2. content = summary ngắn 2-3 dòng ONLY
238
+ 3. filePath = absolute path đến file artifact
239
+ 4. conversationId = conversation ID hiện tại
240
+ 5. projectId = project đang active
241
+
242
+ curl -X POST http://localhost:3100/api/notes -H 'Content-Type: application/json' -d '{
243
+ "projectId": "<project-id>",
244
+ "type": "brainstorm",
245
+ "title": "<artifact-title>",
246
+ "content": "<summary-2-3-lines>",
247
+ "filePath": "<path-to-file>",
248
+ "conversationId": "<conversation-id>",
249
+ "metadata": { "tags": [...], "created_by": "memory-sync" }
250
+ }'
251
+
252
+ ⚠️ Nếu Symphony server offline → skip silently, không block workflow
253
+ ```
254
+
227
255
  ---
228
256
 
229
257
  ## 🔄 MEMORY SYNC PROTOCOL
@@ -304,7 +332,7 @@ NEVER:
304
332
  ```
305
333
  Runs BEFORE: awf-session-restore (cung cấp data)
306
334
  Runs AFTER: awf-auto-save (fallback nếu memory-sync bỏ sót)
307
- Works WITH: beads-manager (link memory entries với Bead IDs)
335
+ Works WITH: symphony-orchestrator (link memory entries với Symphony task IDs)
308
336
  Works WITH: orchestrator (nhận resolved_target → query focused hơn)
309
337
  Enhances: awf-error-translator (thêm historical context)
310
338
  SEPARATE FROM: brainstorm-agent (hoàn toàn độc lập — brainstorm-agent xử lý ý tưởng)
@@ -89,7 +89,7 @@ allowed-tools:
89
89
  **Links:** `SUPERSEDES` → old pattern if exists
90
90
 
91
91
  ### W4: Task Complete → `workflow` type
92
- **Condition:** Task marked done trong Beads
92
+ **Condition:** Task marked done trong Symphony
93
93
  **Capture:** What was done + approach taken
94
94
  **Store:** `nmem_remember(content, type="workflow", priority=5)`
95
95
 
@@ -178,7 +178,7 @@ If `nmem` is not available, falls back to flat-file behavior:
178
178
 
179
179
  ## Integration
180
180
 
181
- - Works alongside `beads-manager` for task lifecycle hooks
181
+ - Works alongside `symphony-orchestrator` for task lifecycle hooks
182
182
  - Reads `.project-identity` for project-scoped memory filtering
183
183
  - Feeds data to `nm-memory-audit` for quality checks
184
184
  - Activated before `orchestrator` dispatches (priority 2.5 in skill chain)
@@ -1,184 +1,58 @@
1
1
  ---
2
2
  name: orchestrator
3
- description: >-
4
- Intelligent dispatcher — analyzes context, injects project brain, then
5
- delegates to the right skill or workflow. Always runs first.
6
- invocation-type: auto
7
- version: 2.1.0
8
- trigger: always
9
- priority: 1
3
+ description: Intelligent dispatcher — analyzes context and delegates to the right skill or workflow
10
4
  ---
11
5
 
12
- # Orchestrator Skill v2.1 — Project-Aware + Self-Evolving
6
+ # Orchestrator Skill
13
7
 
14
- > **Role:** First-layer processor. Chạy trước MỌI skill khác.
15
- > **v2.0:** Project Brain Lookup inject project context trước khi route.
16
- > **v2.1:** Self-Evolution Pattern — tự ghi learnings sau mỗi session.
8
+ ## Purpose
9
+ Route user requests to the correct workflow or skill based on context analysis.
17
10
 
18
- ---
19
-
20
- ## Execution Order (MANDATORY)
11
+ ## Routing Logic
21
12
 
13
+ ### 1. Slash Command Detection
22
14
  ```
23
- Step 1: Project Brain Lookup ← chạy đầu tiên
24
- Step 2: Intent Detection
25
- Step 3: Route to skill/workflow
26
- Step 4: Self-Evolution ← ghi learnings nếu có
15
+ User input starts with `/` Load workflow file directly
16
+ /plan → workflows/lifecycle/plan.md
17
+ /code → workflows/lifecycle/code.md
18
+ /debug → workflows/lifecycle/debug.md
19
+ ...etc (see GEMINI.md § 2)
27
20
  ```
28
21
 
29
- ---
30
-
31
- ## Step 1: Project Brain Lookup (LUÔN CHẠY)
32
-
33
- ### 1.1 — Đọc `.project-identity`
34
-
22
+ ### 2. Intent Detection (No slash command)
35
23
  ```yaml
36
- check: Có file .project-identity trong project dir không?
37
-
38
- IF EXISTS:
39
- read: .project-identity
40
- extract:
41
- - projectName
42
- - stage
43
- - architecture (clean_architecture, mvvm)
44
- - tech stack (swift, react, node, etc.)
45
-
46
- SET: project_context = { name, stage, arch, stack }
47
- ```
48
-
49
- ### 1.2 — Đọc `CODEBASE.md`
50
-
51
- ```yaml
52
- check: Có file CODEBASE.md trong project dir không?
53
-
54
- IF EXISTS:
55
- read: CODEBASE.md
56
- extract:
57
- - layer_map: { layer_name → files[] }
58
- - feature_areas: { feature → directory }
59
- - naming_conventions
60
-
61
- RULES:
62
- → KHÔNG scan raw directory nếu CODEBASE.md tồn tại
63
- → KHÔNG hỏi user về file location — tự suy luận từ codebase_map
64
- ```
65
-
66
- ### 1.3 — Resolve Target từ Request
67
-
68
- ```yaml
69
- resolve_target(user_request, codebase_map):
70
- 1. Layer match: "crash khi login" → AuthenticationViewModel
71
- 2. Feature match: "water tracking" → Features/Water/
72
- 3. Service match: "camera chậm" → CameraViewModel
73
- 4. Fallback: list top 3 candidates từ CODEBASE.md
74
- ```
75
-
76
- ### 1.4 — Brief Confirm Output (LUÔN HIỂN THỊ)
77
-
78
- ```
79
- Format:
80
- "📚 [ProjectName] | [Stage] | [Architecture]
81
- 🗺️ Targeting: [resolved file/layer]"
82
-
83
- Nếu file được nhắc KHÔNG có trong CODEBASE.md:
84
- → Footer: "⚠️ CODEBASE.md có thể outdated — dùng /codebase-sync"
85
- ```
86
-
87
- ---
88
-
89
- ## Step 2: Intent Detection
24
+ code_intent:
25
+ keywords: ["implement", "build", "create", "add", "code", "fix", "viết", "tạo"]
26
+ action: Suggest `/code` or `/codeExpert`
90
27
 
91
- ```yaml
92
28
  debug_intent:
93
- keywords: ["error", "bug", "crash", "fix", "lỗi", "sửa", "fail", "không chạy"]
94
- action: Execute debug flow với target đã resolve từ Step 1
95
-
96
- code_intent:
97
- keywords: ["implement", "build", "create", "add", "code", "viết", "tạo", "thêm"]
98
- action: Execute code flow tại target layer/file đã biết
29
+ keywords: ["error", "bug", "crash", "fix", "lỗi", "sửa", "fail"]
30
+ action: Suggest `/debug` or `/debugExpert`
99
31
 
100
32
  plan_intent:
101
33
  keywords: ["plan", "design", "architect", "how to", "strategy", "thiết kế"]
102
- action: Route to /plan với project context injected
34
+ action: Suggest `/plan` or `/planExpert`
103
35
 
104
36
  context_intent:
105
- keywords: ["remember", "save", "continue", "where was I", "nhớ", "tiếp", "recap"]
106
- action: Route to /recap hoặc /save-brain
37
+ keywords: ["remember", "save", "continue", "where was I", "nhớ", "tiếp"]
38
+ action: Suggest `/recap` or `/save-brain`
107
39
 
108
40
  ads_intent:
109
41
  keywords: ["ads", "campaign", "CPI", "ROAS", "quảng cáo"]
110
- action: Route to /ads-audit hoặc /adsExpert
111
-
112
- image_intent:
113
- trigger: User gửi ảnh chụp màn hình
114
- + debug keywords: Route to visual-debug với CODEBASE context
115
- + design keywords: Route to design-to-ui
116
- + error screenshot: Route to debug flow
42
+ action: Suggest `/ads-audit` or `/adsExpert`
117
43
  ```
118
44
 
119
- ---
120
-
121
- ## Step 3: Routing
122
-
123
- ### With Project Context (khi đã có CODEBASE.md)
124
-
45
+ ### 3. Skill Pack Check
125
46
  ```
126
- Không suggest workflow, THỰC HIỆN LUÔN
127
- Đi thẳng đến file/layer đã resolve
128
- → Không hỏi "file này ở đâu?" — đã biết từ CODEBASE.md
47
+ If user request involves iOS-specific Check if mobile-ios pack enabled
48
+ If not enabled Suggest: "awf enable-pack mobile-ios"
129
49
  ```
130
50
 
131
- ### Slash Command Detection
132
-
133
- ```yaml
134
- /plan → workflows/lifecycle/plan.md
135
- /planExpert → workflows/lifecycle/planExpert.md
136
- /code → workflows/lifecycle/code.md
137
- /codeExpert → workflows/lifecycle/codeExpert.md
138
- /debug → workflows/lifecycle/debug.md
139
- /debugExpert → workflows/lifecycle/debugExpert.md
140
- /codebase-sync → workflows/context/codebase-sync.md
141
- # ...etc (see GEMINI.md)
142
- ```
143
-
144
- ### Fallback
145
-
51
+ ### 4. Fallback
146
52
  ```
147
- No intent match → Ask clarifying question (max 2 lần)
148
- Still unclear → Suggest /help
53
+ No match → Ask clarifying question (max 2 times)
54
+ Still unclear → Suggest `/help`
149
55
  ```
150
56
 
151
- ---
152
-
153
- ## Step 4: Self-Evolution Protocol
154
-
155
- After each session, if a routing decision was suboptimal or a new intent was discovered:
156
-
157
- 1. **Record** the finding in the Learnings section below
158
- 2. **Update** routing rules in Step 2 if a new keyword pattern should be added
159
- 3. **Cross-check** skill catalog (`skills/CATALOG.md`) to ensure new skills are routable
160
-
161
- > This ensures the orchestrator improves its routing accuracy over time.
162
-
163
- ## Learnings
164
-
165
- _Findings from past sessions are recorded here. Add new entries as bullet points._
166
-
167
- - v2.0: Added project brain lookup — significantly reduces unnecessary questions about file locations.
168
- - v2.1: Added self-evolution pattern — skill now self-improves by recording routing insights.
169
- - `invocation-type` field added to help distinguish auto vs manual skills in routing decisions.
170
-
171
- ---
172
-
173
- ## Integration
174
-
175
- ```yaml
176
- runs_before: awf-session-restore, memory-sync, all workflows
177
- provides_to: [project_context, resolved_target, intent]
178
- receives_from: user_request, active_document
179
- ```
180
-
181
- ---
182
-
183
- *orchestrator v2.1 — Project-Aware + Self-Evolving Dispatcher*
184
- *Created by Kien AI*
57
+ ## Auto-Activation
58
+ This skill is always active. It runs as the first layer before any other processing.
@@ -89,7 +89,7 @@ allowed-tools:
89
89
  **Links:** `SUPERSEDES` → old pattern if exists
90
90
 
91
91
  ### W4: Task Complete → `workflow` type
92
- **Condition:** Task marked done trong Beads
92
+ **Condition:** Task marked done trong Symphony
93
93
  **Capture:** What was done + approach taken
94
94
  **Store:** `nmem_remember(content, type="workflow", priority=5)`
95
95
 
@@ -178,7 +178,7 @@ If `nmem` is not available, falls back to flat-file behavior:
178
178
 
179
179
  ## Integration
180
180
 
181
- - Works alongside `beads-manager` for task lifecycle hooks
181
+ - Works alongside `symphony-orchestrator` for task lifecycle hooks
182
182
  - Reads `.project-identity` for project-scoped memory filtering
183
183
  - Feeds data to `nm-memory-audit` for quality checks
184
184
  - Activated before `orchestrator` dispatches (priority 2.5 in skill chain)
@@ -429,7 +429,7 @@ triggers_from:
429
429
  delegates_to:
430
430
  - "/test" — after parity check
431
431
  - "/deploy" — when rebuild is complete
432
- - beads-manager — auto-track progress per step
432
+ - symphony-orchestrator — auto-track progress per step
433
433
 
434
434
  works_with:
435
435
  - memory-sync — saves decisions, patterns, solutions
@@ -663,7 +663,7 @@ triggers_from:
663
663
  delegates_to:
664
664
  - "/test" — after parity check
665
665
  - "/deploy" — when rebuild is complete
666
- - beads-manager — auto-track progress per step
666
+ - symphony-orchestrator — auto-track progress per step
667
667
 
668
668
  works_with:
669
669
  - memory-sync — saves decisions, patterns, solutions
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: swiftui-pro
3
+ description: Comprehensively reviews SwiftUI code for best practices on modern APIs, maintainability, and performance. Use when reading, writing, or reviewing SwiftUI projects.
4
+ license: MIT
5
+ metadata:
6
+ author: Paul Hudson
7
+ version: "1.0"
8
+ ---
9
+
10
+ Review Swift and SwiftUI code for correctness, modern API usage, and adherence to project conventions. Report only genuine problems - do not nitpick or invent issues.
11
+
12
+ Review process:
13
+
14
+ 1. Check for deprecated API using `references/api.md`.
15
+ 1. Check that views, modifiers, and animations have been written optimally using `references/views.md`.
16
+ 1. Validate that data flow is configured correctly using `references/data.md`.
17
+ 1. Ensure navigation is updated and performant using `references/navigation.md`.
18
+ 1. Ensure the code uses designs that are accessible and compliant with Apple’s Human Interface Guidelines using `references/design.md`.
19
+ 1. Validate accessibility compliance including Dynamic Type, VoiceOver, and Reduce Motion using `references/accessibility.md`.
20
+ 1. Ensure the code is able to run efficiently using `references/performance.md`.
21
+ 1. Quick validation of Swift code using `references/swift.md`.
22
+ 1. Final code hygiene check using `references/hygiene.md`.
23
+
24
+ If doing a partial review, load only the relevant reference files.
25
+
26
+
27
+ ## Core Instructions
28
+
29
+ - iOS 26 exists, and is the default deployment target for new apps.
30
+ - Target Swift 6.2 or later, using modern Swift concurrency.
31
+ - As a SwiftUI developer, the user will want to avoid UIKit unless requested.
32
+ - Do not introduce third-party frameworks without asking first.
33
+ - Break different types up into different Swift files rather than placing multiple structs, classes, or enums into a single file.
34
+ - Use a consistent project structure, with folder layout determined by app features.
35
+
36
+
37
+ ## Output Format
38
+
39
+ Organize findings by file. For each issue:
40
+
41
+ 1. State the file and relevant line(s).
42
+ 2. Name the rule being violated (e.g., "Use `foregroundStyle()` instead of `foregroundColor()`").
43
+ 3. Show a brief before/after code fix.
44
+
45
+ Skip files with no issues. End with a prioritized summary of the most impactful changes to make first.
46
+
47
+ Example output:
48
+
49
+ ### ContentView.swift
50
+
51
+ **Line 12: Use `foregroundStyle()` instead of `foregroundColor()`.**
52
+
53
+ ```swift
54
+ // Before
55
+ Text("Hello").foregroundColor(.red)
56
+
57
+ // After
58
+ Text("Hello").foregroundStyle(.red)
59
+ ```
60
+
61
+ **Line 24: Icon-only button is bad for VoiceOver - add a text label.**
62
+
63
+ ```swift
64
+ // Before
65
+ Button(action: addUser) {
66
+ Image(systemName: "plus")
67
+ }
68
+
69
+ // After
70
+ Button("Add User", systemImage: "plus", action: addUser)
71
+ ```
72
+
73
+ **Line 31: Avoid `Binding(get:set:)` in view body - use `@State` with `onChange()` instead.**
74
+
75
+ ```swift
76
+ // Before
77
+ TextField("Username", text: Binding(
78
+ get: { model.username },
79
+ set: { model.username = $0; model.save() }
80
+ ))
81
+
82
+ // After
83
+ TextField("Username", text: $model.username)
84
+ .onChange(of: model.username) {
85
+ model.save()
86
+ }
87
+ ```
88
+
89
+ ### Summary
90
+
91
+ 1. **Accessibility (high):** The add button on line 24 is invisible to VoiceOver.
92
+ 2. **Deprecated API (medium):** `foregroundColor()` on line 12 should be `foregroundStyle()`.
93
+ 3. **Data flow (medium):** The manual binding on line 31 is fragile and harder to maintain.
94
+
95
+ End of example.
96
+
97
+
98
+ ## References
99
+
100
+ - `references/accessibility.md` - Dynamic Type, VoiceOver, Reduce Motion, and other accessibility requirements.
101
+ - `references/api.md` - updating code for modern API, and the deprecated code it replaces.
102
+ - `references/design.md` - guidance for building accessible apps that meet Apple’s Human Interface Guidelines.
103
+ - `references/hygiene.md` - making code compile cleanly and be maintainable in the long term.
104
+ - `references/navigation.md` - navigation using `NavigationStack`/`NavigationSplitView`, plus alerts, confirmation dialogs, and sheets.
105
+ - `references/performance.md` - optimizing SwiftUI code for maximum performance.
106
+ - `references/data.md` - data flow, shared state, and property wrappers.
107
+ - `references/swift.md` - tips on writing modern Swift code, including using Swift Concurrency effectively.
108
+ - `references/views.md` - view structure, composition, and animation.
@@ -0,0 +1,10 @@
1
+ interface:
2
+ display_name: "SwiftUI Pro"
3
+ short_description: "Reviews SwiftUI code for modern best practices."
4
+ icon_small: "./assets/swiftui-pro-icon.svg"
5
+ icon_large: "./assets/swiftui-pro-icon.png"
6
+ brand_color: "#006AFD"
7
+ default_prompt: "Use $swiftui-pro to review my project."
8
+
9
+ policy:
10
+ allow_implicit_invocation: true
@@ -0,0 +1,29 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="227.72" height="227.72" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 227.72 227.72">
3
+ <defs>
4
+ <style>
5
+ .st0 {
6
+ fill: none;
7
+ stroke: url(#linear-gradient1);
8
+ stroke-miterlimit: 10;
9
+ stroke-width: 6px;
10
+ }
11
+
12
+ .st1 {
13
+ fill: url(#linear-gradient);
14
+ fill-rule: evenodd;
15
+ }
16
+ </style>
17
+ <linearGradient id="linear-gradient" x1="58.405" y1="206.955" x2="178.785" y2="86.575" gradientTransform="translate(0 260) scale(1 -1)" gradientUnits="userSpaceOnUse">
18
+ <stop offset="0" stop-color="#00d9ff"/>
19
+ <stop offset="1" stop-color="#006efd"/>
20
+ </linearGradient>
21
+ <linearGradient id="linear-gradient1" x1="33.349" y1="218.651" x2="194.371" y2="57.629" gradientTransform="translate(0 252) scale(1 -1)" gradientUnits="userSpaceOnUse">
22
+ <stop offset="0" stop-color="#00eeaf"/>
23
+ <stop offset="0" stop-color="#00d8ff"/>
24
+ <stop offset="1" stop-color="#006ffd"/>
25
+ </linearGradient>
26
+ </defs>
27
+ <path class="st1" d="M165.43,131.08c3.87-8.17,16.03-46.62-38.6-85.38,7.61,7.03,40.19,39.2,26.05,75.5-34.2-25.27-87.91-66.75-87.91-66.75,0,0,63.69,60.57,83.58,79.15,19.9,18.59,26.97,27.71,26.47,43.59,0,.01,14.58-23.23-9.59-46.11ZM130.89,145.79c-39.35,18.56-78.42-20.82-78.42-20.82,0,0,21.12,26.7,45.19,35.06,33.72,11.71,54.61-9.64,54.61-9.64L52.42,59.03s56.43,62.62,78.47,86.76Z"/>
28
+ <circle class="st0" cx="113.86" cy="113.86" r="110.86"/>
29
+ </svg>
@@ -0,0 +1,13 @@
1
+ # Accessibility
2
+
3
+ - Respect the user’s accessibility settings for fonts, colors, animations, and more.
4
+ - Do not force specific font sizes. Prefer Dynamic Type (`.font(.body)`, `.font(.headline)`, etc.).
5
+ - If you *need* a custom font size, use `@ScaledMetric` when targeting iOS 18 and earlier. When targeting iOS 26 or later, `.font(.body.scaled(by:))` is also available to get font size adjustment.
6
+ - Flag instances where images have unclear or unhelpful VoiceOver readings, e.g. `Image(.newBanner2026)`. If they are decorative, suggest using `Image(decorative:)` or `accessibilityHidden()`, otherwise attach an `accessibilityLabel()`.
7
+ - If the user has “Reduce Motion” enabled, replace large, motion-based animations with opacity instead.
8
+ - If buttons have complex or frequently changing labels, recommend using `accessibilityInputLabels()` to provide better Voice Control commands. For example, if a button had a live-updating share price for Apple such as “AAPL $271.68”, adding an input label for “Apple” would be a big improvement.
9
+ - Buttons with image labels must always include text, even if the text is invisible: `Button("Label", systemImage: "plus", action: myAction)`. Flag icon-only buttons that lack a text label as being bad for VoiceOver.
10
+ - If color is an important differentiator in the user interface, make sure to respect the environment’s `.accessibilityDifferentiateWithoutColor` setting by showing some kind of variation beyond just color – icons, patterns, strokes, etc.
11
+ - The same is true of `Menu`: using `Menu("Options", systemImage: "ellipsis.circle") { }` is much better than just using an image.
12
+ - Never use `onTapGesture()` unless you specifically need tap location or tap count. All other tappable elements should be a `Button`.
13
+ - If `onTapGesture()` must be used, make sure to add `.accessibilityAddTraits(.isButton)` or similar so it can be read by VoiceOver correctly.
@@ -0,0 +1,39 @@
1
+ # Using modern SwiftUI API
2
+
3
+ - Always use `foregroundStyle()` instead of `foregroundColor()`.
4
+ - Always use `clipShape(.rect(cornerRadius:))` instead of `cornerRadius()`.
5
+ - Always use the `Tab` API instead of `tabItem()`.
6
+ - Never use the `onChange()` modifier in its 1-parameter variant; either use the variant that accepts two parameters or accepts none.
7
+ - Do not use `GeometryReader` if a newer alternative works: `containerRelativeFrame()`, `visualEffect()`, or the `Layout` protocol. Flag `GeometryReader` usage and suggest the modern alternative.
8
+ - When designing haptic effects, prefer using `sensoryFeedback()` over older UIKit APIs such as `UIImpactFeedbackGenerator`.
9
+ - Use the `@Entry` macro to define custom `EnvironmentValues`, `FocusValues`, `Transaction`, and `ContainerValues` keys. This replaces the legacy pattern of manually creating a type conforming to (for example) `EnvironmentKey` with a `defaultValue`, then extending `EnvironmentValues` with a computed property.
10
+ - Strongly prefer `overlay(alignment:content:)` over the deprecated `overlay(_:alignment:)`. For example, use `.overlay { Text("Hello, world!") }` rather than `.overlay(Text("Hello, world!"))`.
11
+ - Never use `.navigationBarLeading` and `.navigationBarTrailing` for toolbar item placement; they are deprecated. The correct, modern placements are `.topBarLeading` and `.topBarTrailing`.
12
+ - Prefer to rely on automatic grammar agreement when dealing with English, French, German, Portuguese, Spanish, and Italian. For example, use `Text("^[\(people) person](inflect: true)")` to show a number of people.
13
+ - You can fill and stroke a shape with two chained modifiers; you do *not* need an overlay for the stroke. The overlay was required previously, but this is fixed in iOS 17 and later.
14
+ - When referencing images from an asset catalog, prefer the generated symbol asset API when the project is configured to use them: `Image(.avatar)` rather than `Image("avatar")`.
15
+ - When targeting iOS 26 and later, SwiftUI has a native `WebView` view type that replaces almost all uses of hand-wrapped `WKWebView` inside `UIViewRepresentable`. To use it, make sure to include `import WebKit`.
16
+ - `ForEach` over an `enumerated()` sequence should not convert to an array first. Use `ForEach(items.enumerated(), id: \.element.id)` directly.
17
+ - When hiding scroll indicators, use `.scrollIndicators(.hidden)` rather than `showsIndicators: false` in the initializer.
18
+ - Never use `Text` concatenation with `+`.
19
+
20
+ For example, the usage of `+` here is bad and deprecated:
21
+
22
+ ```swift
23
+ Text("Hello").foregroundStyle(.red)
24
+ +
25
+ Text("World").foregroundStyle(.blue)
26
+ ```
27
+
28
+ Instead, use text interpolation like this:
29
+
30
+ ```swift
31
+ let red = Text("Hello").foregroundStyle(.red)
32
+ let blue = Text("World").foregroundStyle(.blue)
33
+ Text("\(red)\(blue)")
34
+ ```
35
+
36
+
37
+ ## Using ObservableObject
38
+
39
+ If using `ObservableObject` is absolutely required – for example if you are trying to create a debouncer using a Combine publisher – you should always make sure `import Combine` is added. This was previously provided through SwiftUI, but that is no longer the case.
@@ -0,0 +1,43 @@
1
+ # Data flow, shared state, and property wrappers
2
+
3
+ It is important that SwiftUI body code and logic code be kept separate in order to make code easier to read, write, and maintain. That usually means placing code into methods rather than inline in the `body` property, but often also means carving functionality out into separate `@Observable` classes.
4
+
5
+ These rules help ensure code is efficient and works well in the long term.
6
+
7
+
8
+ ## Shared state
9
+
10
+ - `@Observable` classes must be marked `@MainActor` unless the project has Main Actor default actor isolation. Flag any `@Observable` class missing this annotation.
11
+ - All shared data should use `@Observable` classes with `@State` (for ownership) and `@Bindable` / `@Environment` (for passing).
12
+ - Strongly prefer not to use `ObservableObject`, `@Published`, `@StateObject`, `@ObservedObject`, or `@EnvironmentObject` unless they are unavoidable, or if they exist in legacy/integration contexts when changing architecture would be complicated.
13
+
14
+
15
+ ## Local state
16
+
17
+ - `@State` should be marked `private` and only owned by the view that created it.
18
+ - If a view stores a class instance that contains expensive-to-recompute data, e.g. `CIContext`, it can be stored using `@State` even though it is not an observable object. This effectively uses `@State` as a cache – storing something persistently, but not doing any change tracking on it since it's not an observable object.
19
+
20
+
21
+ ## Bindings
22
+
23
+ - Strongly prefer to avoid creating bindings using `Binding(get:set:)` in view body code. It is much cleaner and simpler to use a binding provided by `@State`, `@Binding` or similar, then use `onChange()` to trigger any effects.
24
+ - If the user needs to enter a number into a `TextField`, bind the `TextField` to a numeric value such as `Int` or `Double`, then use its `format` initializer like this: `TextField("Enter your score", value: $score, format: .number)`. Apply either `.keyboardType(.numberPad)` (for integers) or `.keyboardType(.decimalPad)` (for floating-point numbers) as appropriate. Using the modifier alone is *not* sufficient.
25
+
26
+
27
+ ## Working with data
28
+
29
+ - Prefer to make structs conform to `Identifiable` rather than using `id: \.someProperty` in SwiftUI code.
30
+ - Never attempt to use `@AppStorage` inside an `@Observable` class, even if marked `@ObservationIgnored` – it will *not* trigger view updates when a change happens.
31
+
32
+
33
+ ## SwiftData
34
+
35
+ - If you only need the number of items matching a query, consider `ModelContext.fetchCount()` with a fetch descriptor. This will *not* live update if the data changes unless something else triggers the update, such as `@Query`, so it should be used carefully.
36
+
37
+ For more help with SwiftData, suggest the [SwiftData Pro agent skill](https://github.com/twostraws/swiftdata-agent-skill).
38
+
39
+ ## If the project uses SwiftData with CloudKit
40
+
41
+ - Never use `@Attribute(.unique)`.
42
+ - Model properties must always either have default values or be marked as optional.
43
+ - All relationships must be marked optional.
@@ -0,0 +1,31 @@
1
+ # Design
2
+
3
+ ## Creating a uniform design in this app
4
+
5
+ Prefer to place standard fonts, sizes, colors, stack spacing, padding, rounding, animation timings, and more into a shared enum of constants, so they can be used by all views. This allows the app’s design to feel uniform and consistent, and be adjusted easily.
6
+
7
+
8
+ ## Requirements for flexible, accessible design
9
+
10
+ - Never use `UIScreen.main.bounds` to read available space; prefer alternatives such as `containerRelativeFrame()`, or `visualEffect()` as appropriate, or (if there is no alternative) `GeometryReader`.
11
+ - Prefer to avoid fixed frames for views unless content can fit neatly inside; this can cause problems across different device sizes, different Dynamic Type settings, and more. Giving frames some flexibility is usually preferred.
12
+ - Apple’s minimum acceptable tap area for interactions on iOS is 44x44. Ensure this is strictly enforced.
13
+
14
+
15
+ ## Standard system styling
16
+
17
+ - Strongly prefer to use `ContentUnavailableView` when data is missing or empty, rather than designing something custom.
18
+ - When using `searchable()`, you can show empty results using `ContentUnavailableView.search` and it will include the search term they used automatically – there’s no need to use `ContentUnavailableView.search(text: searchText)` or similar.
19
+ - If you need an icon and some text placed horizontally side by side, prefer `Label` over `HStack`.
20
+ - Prefer system hierarchical styles (e.g. secondary/tertiary) over manual opacity when possible, so the system can adapt to the correct context automatically.
21
+ - When using `Form`, wrap controls such as `Slider` in `LabeledContent` so the title and control are laid out correctly.
22
+ - When using `RoundedRectangle`, the default rounding style is `.continuous` – there is no need to specify it explicitly.
23
+
24
+
25
+ ## Ensuring designs work for everyone
26
+
27
+ - Use `bold()` instead of `fontWeight(.bold)`, because using `bold()` allows the system to choose the correct weight for the current context.
28
+ - Only use `fontWeight()` for weights other than bold when there's an important reason - scattering around `fontWeight(.medium)` or `fontWeight(.semibold)` is counterproductive.
29
+ - Avoid hard-coded values for padding and stack spacing unless specifically requested.
30
+ - Avoid UIKit colors (`UIColor`) in SwiftUI code; use SwiftUI `Color` or asset catalog colors.
31
+ - The font size `.caption2` is extremely small, and is generally best avoided. Even the font size `.caption` is on the small side, and should be used carefully.
@@ -0,0 +1,9 @@
1
+ # Hygiene
2
+
3
+ - If the project requires secrets such as API keys, never include them in the repository.
4
+ - Code comments and documentation comments should be present where the logic isn't self-evident.
5
+ - Unit tests should exist for core application logic. UI tests only where unit tests are not possible.
6
+ - `@AppStorage` must never be used to store usernames, passwords, or other sensitive data. Use the keychain for that.
7
+ - If SwiftLint is configured, it should return no warnings or errors.
8
+ - If the project uses Localizable.xcstrings, prefer to add user-facing strings using symbol keys (e.g. “helloWorld”) in the string catalog with `extractionState` set to "manual", accessing them via generated symbols such as `Text(.helloWorld)`. Offer to translate new keys into all languages supported by the project.
9
+ - If the Xcode MCP is configured, prefer its tools over generic alternatives. For example, `RenderPreview` is able to capture images of rendered SwiftUI previews for examination, and `DocumentationSearch` can search Apple’s documentation for latest usage instructions.
@@ -0,0 +1,14 @@
1
+ # Navigation and presentation
2
+
3
+ - Use `NavigationStack` or `NavigationSplitView` as appropriate; flag all use of the deprecated `NavigationView`.
4
+ - Strongly prefer to use `navigationDestination(for:)` to specify destinations; flag all use of the old `NavigationLink(destination:)` pattern where it should be replaced.
5
+ - Never mix `navigationDestination(for:)` and `NavigationLink(destination:)` in the same navigation hierarchy; it causes significant problems.
6
+ - `navigationDestination(for:)` must be registered once per data type; flag duplicates.
7
+
8
+
9
+ ## Alerts, confirmation dialogs, and sheets
10
+
11
+ - Always attach `confirmationDialog()` to the user interface that triggers the dialog. This allows Liquid Glass animations to move from the correct source.
12
+ - If an alert has only a single “OK” button that does nothing but dismiss the alert, it can be omitted entirely: `.alert("Dismiss Me", isPresented: $isShowingAlert) { }`.
13
+ - If a sheet is designed to present an optional piece of data, prefer `sheet(item:)` over `sheet(isPresented:)` so the optional is safely unwrapped.
14
+ - When using `sheet(item:)` with a view that accepts the item as its only initializer parameter, prefer `sheet(item: $someItem, content: SomeView.init)` over `sheet(item: $someItem) { someItem in SomeView(item: someItem) }`.