@kata-sh/cli 0.1.0 → 0.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.
- package/LICENSE +21 -0
- package/README.md +156 -0
- package/dist/app-paths.d.ts +4 -0
- package/dist/app-paths.js +6 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +56 -0
- package/dist/loader.d.ts +2 -0
- package/dist/loader.js +95 -0
- package/dist/resource-loader.d.ts +18 -0
- package/dist/resource-loader.js +50 -0
- package/dist/wizard.d.ts +15 -0
- package/dist/wizard.js +159 -0
- package/package.json +50 -21
- package/pkg/dist/modes/interactive/theme/dark.json +85 -0
- package/pkg/dist/modes/interactive/theme/light.json +84 -0
- package/pkg/dist/modes/interactive/theme/theme-schema.json +335 -0
- package/pkg/dist/modes/interactive/theme/theme.d.ts +78 -0
- package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -0
- package/pkg/dist/modes/interactive/theme/theme.js +949 -0
- package/pkg/dist/modes/interactive/theme/theme.js.map +1 -0
- package/pkg/package.json +8 -0
- package/scripts/postinstall.js +45 -0
- package/src/resources/AGENTS.md +108 -0
- package/src/resources/KATA-WORKFLOW.md +661 -0
- package/src/resources/agents/researcher.md +29 -0
- package/src/resources/agents/scout.md +56 -0
- package/src/resources/agents/worker.md +31 -0
- package/src/resources/extensions/ask-user-questions.ts +200 -0
- package/src/resources/extensions/bg-shell/index.ts +2758 -0
- package/src/resources/extensions/browser-tools/BROWSER-TOOLS-V2-PROPOSAL.md +1277 -0
- package/src/resources/extensions/browser-tools/core.js +1057 -0
- package/src/resources/extensions/browser-tools/index.ts +4916 -0
- package/src/resources/extensions/browser-tools/package.json +20 -0
- package/src/resources/extensions/context7/index.ts +428 -0
- package/src/resources/extensions/context7/package.json +11 -0
- package/src/resources/extensions/get-secrets-from-user.ts +352 -0
- package/src/resources/extensions/github/formatters.ts +207 -0
- package/src/resources/extensions/github/gh-api.ts +537 -0
- package/src/resources/extensions/github/index.ts +778 -0
- package/src/resources/extensions/kata/activity-log.ts +88 -0
- package/src/resources/extensions/kata/auto.ts +2786 -0
- package/src/resources/extensions/kata/commands.ts +355 -0
- package/src/resources/extensions/kata/crash-recovery.ts +85 -0
- package/src/resources/extensions/kata/dashboard-overlay.ts +516 -0
- package/src/resources/extensions/kata/docs/preferences-reference.md +103 -0
- package/src/resources/extensions/kata/doctor.ts +683 -0
- package/src/resources/extensions/kata/files.ts +730 -0
- package/src/resources/extensions/kata/gitignore.ts +165 -0
- package/src/resources/extensions/kata/guided-flow.ts +976 -0
- package/src/resources/extensions/kata/index.ts +556 -0
- package/src/resources/extensions/kata/metrics.ts +397 -0
- package/src/resources/extensions/kata/observability-validator.ts +408 -0
- package/src/resources/extensions/kata/package.json +11 -0
- package/src/resources/extensions/kata/paths.ts +346 -0
- package/src/resources/extensions/kata/preferences.ts +695 -0
- package/src/resources/extensions/kata/prompt-loader.ts +50 -0
- package/src/resources/extensions/kata/prompts/complete-milestone.md +25 -0
- package/src/resources/extensions/kata/prompts/complete-slice.md +27 -0
- package/src/resources/extensions/kata/prompts/discuss.md +151 -0
- package/src/resources/extensions/kata/prompts/doctor-heal.md +29 -0
- package/src/resources/extensions/kata/prompts/execute-task.md +64 -0
- package/src/resources/extensions/kata/prompts/guided-complete-slice.md +1 -0
- package/src/resources/extensions/kata/prompts/guided-discuss-milestone.md +3 -0
- package/src/resources/extensions/kata/prompts/guided-discuss-slice.md +59 -0
- package/src/resources/extensions/kata/prompts/guided-execute-task.md +1 -0
- package/src/resources/extensions/kata/prompts/guided-plan-milestone.md +23 -0
- package/src/resources/extensions/kata/prompts/guided-plan-slice.md +1 -0
- package/src/resources/extensions/kata/prompts/guided-research-slice.md +11 -0
- package/src/resources/extensions/kata/prompts/guided-resume-task.md +1 -0
- package/src/resources/extensions/kata/prompts/plan-milestone.md +47 -0
- package/src/resources/extensions/kata/prompts/plan-slice.md +63 -0
- package/src/resources/extensions/kata/prompts/queue.md +85 -0
- package/src/resources/extensions/kata/prompts/reassess-roadmap.md +48 -0
- package/src/resources/extensions/kata/prompts/replan-slice.md +39 -0
- package/src/resources/extensions/kata/prompts/research-milestone.md +37 -0
- package/src/resources/extensions/kata/prompts/research-slice.md +28 -0
- package/src/resources/extensions/kata/prompts/run-uat.md +109 -0
- package/src/resources/extensions/kata/prompts/system.md +341 -0
- package/src/resources/extensions/kata/session-forensics.ts +550 -0
- package/src/resources/extensions/kata/skill-discovery.ts +137 -0
- package/src/resources/extensions/kata/state.ts +509 -0
- package/src/resources/extensions/kata/templates/context.md +76 -0
- package/src/resources/extensions/kata/templates/decisions.md +8 -0
- package/src/resources/extensions/kata/templates/milestone-summary.md +73 -0
- package/src/resources/extensions/kata/templates/plan.md +133 -0
- package/src/resources/extensions/kata/templates/preferences.md +15 -0
- package/src/resources/extensions/kata/templates/project.md +31 -0
- package/src/resources/extensions/kata/templates/reassessment.md +28 -0
- package/src/resources/extensions/kata/templates/requirements.md +81 -0
- package/src/resources/extensions/kata/templates/research.md +46 -0
- package/src/resources/extensions/kata/templates/roadmap.md +118 -0
- package/src/resources/extensions/kata/templates/slice-context.md +58 -0
- package/src/resources/extensions/kata/templates/slice-summary.md +99 -0
- package/src/resources/extensions/kata/templates/state.md +19 -0
- package/src/resources/extensions/kata/templates/task-plan.md +52 -0
- package/src/resources/extensions/kata/templates/task-summary.md +57 -0
- package/src/resources/extensions/kata/templates/uat.md +54 -0
- package/src/resources/extensions/kata/tests/activity-log-prune.test.ts +327 -0
- package/src/resources/extensions/kata/tests/auto-preflight.test.ts +97 -0
- package/src/resources/extensions/kata/tests/auto-supervisor.test.mjs +53 -0
- package/src/resources/extensions/kata/tests/complete-milestone.test.ts +317 -0
- package/src/resources/extensions/kata/tests/cost-projection.test.ts +160 -0
- package/src/resources/extensions/kata/tests/derive-state-deps.test.ts +477 -0
- package/src/resources/extensions/kata/tests/derive-state.test.ts +1013 -0
- package/src/resources/extensions/kata/tests/doctor.test.ts +718 -0
- package/src/resources/extensions/kata/tests/idle-recovery.test.ts +490 -0
- package/src/resources/extensions/kata/tests/metrics-io.test.ts +254 -0
- package/src/resources/extensions/kata/tests/metrics.test.ts +217 -0
- package/src/resources/extensions/kata/tests/must-have-parser.test.ts +309 -0
- package/src/resources/extensions/kata/tests/parsers.test.ts +1257 -0
- package/src/resources/extensions/kata/tests/plan-milestone.test.ts +185 -0
- package/src/resources/extensions/kata/tests/plan-quality-validator.test.ts +386 -0
- package/src/resources/extensions/kata/tests/reassess-prompt.test.ts +208 -0
- package/src/resources/extensions/kata/tests/replan-slice.test.ts +686 -0
- package/src/resources/extensions/kata/tests/requirements.test.ts +151 -0
- package/src/resources/extensions/kata/tests/resolve-ts-hooks.mjs +17 -0
- package/src/resources/extensions/kata/tests/resolve-ts.mjs +11 -0
- package/src/resources/extensions/kata/tests/run-uat.test.ts +383 -0
- package/src/resources/extensions/kata/tests/unit-runtime.test.ts +388 -0
- package/src/resources/extensions/kata/tests/workspace-index.test.ts +118 -0
- package/src/resources/extensions/kata/tests/worktree.test.ts +222 -0
- package/src/resources/extensions/kata/types.ts +159 -0
- package/src/resources/extensions/kata/unit-runtime.ts +163 -0
- package/src/resources/extensions/kata/workspace-index.ts +203 -0
- package/src/resources/extensions/kata/worktree.ts +182 -0
- package/src/resources/extensions/mac-tools/index.ts +852 -0
- package/src/resources/extensions/mac-tools/swift-cli/Package.swift +22 -0
- package/src/resources/extensions/mac-tools/swift-cli/Sources/main.swift +1318 -0
- package/src/resources/extensions/search-the-web/cache.ts +78 -0
- package/src/resources/extensions/search-the-web/format.ts +258 -0
- package/src/resources/extensions/search-the-web/http.ts +238 -0
- package/src/resources/extensions/search-the-web/index.ts +68 -0
- package/src/resources/extensions/search-the-web/tool-fetch-page.ts +519 -0
- package/src/resources/extensions/search-the-web/tool-llm-context.ts +404 -0
- package/src/resources/extensions/search-the-web/tool-search.ts +503 -0
- package/src/resources/extensions/search-the-web/url-utils.ts +91 -0
- package/src/resources/extensions/shared/confirm-ui.ts +126 -0
- package/src/resources/extensions/shared/interview-ui.ts +822 -0
- package/src/resources/extensions/shared/next-action-ui.ts +235 -0
- package/src/resources/extensions/shared/progress-widget.ts +282 -0
- package/src/resources/extensions/shared/thinking-widget.ts +107 -0
- package/src/resources/extensions/shared/ui.ts +400 -0
- package/src/resources/extensions/shared/wizard-ui.ts +551 -0
- package/src/resources/extensions/slash-commands/audit.ts +92 -0
- package/src/resources/extensions/slash-commands/create-extension.ts +375 -0
- package/src/resources/extensions/slash-commands/create-slash-command.ts +280 -0
- package/src/resources/extensions/slash-commands/index.ts +12 -0
- package/src/resources/extensions/slash-commands/kata-run.ts +34 -0
- package/src/resources/extensions/subagent/agents.ts +126 -0
- package/src/resources/extensions/subagent/index.ts +1293 -0
- package/src/resources/skills/debug-like-expert/SKILL.md +231 -0
- package/src/resources/skills/debug-like-expert/references/debugging-mindset.md +253 -0
- package/src/resources/skills/debug-like-expert/references/hypothesis-testing.md +373 -0
- package/src/resources/skills/debug-like-expert/references/investigation-techniques.md +337 -0
- package/src/resources/skills/debug-like-expert/references/verification-patterns.md +425 -0
- package/src/resources/skills/debug-like-expert/references/when-to-research.md +361 -0
- package/src/resources/skills/frontend-design/SKILL.md +45 -0
- package/src/resources/skills/swiftui/SKILL.md +208 -0
- package/src/resources/skills/swiftui/references/animations.md +921 -0
- package/src/resources/skills/swiftui/references/architecture.md +1561 -0
- package/src/resources/skills/swiftui/references/layout-system.md +1186 -0
- package/src/resources/skills/swiftui/references/navigation.md +1492 -0
- package/src/resources/skills/swiftui/references/networking-async.md +214 -0
- package/src/resources/skills/swiftui/references/performance.md +1706 -0
- package/src/resources/skills/swiftui/references/platform-integration.md +204 -0
- package/src/resources/skills/swiftui/references/state-management.md +1443 -0
- package/src/resources/skills/swiftui/references/swiftdata.md +297 -0
- package/src/resources/skills/swiftui/references/testing-debugging.md +247 -0
- package/src/resources/skills/swiftui/references/uikit-appkit-interop.md +218 -0
- package/src/resources/skills/swiftui/workflows/add-feature.md +191 -0
- package/src/resources/skills/swiftui/workflows/build-new-app.md +311 -0
- package/src/resources/skills/swiftui/workflows/debug-swiftui.md +192 -0
- package/src/resources/skills/swiftui/workflows/optimize-performance.md +197 -0
- package/src/resources/skills/swiftui/workflows/ship-app.md +203 -0
- package/src/resources/skills/swiftui/workflows/write-tests.md +235 -0
- package/dist/commands/task.d.ts +0 -9
- package/dist/commands/task.d.ts.map +0 -1
- package/dist/commands/task.js +0 -129
- package/dist/commands/task.js.map +0 -1
- package/dist/commands/task.test.d.ts +0 -2
- package/dist/commands/task.test.d.ts.map +0 -1
- package/dist/commands/task.test.js +0 -169
- package/dist/commands/task.test.js.map +0 -1
- package/dist/e2e/task-e2e.test.d.ts +0 -2
- package/dist/e2e/task-e2e.test.d.ts.map +0 -1
- package/dist/e2e/task-e2e.test.js +0 -173
- package/dist/e2e/task-e2e.test.js.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -93
- package/dist/index.js.map +0 -1
- package/dist/slug.d.ts +0 -2
- package/dist/slug.d.ts.map +0 -1
- package/dist/slug.js +0 -12
- package/dist/slug.js.map +0 -1
- package/dist/slug.test.d.ts +0 -2
- package/dist/slug.test.d.ts.map +0 -1
- package/dist/slug.test.js +0 -32
- package/dist/slug.test.js.map +0 -1
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
<required_reading>
|
|
2
|
+
**Read these reference files NOW before starting:**
|
|
3
|
+
1. `../macos-apps/references/cli-observability.md` - Log streaming, crash analysis, LLDB, memory debugging
|
|
4
|
+
2. `references/testing-debugging.md` - SwiftUI-specific debugging techniques
|
|
5
|
+
3. `references/state-management.md` - State management issues are #1 bug source
|
|
6
|
+
</required_reading>
|
|
7
|
+
|
|
8
|
+
<process>
|
|
9
|
+
## Step 1: Reproduce the Bug Consistently
|
|
10
|
+
|
|
11
|
+
**Isolate the issue:**
|
|
12
|
+
- Create minimal reproducible example
|
|
13
|
+
- Remove unrelated views and logic
|
|
14
|
+
- Test in both preview and simulator/device
|
|
15
|
+
|
|
16
|
+
**Document:**
|
|
17
|
+
- What action triggers it?
|
|
18
|
+
- Every time or intermittent?
|
|
19
|
+
- Which platforms/OS versions?
|
|
20
|
+
|
|
21
|
+
## Step 2: Identify Bug Category
|
|
22
|
+
|
|
23
|
+
**State Management (60% of bugs):**
|
|
24
|
+
- View not updating
|
|
25
|
+
- Infinite update loops
|
|
26
|
+
- @State/@Binding incorrect usage
|
|
27
|
+
- Missing @Observable
|
|
28
|
+
|
|
29
|
+
**Layout Issues:**
|
|
30
|
+
- Views not appearing
|
|
31
|
+
- Wrong positioning
|
|
32
|
+
- ScrollView/List sizing problems
|
|
33
|
+
|
|
34
|
+
**Navigation Issues:**
|
|
35
|
+
- Stack corruption
|
|
36
|
+
- Sheets not dismissing
|
|
37
|
+
- Deep linking breaking
|
|
38
|
+
|
|
39
|
+
**Performance Issues:**
|
|
40
|
+
- UI freezing
|
|
41
|
+
- Excessive redraws
|
|
42
|
+
- Memory leaks
|
|
43
|
+
|
|
44
|
+
## Step 3: Add Observability
|
|
45
|
+
|
|
46
|
+
**Add _printChanges() to suspect view:**
|
|
47
|
+
```swift
|
|
48
|
+
var body: some View {
|
|
49
|
+
let _ = Self._printChanges()
|
|
50
|
+
// rest of view
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
This prints exactly which property caused the view to redraw.
|
|
54
|
+
|
|
55
|
+
**Add logging for runtime visibility:**
|
|
56
|
+
```swift
|
|
57
|
+
import os
|
|
58
|
+
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "Debug")
|
|
59
|
+
|
|
60
|
+
// In your code:
|
|
61
|
+
logger.debug("State changed: \(self.items.count) items")
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Stream logs from CLI:**
|
|
65
|
+
```bash
|
|
66
|
+
# While app is running
|
|
67
|
+
log stream --predicate 'subsystem == "com.yourcompany.appname"' --level debug
|
|
68
|
+
|
|
69
|
+
# Search historical logs
|
|
70
|
+
log show --predicate 'subsystem == "com.yourcompany.appname"' --last 1h
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Step 4: Check Common Causes
|
|
74
|
+
|
|
75
|
+
**State red flags:**
|
|
76
|
+
- Mutating @State from outside owning view
|
|
77
|
+
- Using @StateObject when should use @Observable
|
|
78
|
+
- Missing @Bindable for passing bindings
|
|
79
|
+
|
|
80
|
+
**View identity issues:**
|
|
81
|
+
- Array index as id when order changes
|
|
82
|
+
- Missing .id() when identity should reset
|
|
83
|
+
- Same id for different content
|
|
84
|
+
|
|
85
|
+
**Environment problems:**
|
|
86
|
+
- Custom @Environment not provided
|
|
87
|
+
- Using deprecated @EnvironmentObject
|
|
88
|
+
|
|
89
|
+
## Step 5: Apply Fix
|
|
90
|
+
|
|
91
|
+
**State fix:**
|
|
92
|
+
```swift
|
|
93
|
+
// Wrong: ObservableObject
|
|
94
|
+
class ViewModel: ObservableObject {
|
|
95
|
+
@Published var count = 0
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Right: @Observable
|
|
99
|
+
@Observable
|
|
100
|
+
class ViewModel {
|
|
101
|
+
var count = 0
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**View identity fix:**
|
|
106
|
+
```swift
|
|
107
|
+
// Wrong: index as id
|
|
108
|
+
ForEach(items.indices, id: \.self) { index in }
|
|
109
|
+
|
|
110
|
+
// Right: stable id
|
|
111
|
+
ForEach(items) { item in }
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Navigation fix:**
|
|
115
|
+
```swift
|
|
116
|
+
// Wrong: NavigationView
|
|
117
|
+
NavigationView { }
|
|
118
|
+
|
|
119
|
+
// Right: NavigationStack
|
|
120
|
+
NavigationStack { }
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Step 6: Verify Fix from CLI
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# 1. Rebuild
|
|
127
|
+
xcodebuild -scheme AppName build 2>&1 | xcsift
|
|
128
|
+
|
|
129
|
+
# 2. Run tests
|
|
130
|
+
xcodebuild -scheme AppName test 2>&1 | xcsift
|
|
131
|
+
|
|
132
|
+
# 3. Launch and monitor
|
|
133
|
+
open ./build/Build/Products/Debug/AppName.app
|
|
134
|
+
log stream --predicate 'subsystem == "com.yourcompany.appname"' --level debug
|
|
135
|
+
|
|
136
|
+
# 4. Check for memory leaks
|
|
137
|
+
leaks AppName
|
|
138
|
+
|
|
139
|
+
# 5. If crash occurred, check crash logs
|
|
140
|
+
ls ~/Library/Logs/DiagnosticReports/ | grep AppName
|
|
141
|
+
cat ~/Library/Logs/DiagnosticReports/AppName_*.ips | head -100
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**For deep debugging, attach LLDB:**
|
|
145
|
+
```bash
|
|
146
|
+
lldb -n AppName
|
|
147
|
+
(lldb) breakpoint set --file ContentView.swift --line 42
|
|
148
|
+
(lldb) continue
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Report to user:
|
|
152
|
+
- "Bug no longer reproduces after [specific fix]"
|
|
153
|
+
- "Tests pass: X pass, 0 fail"
|
|
154
|
+
- "No memory leaks detected"
|
|
155
|
+
- "Ready for you to verify the fix"
|
|
156
|
+
</process>
|
|
157
|
+
|
|
158
|
+
<anti_patterns>
|
|
159
|
+
## Avoid These Mistakes
|
|
160
|
+
|
|
161
|
+
**Random changes:**
|
|
162
|
+
- Trying property wrappers without understanding
|
|
163
|
+
- Adding .id(UUID()) hoping it fixes things
|
|
164
|
+
- Wrapping in DispatchQueue.main.async as band-aid
|
|
165
|
+
|
|
166
|
+
**Ignoring root cause:**
|
|
167
|
+
- Hiding warnings instead of fixing
|
|
168
|
+
- Working around instead of fixing architecture
|
|
169
|
+
|
|
170
|
+
**Skipping _printChanges():**
|
|
171
|
+
- For state bugs, this is the fastest diagnostic
|
|
172
|
+
- Running this FIRST saves hours
|
|
173
|
+
|
|
174
|
+
**Using deprecated APIs:**
|
|
175
|
+
- Fix bugs in ObservableObject? Migrate to @Observable
|
|
176
|
+
- NavigationView bugs? Switch to NavigationStack
|
|
177
|
+
|
|
178
|
+
**Mutating state in body:**
|
|
179
|
+
- Never change @State during body computation
|
|
180
|
+
- Move to .task, .onChange, or button actions
|
|
181
|
+
</anti_patterns>
|
|
182
|
+
|
|
183
|
+
<success_criteria>
|
|
184
|
+
This workflow is complete when:
|
|
185
|
+
- [ ] Bug is reproducible (or documented as intermittent)
|
|
186
|
+
- [ ] Root cause identified using _printChanges() or other tool
|
|
187
|
+
- [ ] Fix applied following SwiftUI best practices
|
|
188
|
+
- [ ] Bug no longer occurs
|
|
189
|
+
- [ ] No new bugs introduced
|
|
190
|
+
- [ ] Tested on all target platforms
|
|
191
|
+
- [ ] Console shows no related warnings
|
|
192
|
+
</success_criteria>
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
<required_reading>
|
|
2
|
+
**Read these reference files NOW before starting:**
|
|
3
|
+
1. `../macos-apps/references/cli-observability.md` - xctrace profiling, leak detection, memory debugging
|
|
4
|
+
2. `references/performance.md` - Profiling, lazy loading, view identity, optimization
|
|
5
|
+
3. `references/layout-system.md` - Layout containers and GeometryReader pitfalls
|
|
6
|
+
</required_reading>
|
|
7
|
+
|
|
8
|
+
<process>
|
|
9
|
+
## Step 1: Establish Performance Baseline
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Build release for accurate profiling
|
|
13
|
+
xcodebuild -scheme AppName -configuration Release build 2>&1 | xcsift
|
|
14
|
+
|
|
15
|
+
# List available profiling templates
|
|
16
|
+
xcrun xctrace list templates
|
|
17
|
+
|
|
18
|
+
# Time Profiler - CPU usage baseline
|
|
19
|
+
xcrun xctrace record \
|
|
20
|
+
--template 'Time Profiler' \
|
|
21
|
+
--time-limit 30s \
|
|
22
|
+
--output baseline-cpu.trace \
|
|
23
|
+
--launch -- ./build/Build/Products/Release/AppName.app/Contents/MacOS/AppName
|
|
24
|
+
|
|
25
|
+
# SwiftUI template (if available)
|
|
26
|
+
xcrun xctrace record \
|
|
27
|
+
--template 'SwiftUI' \
|
|
28
|
+
--time-limit 30s \
|
|
29
|
+
--output baseline-swiftui.trace \
|
|
30
|
+
--launch -- ./build/Build/Products/Release/AppName.app/Contents/MacOS/AppName
|
|
31
|
+
|
|
32
|
+
# Export trace data
|
|
33
|
+
xcrun xctrace export --input baseline-cpu.trace --toc
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Document baseline: CPU usage, view update count, frame rate during slow flows.
|
|
37
|
+
|
|
38
|
+
## Step 2: Profile View Updates
|
|
39
|
+
|
|
40
|
+
Add to suspect views:
|
|
41
|
+
```swift
|
|
42
|
+
var body: some View {
|
|
43
|
+
let _ = Self._printChanges()
|
|
44
|
+
// rest of view
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Check console for which properties caused invalidation.
|
|
49
|
+
|
|
50
|
+
## Step 3: Fix Unnecessary View Recreation
|
|
51
|
+
|
|
52
|
+
**Stable view identity:**
|
|
53
|
+
```swift
|
|
54
|
+
// Wrong: index as id
|
|
55
|
+
ForEach(items.indices, id: \.self) { }
|
|
56
|
+
|
|
57
|
+
// Right: stable id
|
|
58
|
+
ForEach(items) { item in
|
|
59
|
+
ItemRow(item: item).id(item.id)
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Isolate frequently-changing state:**
|
|
64
|
+
```swift
|
|
65
|
+
// Before: entire list recreates
|
|
66
|
+
struct SlowList: View {
|
|
67
|
+
@State private var items: [Item] = []
|
|
68
|
+
@State private var count: Int = 0 // Updates often
|
|
69
|
+
|
|
70
|
+
var body: some View {
|
|
71
|
+
List(items) { item in ItemRow(item: item) }
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// After: isolate count to separate view
|
|
76
|
+
struct FastList: View {
|
|
77
|
+
@State private var items: [Item] = []
|
|
78
|
+
|
|
79
|
+
var body: some View {
|
|
80
|
+
VStack {
|
|
81
|
+
CountBadge() // Only this updates
|
|
82
|
+
List(items) { item in ItemRow(item: item) }
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Step 4: Optimize Lists
|
|
89
|
+
|
|
90
|
+
```swift
|
|
91
|
+
// Use lazy containers
|
|
92
|
+
ScrollView {
|
|
93
|
+
LazyVStack(spacing: 8) {
|
|
94
|
+
ForEach(items) { item in
|
|
95
|
+
ItemRow(item: item)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Step 5: Reduce Layout Passes
|
|
102
|
+
|
|
103
|
+
```swift
|
|
104
|
+
// Avoid GeometryReader when possible
|
|
105
|
+
// Before:
|
|
106
|
+
GeometryReader { geo in
|
|
107
|
+
Circle().frame(width: geo.size.width * 0.8)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// After:
|
|
111
|
+
Circle()
|
|
112
|
+
.frame(maxWidth: .infinity)
|
|
113
|
+
.aspectRatio(1, contentMode: .fit)
|
|
114
|
+
.padding(.horizontal, 20)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Step 6: Use @Observable
|
|
118
|
+
|
|
119
|
+
```swift
|
|
120
|
+
// Before: ObservableObject invalidates everything
|
|
121
|
+
class OldViewModel: ObservableObject {
|
|
122
|
+
@Published var name = ""
|
|
123
|
+
@Published var count = 0
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// After: granular updates
|
|
127
|
+
@Observable
|
|
128
|
+
class ViewModel {
|
|
129
|
+
var name = ""
|
|
130
|
+
var count = 0
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Step 7: Verify Improvements from CLI
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# 1. Rebuild release
|
|
138
|
+
xcodebuild -scheme AppName -configuration Release build 2>&1 | xcsift
|
|
139
|
+
|
|
140
|
+
# 2. Profile again with same settings
|
|
141
|
+
xcrun xctrace record \
|
|
142
|
+
--template 'Time Profiler' \
|
|
143
|
+
--time-limit 30s \
|
|
144
|
+
--output optimized-cpu.trace \
|
|
145
|
+
--launch -- ./build/Build/Products/Release/AppName.app/Contents/MacOS/AppName
|
|
146
|
+
|
|
147
|
+
# 3. Check for memory leaks
|
|
148
|
+
leaks AppName
|
|
149
|
+
|
|
150
|
+
# 4. Run tests to ensure no regressions
|
|
151
|
+
xcodebuild test -scheme AppName 2>&1 | xcsift
|
|
152
|
+
|
|
153
|
+
# 5. Launch for user verification
|
|
154
|
+
open ./build/Build/Products/Release/AppName.app
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Report to user:
|
|
158
|
+
- "CPU usage reduced from X% to Y%"
|
|
159
|
+
- "View body invocations reduced by Z%"
|
|
160
|
+
- "No memory leaks detected"
|
|
161
|
+
- "Tests: all pass, no regressions"
|
|
162
|
+
- "App launched - please verify scrolling feels smooth"
|
|
163
|
+
</process>
|
|
164
|
+
|
|
165
|
+
<anti_patterns>
|
|
166
|
+
## Avoid These Mistakes
|
|
167
|
+
|
|
168
|
+
**Optimizing without profiling:**
|
|
169
|
+
- Always measure with Instruments first
|
|
170
|
+
- Let data guide decisions
|
|
171
|
+
|
|
172
|
+
**Using .equatable() as first resort:**
|
|
173
|
+
- Masks the issue instead of fixing it
|
|
174
|
+
- Can cause stale UI
|
|
175
|
+
|
|
176
|
+
**Testing only in simulator:**
|
|
177
|
+
- Simulator runs on Mac CPU
|
|
178
|
+
- Always profile on real devices
|
|
179
|
+
|
|
180
|
+
**Ignoring view identity:**
|
|
181
|
+
- Use explicit id() when needed
|
|
182
|
+
- Ensure stable IDs in ForEach
|
|
183
|
+
|
|
184
|
+
**Premature view extraction:**
|
|
185
|
+
- Extract when it isolates state observation
|
|
186
|
+
- Not "for performance" by default
|
|
187
|
+
</anti_patterns>
|
|
188
|
+
|
|
189
|
+
<success_criteria>
|
|
190
|
+
This workflow is complete when:
|
|
191
|
+
- [ ] Time Profiler shows reduced CPU usage
|
|
192
|
+
- [ ] 50%+ reduction in unnecessary view body invocations
|
|
193
|
+
- [ ] Scroll performance at 60fps
|
|
194
|
+
- [ ] App feels responsive on oldest supported device
|
|
195
|
+
- [ ] Memory usage stable, no leaks
|
|
196
|
+
- [ ] _printChanges() confirms targeted updates
|
|
197
|
+
</success_criteria>
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
<required_reading>
|
|
2
|
+
**Read these reference files NOW before starting:**
|
|
3
|
+
1. `../macos-apps/references/cli-workflow.md` - Build, test, sign, notarize from CLI
|
|
4
|
+
2. `../macos-apps/references/security-code-signing.md` - Code signing and notarization
|
|
5
|
+
3. `references/platform-integration.md` - iOS/macOS specifics, platform requirements
|
|
6
|
+
</required_reading>
|
|
7
|
+
|
|
8
|
+
<process>
|
|
9
|
+
## Step 1: Run Tests
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# iOS
|
|
13
|
+
xcodebuild test -scheme AppName -destination 'platform=iOS Simulator,name=iPhone 15 Pro' 2>&1 | xcsift
|
|
14
|
+
|
|
15
|
+
# macOS
|
|
16
|
+
xcodebuild test -scheme AppName 2>&1 | xcsift
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
All tests must pass before shipping.
|
|
20
|
+
|
|
21
|
+
## Step 2: Profile Performance from CLI
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Build release for accurate profiling
|
|
25
|
+
xcodebuild -scheme AppName -configuration Release build 2>&1 | xcsift
|
|
26
|
+
|
|
27
|
+
# Time Profiler
|
|
28
|
+
xcrun xctrace record \
|
|
29
|
+
--template 'Time Profiler' \
|
|
30
|
+
--time-limit 30s \
|
|
31
|
+
--output ship-profile.trace \
|
|
32
|
+
--launch -- ./build/Build/Products/Release/AppName.app/Contents/MacOS/AppName
|
|
33
|
+
|
|
34
|
+
# Check for leaks
|
|
35
|
+
leaks AppName
|
|
36
|
+
|
|
37
|
+
# Memory allocations
|
|
38
|
+
xcrun xctrace record \
|
|
39
|
+
--template 'Allocations' \
|
|
40
|
+
--time-limit 30s \
|
|
41
|
+
--output ship-allocations.trace \
|
|
42
|
+
--attach $(pgrep AppName)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Report: "No memory leaks. CPU usage acceptable. Ready to ship."
|
|
46
|
+
|
|
47
|
+
## Step 3: Update Version Numbers
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Marketing version
|
|
51
|
+
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString 1.0.0" "YourApp/Info.plist"
|
|
52
|
+
|
|
53
|
+
# Build number (must increment each submission)
|
|
54
|
+
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion 1" "YourApp/Info.plist"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Step 4: Create Privacy Manifest
|
|
58
|
+
|
|
59
|
+
Create `PrivacyInfo.xcprivacy` with all accessed APIs:
|
|
60
|
+
- NSPrivacyAccessedAPICategoryUserDefaults
|
|
61
|
+
- NSPrivacyAccessedAPICategoryFileTimestamp
|
|
62
|
+
- etc.
|
|
63
|
+
|
|
64
|
+
Required for iOS 17+ and macOS 14+.
|
|
65
|
+
|
|
66
|
+
## Step 5: Verify App Icons
|
|
67
|
+
|
|
68
|
+
All required sizes in Assets.xcassets:
|
|
69
|
+
- 1024x1024 App Store icon (required)
|
|
70
|
+
- All device sizes filled
|
|
71
|
+
|
|
72
|
+
## Step 6: Configure Code Signing
|
|
73
|
+
|
|
74
|
+
Set in project.yml (XcodeGen) or verify existing settings:
|
|
75
|
+
```yaml
|
|
76
|
+
settings:
|
|
77
|
+
base:
|
|
78
|
+
CODE_SIGN_STYLE: Automatic
|
|
79
|
+
DEVELOPMENT_TEAM: YOURTEAMID
|
|
80
|
+
CODE_SIGN_IDENTITY: "Apple Distribution"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Or set via xcodebuild:
|
|
84
|
+
```bash
|
|
85
|
+
xcodebuild -scheme AppName \
|
|
86
|
+
CODE_SIGN_STYLE=Automatic \
|
|
87
|
+
DEVELOPMENT_TEAM=YOURTEAMID \
|
|
88
|
+
archive
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Step 7: Create Archive
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
xcodebuild archive \
|
|
95
|
+
-scheme YourApp \
|
|
96
|
+
-configuration Release \
|
|
97
|
+
-archivePath ./build/YourApp.xcarchive \
|
|
98
|
+
-destination 'generic/platform=iOS'
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Step 8: Export for App Store
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
xcodebuild -exportArchive \
|
|
105
|
+
-archivePath ./build/YourApp.xcarchive \
|
|
106
|
+
-exportPath ./build/Export \
|
|
107
|
+
-exportOptionsPlist ExportOptions.plist
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Step 9: Create App in App Store Connect
|
|
111
|
+
|
|
112
|
+
1. Visit appstoreconnect.apple.com
|
|
113
|
+
2. My Apps → + → New App
|
|
114
|
+
3. Fill in name, bundle ID, SKU
|
|
115
|
+
|
|
116
|
+
## Step 10: Upload Build from CLI
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# Validate before upload
|
|
120
|
+
xcrun altool --validate-app -f ./build/Export/AppName.ipa -t ios --apiKey YOUR_KEY --apiIssuer YOUR_ISSUER
|
|
121
|
+
|
|
122
|
+
# Upload to App Store Connect
|
|
123
|
+
xcrun altool --upload-app -f ./build/Export/AppName.ipa -t ios --apiKey YOUR_KEY --apiIssuer YOUR_ISSUER
|
|
124
|
+
|
|
125
|
+
# For macOS apps, notarize first (see ../macos-apps/references/security-code-signing.md)
|
|
126
|
+
xcrun notarytool submit AppName.zip --apple-id your@email.com --team-id TEAMID --password @keychain:AC_PASSWORD --wait
|
|
127
|
+
xcrun stapler staple AppName.app
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Alternative: Use Transporter app if API keys aren't set up.
|
|
131
|
+
|
|
132
|
+
## Step 11: Complete Metadata
|
|
133
|
+
|
|
134
|
+
In App Store Connect:
|
|
135
|
+
- Description (4000 char max)
|
|
136
|
+
- Keywords (100 char max)
|
|
137
|
+
- Screenshots (at least 1 per device type)
|
|
138
|
+
- Privacy Policy URL
|
|
139
|
+
- Support URL
|
|
140
|
+
|
|
141
|
+
## Step 12: Configure TestFlight (Optional)
|
|
142
|
+
|
|
143
|
+
1. Wait for build processing
|
|
144
|
+
2. Add internal testers (up to 100)
|
|
145
|
+
3. For external testing, submit for Beta App Review
|
|
146
|
+
|
|
147
|
+
## Step 13: Submit for Review
|
|
148
|
+
|
|
149
|
+
1. Select processed build
|
|
150
|
+
2. Complete App Review Information
|
|
151
|
+
3. Provide demo account if login required
|
|
152
|
+
4. Submit for Review
|
|
153
|
+
|
|
154
|
+
Review typically completes in 24-48 hours.
|
|
155
|
+
|
|
156
|
+
## Step 14: Handle Outcome
|
|
157
|
+
|
|
158
|
+
**If approved:** Release manually or automatically
|
|
159
|
+
|
|
160
|
+
**If rejected:**
|
|
161
|
+
- Read rejection reason
|
|
162
|
+
- Fix issues
|
|
163
|
+
- Increment build number
|
|
164
|
+
- Re-upload and resubmit
|
|
165
|
+
</process>
|
|
166
|
+
|
|
167
|
+
<anti_patterns>
|
|
168
|
+
## Avoid These Mistakes
|
|
169
|
+
|
|
170
|
+
**Testing only in simulator:**
|
|
171
|
+
- Always test on physical devices before submission
|
|
172
|
+
|
|
173
|
+
**Incomplete privacy manifest:**
|
|
174
|
+
- Document all accessed APIs
|
|
175
|
+
- Use Xcode's Privacy Report
|
|
176
|
+
|
|
177
|
+
**Same build number:**
|
|
178
|
+
- Must increment CFBundleVersion for each upload
|
|
179
|
+
|
|
180
|
+
**Debug code in release:**
|
|
181
|
+
- Remove NSLog, test accounts, debug views
|
|
182
|
+
- Use #if DEBUG
|
|
183
|
+
|
|
184
|
+
**Screenshots of splash screen:**
|
|
185
|
+
- Must show app in actual use
|
|
186
|
+
- Guideline 2.3.3 rejection risk
|
|
187
|
+
|
|
188
|
+
**Not testing exported build:**
|
|
189
|
+
- Export process applies different signing
|
|
190
|
+
- Apps can crash after export despite working in Xcode
|
|
191
|
+
</anti_patterns>
|
|
192
|
+
|
|
193
|
+
<success_criteria>
|
|
194
|
+
This workflow is complete when:
|
|
195
|
+
- [ ] All tests pass
|
|
196
|
+
- [ ] Version and build numbers updated
|
|
197
|
+
- [ ] Privacy manifest complete
|
|
198
|
+
- [ ] Archive created successfully
|
|
199
|
+
- [ ] Build uploaded to App Store Connect
|
|
200
|
+
- [ ] Metadata and screenshots complete
|
|
201
|
+
- [ ] App submitted for review
|
|
202
|
+
- [ ] App approved and live on App Store
|
|
203
|
+
</success_criteria>
|