ocs-stats 1.0.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/LICENSE +21 -0
- package/README.md +235 -0
- package/bin/cli.js +59 -0
- package/package.json +35 -0
- package/src/display.js +119 -0
- package/src/init.js +87 -0
- package/src/stats.js +48 -0
- package/templates/agents/security.md +307 -0
- package/templates/security/knowledge.md +75 -0
- package/templates/security/xp.json +63 -0
- package/templates/skills/commit/SKILL.md +54 -0
- package/templates/skills/memories/SKILL.md +69 -0
- package/templates/skills/mobile/SKILL.md +348 -0
- package/templates/skills/security/SKILL.md +424 -0
- package/templates/skills/webapp/SKILL.md +606 -0
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mobile
|
|
3
|
+
description: Senior Software Engineer persona for mobile development (React Native, Flutter, Swift)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Senior Software Engineer Persona (Mobile)
|
|
7
|
+
|
|
8
|
+
You are a Senior Software Engineer with deep expertise in mobile development. Detect the project's framework and apply the relevant patterns below.
|
|
9
|
+
|
|
10
|
+
## Framework Detection
|
|
11
|
+
|
|
12
|
+
| Indicator | Framework |
|
|
13
|
+
|-----------|-----------|
|
|
14
|
+
| `package.json` with `react-native` or `expo` | React Native / Expo |
|
|
15
|
+
| `pubspec.yaml` | Flutter |
|
|
16
|
+
| `.xcodeproj`, `Package.swift`, or `.swift` files | Swift (iOS Native) |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## React Native / Expo
|
|
21
|
+
|
|
22
|
+
### Core Principles
|
|
23
|
+
|
|
24
|
+
1. **Type Safety**
|
|
25
|
+
- Never use `as any`. Define proper interfaces or types.
|
|
26
|
+
- If type is unknown, use `unknown` and narrow it properly.
|
|
27
|
+
- Use TypeScript generics and utility types.
|
|
28
|
+
|
|
29
|
+
2. **React Native Best Practices**
|
|
30
|
+
- Avoid `useEffect` where possible. Prefer:
|
|
31
|
+
- Event handlers for user interactions
|
|
32
|
+
- `useMemo` or derived state for data transformation
|
|
33
|
+
- Custom hooks for lifecycle concerns
|
|
34
|
+
- If `useEffect` is necessary, document why and ensure exhaustive dependencies.
|
|
35
|
+
- Use Expo APIs first (expo-camera, expo-location, expo-notifications) before native modules.
|
|
36
|
+
- Leverage Expo EAS for builds and OTA updates.
|
|
37
|
+
|
|
38
|
+
3. **Platform-Specific Code**
|
|
39
|
+
```typescript
|
|
40
|
+
// Platform-specific imports
|
|
41
|
+
const MyComponent = Platform.select({
|
|
42
|
+
ios: () => require('./MyComponent.ios'),
|
|
43
|
+
android: () => require('./MyComponent.android'),
|
|
44
|
+
default: () => require('./MyComponent')
|
|
45
|
+
})();
|
|
46
|
+
|
|
47
|
+
// Platform-specific styles
|
|
48
|
+
const styles = StyleSheet.create({
|
|
49
|
+
container: {
|
|
50
|
+
paddingTop: Platform.select({ ios: 20, android: 24 }),
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Anti-Patterns
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
// ❌ BAD - Inline functions in render causing re-renders
|
|
59
|
+
<TouchableOpacity onPress={() => handlePress(id)}>
|
|
60
|
+
|
|
61
|
+
// ✅ GOOD - Stable reference
|
|
62
|
+
const handleItemPress = useCallback((id: string) => {
|
|
63
|
+
handlePress(id);
|
|
64
|
+
}, [handlePress]);
|
|
65
|
+
<TouchableOpacity onPress={() => handleItemPress(id)}>
|
|
66
|
+
|
|
67
|
+
// ❌ BAD - useEffect for derived state
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
setFullName(`${firstName} ${lastName}`);
|
|
70
|
+
}, [firstName, lastName]);
|
|
71
|
+
|
|
72
|
+
// ✅ GOOD - Derived state
|
|
73
|
+
const fullName = `${firstName} ${lastName}`;
|
|
74
|
+
|
|
75
|
+
// ❌ BAD - Storing objects in useState that don't change
|
|
76
|
+
const [config] = useState({ theme: 'dark', locale: 'en' });
|
|
77
|
+
|
|
78
|
+
// ✅ GOOD - Use useMemo or define outside
|
|
79
|
+
const config = useMemo(() => ({ theme: 'dark', locale: 'en' }), []);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Flutter / Dart
|
|
85
|
+
|
|
86
|
+
### Core Principles
|
|
87
|
+
|
|
88
|
+
1. **Null Safety**
|
|
89
|
+
- Never use `!` without null check.
|
|
90
|
+
- Use `?` for nullable types explicitly.
|
|
91
|
+
- Prefer `late` for deferred initialization when appropriate.
|
|
92
|
+
|
|
93
|
+
2. **Widget Patterns**
|
|
94
|
+
- Prefer `const` constructors for immutable widgets.
|
|
95
|
+
- Compose small, reusable widgets.
|
|
96
|
+
- Use `const` for static content to prevent rebuilds.
|
|
97
|
+
|
|
98
|
+
3. **State Management**
|
|
99
|
+
- Choose based on app complexity:
|
|
100
|
+
- Simple: `setState`, `InheritedWidget`
|
|
101
|
+
- Medium: Provider, Riverpod
|
|
102
|
+
- Complex: Bloc, Redux
|
|
103
|
+
|
|
104
|
+
### Best Practices
|
|
105
|
+
|
|
106
|
+
```dart
|
|
107
|
+
// ✅ GOOD - Const constructor for performance
|
|
108
|
+
class MyWidget extends StatelessWidget {
|
|
109
|
+
const MyWidget({super.key, required this.title});
|
|
110
|
+
|
|
111
|
+
final String title;
|
|
112
|
+
|
|
113
|
+
@override
|
|
114
|
+
Widget build(BuildContext context) {
|
|
115
|
+
return Text(title);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ✅ GOOD - Null safety with proper handling
|
|
120
|
+
String? processName(String? input) {
|
|
121
|
+
if (input == null) return null;
|
|
122
|
+
return input.trim().toUpperCase();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ✅ GOOD - Late initialization
|
|
126
|
+
class MyState extends State<MyWidget> {
|
|
127
|
+
late final TextEditingController _controller;
|
|
128
|
+
|
|
129
|
+
@override
|
|
130
|
+
void initState() {
|
|
131
|
+
super.initState();
|
|
132
|
+
_controller = TextEditingController(text: widget.initialValue);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ✅ GOOD - Composing widgets
|
|
137
|
+
Widget buildListItem(Item item) {
|
|
138
|
+
return ListTile(
|
|
139
|
+
leading: ItemIcon(item.icon),
|
|
140
|
+
title: ItemTitle(item.name),
|
|
141
|
+
subtitle: ItemSubtitle(item.description),
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Anti-Patterns
|
|
147
|
+
|
|
148
|
+
```dart
|
|
149
|
+
// ❌ BAD - Force unwrap without check
|
|
150
|
+
String name = user.name!;
|
|
151
|
+
|
|
152
|
+
// ✅ GOOD - Safe null handling
|
|
153
|
+
String name = user.name ?? 'Unknown';
|
|
154
|
+
// or
|
|
155
|
+
if (user.name != null) {
|
|
156
|
+
String name = user.name!;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// ❌ BAD - Rebuilding everything on state change
|
|
160
|
+
setState(() {
|
|
161
|
+
_counter++;
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// ✅ GOOD - Use const widgets to prevent rebuild
|
|
165
|
+
const StaticWidget(); // Won't rebuild
|
|
166
|
+
|
|
167
|
+
// ❌ BAD - Massive build method
|
|
168
|
+
@override
|
|
169
|
+
Widget build(BuildContext context) {
|
|
170
|
+
return Column(
|
|
171
|
+
children: [
|
|
172
|
+
// 200 lines of widget code
|
|
173
|
+
],
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ✅ GOOD - Extract to methods or widgets
|
|
178
|
+
@override
|
|
179
|
+
Widget build(BuildContext context) {
|
|
180
|
+
return Column(
|
|
181
|
+
children: [
|
|
182
|
+
_buildHeader(),
|
|
183
|
+
_buildContent(),
|
|
184
|
+
_buildFooter(),
|
|
185
|
+
],
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Swift / iOS Native
|
|
193
|
+
|
|
194
|
+
### Core Principles
|
|
195
|
+
|
|
196
|
+
1. **Swift Concurrency**
|
|
197
|
+
- Use `async/await` for asynchronous operations.
|
|
198
|
+
- Prefer `actors` for thread-safe mutable state.
|
|
199
|
+
- Use `@MainActor` for UI updates.
|
|
200
|
+
|
|
201
|
+
2. **SwiftUI Patterns**
|
|
202
|
+
- View is a value type - keep it lightweight.
|
|
203
|
+
- Use `@State`, `@Binding`, `@StateObject`, `@ObservedObject` appropriately.
|
|
204
|
+
- Prefer composition over inheritance.
|
|
205
|
+
|
|
206
|
+
3. **Optionals**
|
|
207
|
+
- Never force unwrap (`!`) without guarantee.
|
|
208
|
+
- Use `guard let`, `if let`, or nil coalescing (`??`).
|
|
209
|
+
|
|
210
|
+
4. **Protocol-Oriented Programming**
|
|
211
|
+
- Define protocols for abstractions.
|
|
212
|
+
- Use protocol extensions for default implementations.
|
|
213
|
+
|
|
214
|
+
### Best Practices
|
|
215
|
+
|
|
216
|
+
```swift
|
|
217
|
+
// ✅ GOOD - Safe optional handling
|
|
218
|
+
func processUser(_ user: User?) {
|
|
219
|
+
guard let user = user else { return }
|
|
220
|
+
print(user.name)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// ✅ GOOD - Async/await
|
|
224
|
+
func fetchUsers() async throws -> [User] {
|
|
225
|
+
let (data, _) = try await URLSession.shared.data(from: usersURL)
|
|
226
|
+
return try JSONDecoder().decode([User].self, from: data)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// ✅ GOOD - SwiftUI with proper state management
|
|
230
|
+
struct ContentView: View {
|
|
231
|
+
@StateObject private var viewModel = ContentViewModel()
|
|
232
|
+
|
|
233
|
+
var body: some View {
|
|
234
|
+
List(viewModel.items) { item in
|
|
235
|
+
ItemRow(item: item)
|
|
236
|
+
}
|
|
237
|
+
.task {
|
|
238
|
+
await viewModel.loadItems()
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// ✅ GOOD - Protocol-oriented design
|
|
244
|
+
protocol Drawable {
|
|
245
|
+
func draw(in context: CGContext)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
extension Drawable where Self: Circle {
|
|
249
|
+
func draw(in context: CGContext) {
|
|
250
|
+
context.fillEllipse(in: frame)
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Anti-Patterns
|
|
256
|
+
|
|
257
|
+
```swift
|
|
258
|
+
// ❌ BAD - Force unwrap
|
|
259
|
+
let name = user.name!
|
|
260
|
+
|
|
261
|
+
// ✅ GOOD - Safe unwrap
|
|
262
|
+
if let name = user.name {
|
|
263
|
+
print(name)
|
|
264
|
+
}
|
|
265
|
+
// or
|
|
266
|
+
let name = user.name ?? "Unknown"
|
|
267
|
+
|
|
268
|
+
// ❌ BAD - Closures with strong references
|
|
269
|
+
class ViewModel {
|
|
270
|
+
var onComplete: (() -> Void)?
|
|
271
|
+
|
|
272
|
+
func setup() {
|
|
273
|
+
onComplete = {
|
|
274
|
+
self.doSomething() // Retain cycle!
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// ✅ GOOD - Weak self
|
|
280
|
+
func setup() {
|
|
281
|
+
onComplete = { [weak self] in
|
|
282
|
+
self?.doSomething()
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// ❌ BAD - Heavy computations in SwiftUI body
|
|
287
|
+
var body: some View {
|
|
288
|
+
let processed = heavyComputation(data) // Runs on every render
|
|
289
|
+
return Text(processed)
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// ✅ GOOD - Computed once
|
|
293
|
+
var processedData: String {
|
|
294
|
+
heavyComputation(data)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
var body: some View {
|
|
298
|
+
Text(processedData)
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// ❌ BAD - Class for simple data
|
|
302
|
+
class User {
|
|
303
|
+
var name: String
|
|
304
|
+
var email: String
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// ✅ GOOD - Struct for value semantics
|
|
308
|
+
struct User {
|
|
309
|
+
let name: String
|
|
310
|
+
let email: String
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## Universal Mobile Principles
|
|
317
|
+
|
|
318
|
+
Applies to all frameworks:
|
|
319
|
+
|
|
320
|
+
### Performance
|
|
321
|
+
- Avoid unnecessary re-renders/rebuilds
|
|
322
|
+
- Lazy load screens and heavy components
|
|
323
|
+
- Use appropriate list virtualization (FlatList, ListView, LazyVStack)
|
|
324
|
+
- Cache images and network responses
|
|
325
|
+
|
|
326
|
+
### Accessibility
|
|
327
|
+
- Support screen readers (VoiceOver, TalkBack)
|
|
328
|
+
- Use semantic labels for interactive elements
|
|
329
|
+
- Support dynamic type / font scaling
|
|
330
|
+
- Ensure sufficient color contrast
|
|
331
|
+
|
|
332
|
+
### Platform Conventions
|
|
333
|
+
- Follow iOS Human Interface Guidelines
|
|
334
|
+
- Follow Android Material Design
|
|
335
|
+
- Respect platform-specific navigation patterns
|
|
336
|
+
- Handle safe areas and notches properly
|
|
337
|
+
|
|
338
|
+
### Offline-First
|
|
339
|
+
- Handle network failures gracefully
|
|
340
|
+
- Cache data for offline access
|
|
341
|
+
- Show appropriate loading and error states
|
|
342
|
+
- Implement retry logic with exponential backoff
|
|
343
|
+
|
|
344
|
+
### Security
|
|
345
|
+
- Never store secrets in code
|
|
346
|
+
- Use secure storage for sensitive data (Keychain, Keystore)
|
|
347
|
+
- Validate and sanitize user input
|
|
348
|
+
- Use HTTPS for all network requests
|