ethan-skill 1.11.0 → 1.12.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/dist/cli/index.js +1019 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +206 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/skills/27-tech-debt.d.ts +3 -0
- package/dist/skills/27-tech-debt.d.ts.map +1 -0
- package/dist/skills/27-tech-debt.js +149 -0
- package/dist/skills/27-tech-debt.js.map +1 -0
- package/dist/skills/28-api-mock.d.ts +3 -0
- package/dist/skills/28-api-mock.d.ts.map +1 -0
- package/dist/skills/28-api-mock.js +272 -0
- package/dist/skills/28-api-mock.js.map +1 -0
- package/dist/skills/29-data-migration.d.ts +3 -0
- package/dist/skills/29-data-migration.d.ts.map +1 -0
- package/dist/skills/29-data-migration.js +331 -0
- package/dist/skills/29-data-migration.js.map +1 -0
- package/dist/skills/30-llm-feature.d.ts +3 -0
- package/dist/skills/30-llm-feature.d.ts.map +1 -0
- package/dist/skills/30-llm-feature.js +328 -0
- package/dist/skills/30-llm-feature.js.map +1 -0
- package/dist/skills/31-threat-model.d.ts +3 -0
- package/dist/skills/31-threat-model.d.ts.map +1 -0
- package/dist/skills/31-threat-model.js +240 -0
- package/dist/skills/31-threat-model.js.map +1 -0
- package/dist/skills/32-green-code.d.ts +3 -0
- package/dist/skills/32-green-code.d.ts.map +1 -0
- package/dist/skills/32-green-code.js +346 -0
- package/dist/skills/32-green-code.js.map +1 -0
- package/dist/skills/33-service-catalog.d.ts +3 -0
- package/dist/skills/33-service-catalog.d.ts.map +1 -0
- package/dist/skills/33-service-catalog.js +334 -0
- package/dist/skills/33-service-catalog.js.map +1 -0
- package/dist/skills/34-mobile-review.d.ts +3 -0
- package/dist/skills/34-mobile-review.d.ts.map +1 -0
- package/dist/skills/34-mobile-review.js +390 -0
- package/dist/skills/34-mobile-review.js.map +1 -0
- package/dist/skills/35-data-pipeline.d.ts +3 -0
- package/dist/skills/35-data-pipeline.d.ts.map +1 -0
- package/dist/skills/35-data-pipeline.js +392 -0
- package/dist/skills/35-data-pipeline.js.map +1 -0
- package/dist/skills/36-ml-experiment.d.ts +3 -0
- package/dist/skills/36-ml-experiment.d.ts.map +1 -0
- package/dist/skills/36-ml-experiment.js +415 -0
- package/dist/skills/36-ml-experiment.js.map +1 -0
- package/dist/skills/index.d.ts +10 -0
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +41 -1
- package/dist/skills/index.js.map +1 -1
- package/dist/skills/pipeline.d.ts.map +1 -1
- package/dist/skills/pipeline.js +35 -0
- package/dist/skills/pipeline.js.map +1 -1
- package/dist/skills/skills.test.js +3 -3
- package/dist/skills/skills.test.js.map +1 -1
- package/package.json +1 -1
- package/rules/claude-code/CLAUDE.md +2963 -3
- package/rules/cline/.clinerules +2805 -2
- package/rules/codebuddy/CODEBUDDY.md +2913 -2
- package/rules/continue/.continuerules +2805 -2
- package/rules/copilot/copilot-instructions.md +2883 -2
- package/rules/cursor/.cursorrules +2952 -2
- package/rules/cursor/smart-flow.mdc +2952 -2
- package/rules/jetbrains/smart-flow.md +2883 -2
- package/rules/lingma/smart-flow.md +2904 -3
- package/rules/windsurf/.windsurf/rules/smart-flow.md +2884 -3
- package/rules/zed/smart-flow.rules +2794 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"34-mobile-review.d.ts","sourceRoot":"","sources":["../../src/skills/34-mobile-review.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,eAAO,MAAM,iBAAiB,EAAE,eAiY/B,CAAC"}
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mobileReviewSkill = void 0;
|
|
4
|
+
exports.mobileReviewSkill = {
|
|
5
|
+
id: 'mobile-review',
|
|
6
|
+
name: '移动端专项审查',
|
|
7
|
+
nameEn: 'mobile_review',
|
|
8
|
+
order: 34,
|
|
9
|
+
description: '审查移动端应用的平台合规、性能基准、离线同步、无障碍与崩溃防护',
|
|
10
|
+
descriptionEn: 'Review mobile app platform compliance, performance benchmarks, offline sync, accessibility, and crash protection',
|
|
11
|
+
detailDescription: `移动端应用面临独特的挑战:App Store 合规审查、有限的设备性能、不稳定的网络环境和严格的无障碍要求。
|
|
12
|
+
本 Skill 提供系统化的移动端专项审查框架:覆盖 iOS/Android 平台合规要求、
|
|
13
|
+
启动性能和内存基准、离线缓存与数据同步策略、VoiceOver/TalkBack 无障碍检查,
|
|
14
|
+
以及主线程阻塞和内存泄漏防护,确保应用通过审核并提供卓越的用户体验。`,
|
|
15
|
+
triggers: [
|
|
16
|
+
'移动端审查',
|
|
17
|
+
'mobile review',
|
|
18
|
+
'ios review',
|
|
19
|
+
'android review',
|
|
20
|
+
'flutter review',
|
|
21
|
+
'react native review',
|
|
22
|
+
'移动端性能',
|
|
23
|
+
'app review',
|
|
24
|
+
'@ethan mobile-review',
|
|
25
|
+
'/mobile-review',
|
|
26
|
+
],
|
|
27
|
+
steps: [
|
|
28
|
+
{
|
|
29
|
+
title: '1. 平台合规审查',
|
|
30
|
+
content: `检查 iOS 和 Android 的合规要求,确保顺利通过审核:
|
|
31
|
+
|
|
32
|
+
**iOS App Store 合规 Checklist**
|
|
33
|
+
\`\`\`
|
|
34
|
+
□ 隐私权限声明
|
|
35
|
+
- Info.plist 中每个权限 Key 必须有 Usage Description
|
|
36
|
+
- NSCameraUsageDescription: "用于拍摄商品照片"
|
|
37
|
+
- NSLocationWhenInUseUsageDescription: "用于查找附近服务"
|
|
38
|
+
- NSPhotoLibraryUsageDescription: "用于选择头像图片"
|
|
39
|
+
|
|
40
|
+
□ App Tracking Transparency (ATT)
|
|
41
|
+
- iOS 14+ 追踪用户需要弹窗授权
|
|
42
|
+
- NSUserTrackingUsageDescription 必须填写
|
|
43
|
+
|
|
44
|
+
□ 隐私清单 (Privacy Manifest, iOS 17+)
|
|
45
|
+
- PrivacyInfo.xcprivacy 文件
|
|
46
|
+
- 声明使用的 Required Reason API(UserDefaults/File timestamp 等)
|
|
47
|
+
|
|
48
|
+
□ 网络安全配置
|
|
49
|
+
- 所有网络请求使用 HTTPS(ATS 默认开启)
|
|
50
|
+
- 自定义 Exception 需要合理理由
|
|
51
|
+
|
|
52
|
+
□ 支付合规
|
|
53
|
+
- 数字商品/虚拟货币必须使用 In-App Purchase
|
|
54
|
+
- 不得引导用户到外部网站购买
|
|
55
|
+
\`\`\`
|
|
56
|
+
|
|
57
|
+
**Android Google Play 合规 Checklist**
|
|
58
|
+
\`\`\`
|
|
59
|
+
□ 权限最小化
|
|
60
|
+
- 仅申请功能必需的权限
|
|
61
|
+
- targetSdkVersion ≥ 33(Play Store 要求)
|
|
62
|
+
- 危险权限在使用前实时申请(非安装时)
|
|
63
|
+
|
|
64
|
+
□ 数据安全表(Data Safety Section)
|
|
65
|
+
- 明确声明收集的数据类型
|
|
66
|
+
- 说明是否与第三方共享
|
|
67
|
+
|
|
68
|
+
□ 广告 ID(GAID)
|
|
69
|
+
- Android 12+ 需要 AD_ID 权限
|
|
70
|
+
- 儿童类应用禁止使用广告 ID
|
|
71
|
+
|
|
72
|
+
□ 64位支持
|
|
73
|
+
- 所有 native library 提供 arm64-v8a 版本
|
|
74
|
+
\`\`\`
|
|
75
|
+
|
|
76
|
+
**输出**:平台合规检查报告(iOS + Android,通过/未通过标注)`,
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
title: '2. 性能专项审查',
|
|
80
|
+
content: `评估移动端应用的关键性能指标:
|
|
81
|
+
|
|
82
|
+
**性能基准标准**
|
|
83
|
+
|
|
84
|
+
| 指标 | 优秀 | 可接受 | 需优化 |
|
|
85
|
+
|------|------|--------|--------|
|
|
86
|
+
| **冷启动时间** | < 1.5s | < 2.5s | > 2.5s |
|
|
87
|
+
| **热启动时间** | < 0.5s | < 1.0s | > 1.0s |
|
|
88
|
+
| **帧率(FPS)** | 60fps | 55fps | < 50fps |
|
|
89
|
+
| **首屏渲染** | < 1.0s | < 2.0s | > 2.0s |
|
|
90
|
+
| **内存占用(前台)** | < 150MB | < 250MB | > 250MB |
|
|
91
|
+
| **安装包大小** | < 30MB | < 60MB | > 60MB |
|
|
92
|
+
| **电池消耗** | < 5%/h | < 10%/h | > 10%/h |
|
|
93
|
+
|
|
94
|
+
**启动性能优化**
|
|
95
|
+
\`\`\`swift
|
|
96
|
+
// iOS — 减少 AppDelegate 启动时工作
|
|
97
|
+
@main class AppDelegate: UIResponder, UIApplicationDelegate {
|
|
98
|
+
func application(_ application: UIApplication,
|
|
99
|
+
didFinishLaunchingWithOptions options: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
|
100
|
+
|
|
101
|
+
// ❌ 避免在启动时进行:
|
|
102
|
+
// - 同步网络请求
|
|
103
|
+
// - 大量数据库初始化
|
|
104
|
+
// - 复杂计算
|
|
105
|
+
|
|
106
|
+
// ✅ 启动时只做:
|
|
107
|
+
setupCrashReporting() // 轻量
|
|
108
|
+
configureDependencyInjection() // 必须
|
|
109
|
+
|
|
110
|
+
// ✅ 延迟到首屏渲染后
|
|
111
|
+
DispatchQueue.main.async {
|
|
112
|
+
self.setupAnalytics()
|
|
113
|
+
self.prefetchData()
|
|
114
|
+
}
|
|
115
|
+
return true
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
\`\`\`
|
|
119
|
+
|
|
120
|
+
\`\`\`kotlin
|
|
121
|
+
// Android — 使用 App Startup 库延迟初始化
|
|
122
|
+
class MyInitializer : Initializer<Unit> {
|
|
123
|
+
override fun create(context: Context) {
|
|
124
|
+
// 只初始化核心功能
|
|
125
|
+
}
|
|
126
|
+
override fun dependencies() = emptyList<Class<out Initializer<*>>>()
|
|
127
|
+
}
|
|
128
|
+
\`\`\`
|
|
129
|
+
|
|
130
|
+
**包大小优化**
|
|
131
|
+
\`\`\`
|
|
132
|
+
iOS:
|
|
133
|
+
- 使用 Asset Catalog 而非散落图片
|
|
134
|
+
- On-Demand Resources 下载非核心资源
|
|
135
|
+
- App Thinning(Bitcode + Slicing)
|
|
136
|
+
|
|
137
|
+
Android:
|
|
138
|
+
- App Bundle (.aab) 替代 APK(减少 20-40%)
|
|
139
|
+
- R8/ProGuard 代码压缩
|
|
140
|
+
- WebP 替换 PNG/JPEG
|
|
141
|
+
- 动态功能模块(Dynamic Feature Modules)
|
|
142
|
+
\`\`\`
|
|
143
|
+
|
|
144
|
+
**输出**:性能基准报告 + 优化建议清单`,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
title: '3. 离线与数据同步',
|
|
148
|
+
content: `设计可靠的离线能力和数据同步策略:
|
|
149
|
+
|
|
150
|
+
**离线架构模式**
|
|
151
|
+
|
|
152
|
+
**① Cache-First(适合内容类 App)**
|
|
153
|
+
\`\`\`typescript
|
|
154
|
+
// React Native — 先读本地缓存,后台刷新
|
|
155
|
+
async function getArticles(): Promise<Article[]> {
|
|
156
|
+
const cached = await AsyncStorage.getItem('articles');
|
|
157
|
+
|
|
158
|
+
// 立即返回缓存(用户不等待)
|
|
159
|
+
if (cached) {
|
|
160
|
+
const data = JSON.parse(cached);
|
|
161
|
+
// 后台静默刷新
|
|
162
|
+
fetchAndCache().catch(console.error);
|
|
163
|
+
return data;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// 无缓存时等待网络
|
|
167
|
+
return fetchAndCache();
|
|
168
|
+
}
|
|
169
|
+
\`\`\`
|
|
170
|
+
|
|
171
|
+
**② Optimistic Update(适合操作类 App)**
|
|
172
|
+
\`\`\`typescript
|
|
173
|
+
// 先更新本地,后台同步到服务器
|
|
174
|
+
async function toggleLike(postId: string) {
|
|
175
|
+
// 立即更新 UI(乐观更新)
|
|
176
|
+
dispatch({ type: 'TOGGLE_LIKE', postId });
|
|
177
|
+
|
|
178
|
+
try {
|
|
179
|
+
await api.post(\`/posts/\${postId}/like\`);
|
|
180
|
+
} catch (error) {
|
|
181
|
+
// 失败时回滚
|
|
182
|
+
dispatch({ type: 'REVERT_LIKE', postId });
|
|
183
|
+
showToast('操作失败,已恢复');
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
\`\`\`
|
|
187
|
+
|
|
188
|
+
**冲突解决策略**
|
|
189
|
+
\`\`\`
|
|
190
|
+
策略 适用场景
|
|
191
|
+
─────────────────────────────────
|
|
192
|
+
Last-Write-Wins 一般设置、非关键数据
|
|
193
|
+
Server-Wins 金融数据、库存数量
|
|
194
|
+
Client-Wins 用户个人偏好
|
|
195
|
+
Merge(合并) 文档协作(CRDT)
|
|
196
|
+
Ask User(提示用户) 重要数据冲突
|
|
197
|
+
\`\`\`
|
|
198
|
+
|
|
199
|
+
**网络状态监听**
|
|
200
|
+
\`\`\`typescript
|
|
201
|
+
import NetInfo from '@react-native-community/netinfo';
|
|
202
|
+
|
|
203
|
+
NetInfo.addEventListener(state => {
|
|
204
|
+
if (state.isConnected && hasPendingSync()) {
|
|
205
|
+
syncPendingOperations(); // 联网后自动同步
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// 队列离线操作
|
|
210
|
+
async function queueOperation(op: Operation) {
|
|
211
|
+
await OfflineQueue.push(op);
|
|
212
|
+
if (await NetInfo.fetch().then(s => s.isConnected)) {
|
|
213
|
+
await flushQueue();
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
\`\`\`
|
|
217
|
+
|
|
218
|
+
**输出**:离线架构方案 + 冲突解决策略 + 代码模板`,
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
title: '4. 无障碍审查',
|
|
222
|
+
content: `确保应用对视障、听障、行动不便用户友好:
|
|
223
|
+
|
|
224
|
+
**无障碍审查 Checklist**
|
|
225
|
+
|
|
226
|
+
**① 屏幕阅读器(VoiceOver/TalkBack)**
|
|
227
|
+
\`\`\`swift
|
|
228
|
+
// iOS — 所有交互元素必须有 accessibilityLabel
|
|
229
|
+
imageView.accessibilityLabel = "用户头像"
|
|
230
|
+
imageView.accessibilityHint = "双击查看个人资料"
|
|
231
|
+
|
|
232
|
+
// 自定义控件
|
|
233
|
+
button.isAccessibilityElement = true
|
|
234
|
+
button.accessibilityTraits = .button
|
|
235
|
+
button.accessibilityLabel = "发布文章"
|
|
236
|
+
|
|
237
|
+
// ❌ 避免:仅用图标表示功能,无文字描述
|
|
238
|
+
// ✅ 正确:图标 + accessibilityLabel
|
|
239
|
+
\`\`\`
|
|
240
|
+
|
|
241
|
+
\`\`\`kotlin
|
|
242
|
+
// Android
|
|
243
|
+
imageButton.contentDescription = "发布文章"
|
|
244
|
+
// 装饰性图片应设置 importantForAccessibility = no
|
|
245
|
+
decorativeImage.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
|
|
246
|
+
\`\`\`
|
|
247
|
+
|
|
248
|
+
**② 触控目标大小**
|
|
249
|
+
\`\`\`
|
|
250
|
+
最小触控目标:
|
|
251
|
+
- iOS: 44pt × 44pt(Apple HIG 标准)
|
|
252
|
+
- Android: 48dp × 48dp(Material Design 标准)
|
|
253
|
+
|
|
254
|
+
检查方法:
|
|
255
|
+
- iOS Accessibility Inspector: Xcode → Open Developer Tool
|
|
256
|
+
- Android: 开发者选项 → 显示触控区域
|
|
257
|
+
\`\`\`
|
|
258
|
+
|
|
259
|
+
**③ 色彩对比度**
|
|
260
|
+
\`\`\`
|
|
261
|
+
WCAG 2.1 标准:
|
|
262
|
+
- 正文文字(<18pt):对比度 ≥ 4.5:1
|
|
263
|
+
- 大文字(≥18pt):对比度 ≥ 3:1
|
|
264
|
+
- 用户界面组件:对比度 ≥ 3:1
|
|
265
|
+
|
|
266
|
+
工具:
|
|
267
|
+
- Colour Contrast Analyser(桌面工具)
|
|
268
|
+
- axe DevTools(Web)
|
|
269
|
+
- Xcode Accessibility Inspector(iOS)
|
|
270
|
+
\`\`\`
|
|
271
|
+
|
|
272
|
+
**④ 动态字体支持**
|
|
273
|
+
\`\`\`swift
|
|
274
|
+
// iOS — 支持系统字体大小调整
|
|
275
|
+
label.font = UIFont.preferredFont(forTextStyle: .body)
|
|
276
|
+
label.adjustsFontForContentSizeCategory = true
|
|
277
|
+
\`\`\`
|
|
278
|
+
|
|
279
|
+
**⑤ 减弱动态效果**
|
|
280
|
+
\`\`\`swift
|
|
281
|
+
// 尊重"减弱动态效果"设置
|
|
282
|
+
if UIAccessibility.isReduceMotionEnabled {
|
|
283
|
+
// 使用简单的淡入淡出替代复杂动画
|
|
284
|
+
UIView.animate(withDuration: 0.1) { view.alpha = 1 }
|
|
285
|
+
} else {
|
|
286
|
+
// 完整动画
|
|
287
|
+
performFullAnimation()
|
|
288
|
+
}
|
|
289
|
+
\`\`\`
|
|
290
|
+
|
|
291
|
+
**输出**:无障碍审查报告(VoiceOver/TalkBack + 色彩 + 触控 + 字体)`,
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
title: '5. 崩溃与 ANR 防护',
|
|
295
|
+
content: `防止主线程阻塞、内存泄漏和崩溃:
|
|
296
|
+
|
|
297
|
+
**崩溃防护 Checklist**
|
|
298
|
+
|
|
299
|
+
**① 主线程保护(ANR / 卡顿)**
|
|
300
|
+
\`\`\`kotlin
|
|
301
|
+
// Android — 严格模式检测主线程 I/O(开发阶段)
|
|
302
|
+
if (BuildConfig.DEBUG) {
|
|
303
|
+
StrictMode.setThreadPolicy(
|
|
304
|
+
StrictMode.ThreadPolicy.Builder()
|
|
305
|
+
.detectDiskReads()
|
|
306
|
+
.detectDiskWrites()
|
|
307
|
+
.detectNetwork()
|
|
308
|
+
.penaltyLog()
|
|
309
|
+
.build()
|
|
310
|
+
)
|
|
311
|
+
}
|
|
312
|
+
\`\`\`
|
|
313
|
+
|
|
314
|
+
\`\`\`swift
|
|
315
|
+
// iOS — 所有耗时操作移到后台线程
|
|
316
|
+
// ❌ 在主线程执行网络请求(卡 UI)
|
|
317
|
+
let data = try! Data(contentsOf: url) // 同步,阻塞主线程
|
|
318
|
+
|
|
319
|
+
// ✅ 后台执行,主线程更新 UI
|
|
320
|
+
Task {
|
|
321
|
+
let data = await fetchData(url: url) // 异步
|
|
322
|
+
await MainActor.run {
|
|
323
|
+
updateUI(data) // 回主线程
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
\`\`\`
|
|
327
|
+
|
|
328
|
+
**② 内存泄漏防护**
|
|
329
|
+
\`\`\`swift
|
|
330
|
+
// iOS — 使用 weak/unowned 避免循环引用
|
|
331
|
+
class ViewController: UIViewController {
|
|
332
|
+
var closure: (() -> Void)?
|
|
333
|
+
|
|
334
|
+
func setup() {
|
|
335
|
+
// ❌ 强引用循环
|
|
336
|
+
closure = { self.doSomething() }
|
|
337
|
+
|
|
338
|
+
// ✅ weak 引用
|
|
339
|
+
closure = { [weak self] in self?.doSomething() }
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// 使用 Instruments 的 Leaks 模板检测
|
|
344
|
+
// Xcode → Product → Profile → Leaks
|
|
345
|
+
\`\`\`
|
|
346
|
+
|
|
347
|
+
**③ 崩溃上报集成**
|
|
348
|
+
\`\`\`typescript
|
|
349
|
+
// React Native — 集成 Sentry
|
|
350
|
+
import * as Sentry from '@sentry/react-native';
|
|
351
|
+
|
|
352
|
+
Sentry.init({
|
|
353
|
+
dsn: 'https://xxx@sentry.io/xxx',
|
|
354
|
+
tracesSampleRate: 0.2,
|
|
355
|
+
beforeSend: (event) => {
|
|
356
|
+
// 过滤敏感信息
|
|
357
|
+
delete event.user?.email;
|
|
358
|
+
return event;
|
|
359
|
+
},
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
// 自定义崩溃上下文
|
|
363
|
+
Sentry.setContext('order', { orderId, userId });
|
|
364
|
+
\`\`\`
|
|
365
|
+
|
|
366
|
+
**④ 崩溃率基准**
|
|
367
|
+
\`\`\`
|
|
368
|
+
指标 目标值 警戒线
|
|
369
|
+
──────────────────────────────
|
|
370
|
+
崩溃率 < 0.1% > 0.5%
|
|
371
|
+
ANR 率 < 0.05% > 0.2%
|
|
372
|
+
内存 OOM 率 < 0.01% > 0.1%
|
|
373
|
+
\`\`\`
|
|
374
|
+
|
|
375
|
+
**输出**:崩溃防护代码模板 + ANR 检测配置 + 崩溃率监控方案`,
|
|
376
|
+
},
|
|
377
|
+
],
|
|
378
|
+
outputFormat: '平台合规报告(iOS + Android)+ 性能基准报告 + 离线架构方案 + 无障碍审查报告 + 崩溃防护 Checklist',
|
|
379
|
+
examples: [],
|
|
380
|
+
notes: [
|
|
381
|
+
'App Store 审核可能因隐私声明不完整被拒——提交前必须逐项核对 Info.plist 权限说明',
|
|
382
|
+
'移动端性能优化应以真机测试为准,模拟器结果不具代表性(特别是低端 Android 设备)',
|
|
383
|
+
'无障碍功能不仅是道德责任,在部分国家/地区(如美国 ADA、欧盟 EAA)也是法律要求',
|
|
384
|
+
'崩溃率超过 0.5% 会被 Google Play 标记为"问题应用",影响商店排名',
|
|
385
|
+
'包大小每增加 10MB 约导致 Android 安装转化率下降 1-2%,务必定期监控',
|
|
386
|
+
],
|
|
387
|
+
category: '质量侧',
|
|
388
|
+
nextSkill: 'performance',
|
|
389
|
+
};
|
|
390
|
+
//# sourceMappingURL=34-mobile-review.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"34-mobile-review.js","sourceRoot":"","sources":["../../src/skills/34-mobile-review.ts"],"names":[],"mappings":";;;AAEa,QAAA,iBAAiB,GAAoB;IAChD,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,eAAe;IACvB,KAAK,EAAE,EAAE;IACT,WAAW,EAAE,iCAAiC;IAC9C,aAAa,EAAE,kHAAkH;IACjI,iBAAiB,EAAE;;;mCAGc;IACjC,QAAQ,EAAE;QACR,OAAO;QACP,eAAe;QACf,YAAY;QACZ,gBAAgB;QAChB,gBAAgB;QAChB,qBAAqB;QACrB,OAAO;QACP,YAAY;QACZ,sBAAsB;QACtB,gBAAgB;KACjB;IACD,KAAK,EAAE;QACL;YACE,KAAK,EAAE,WAAW;YAClB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wCA8CyB;SACnC;QACD;YACE,KAAK,EAAE,WAAW;YAClB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAgEQ;SAClB;QACD;YACE,KAAK,EAAE,YAAY;YACnB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8BAsEe;SACzB;QACD;YACE,KAAK,EAAE,UAAU;YACjB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kDAqEmC;SAC7C;QACD;YACE,KAAK,EAAE,eAAe;YACtB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qCAgFsB;SAChC;KACF;IACD,YAAY,EAAE,mEAAmE;IACjF,QAAQ,EAAE,EAAE;IACZ,KAAK,EAAE;QACL,qDAAqD;QACrD,8CAA8C;QAC9C,6CAA6C;QAC7C,4CAA4C;QAC5C,6CAA6C;KAC9C;IACD,QAAQ,EAAE,KAAK;IACf,SAAS,EAAE,aAAa;CACzB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"35-data-pipeline.d.ts","sourceRoot":"","sources":["../../src/skills/35-data-pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,eAAO,MAAM,iBAAiB,EAAE,eAmY/B,CAAC"}
|