@coralai/sps-cli 0.42.0 → 0.43.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.
Files changed (109) hide show
  1. package/README.md +34 -3
  2. package/dist/commands/projectInit.d.ts.map +1 -1
  3. package/dist/commands/projectInit.js +40 -53
  4. package/dist/commands/projectInit.js.map +1 -1
  5. package/dist/commands/skillCommand.d.ts +2 -0
  6. package/dist/commands/skillCommand.d.ts.map +1 -0
  7. package/dist/commands/skillCommand.js +235 -0
  8. package/dist/commands/skillCommand.js.map +1 -0
  9. package/dist/core/skillStore.d.ts +46 -0
  10. package/dist/core/skillStore.d.ts.map +1 -0
  11. package/dist/core/skillStore.js +197 -0
  12. package/dist/core/skillStore.js.map +1 -0
  13. package/dist/core/skillStore.test.d.ts +2 -0
  14. package/dist/core/skillStore.test.d.ts.map +1 -0
  15. package/dist/core/skillStore.test.js +190 -0
  16. package/dist/core/skillStore.test.js.map +1 -0
  17. package/dist/main.js +19 -17
  18. package/dist/main.js.map +1 -1
  19. package/package.json +1 -1
  20. package/skills/architecture-decision-records/SKILL.md +207 -0
  21. package/skills/backend/SKILL.md +62 -0
  22. package/skills/backend/references/api-design.md +168 -0
  23. package/skills/backend/references/caching.md +181 -0
  24. package/skills/backend/references/data-access.md +173 -0
  25. package/skills/backend/references/layering.md +181 -0
  26. package/skills/backend/references/observability.md +190 -0
  27. package/skills/backend/references/resilience.md +201 -0
  28. package/skills/backend/references/security.md +186 -0
  29. package/skills/backend-architect/SKILL.md +119 -0
  30. package/skills/code-reviewer/SKILL.md +143 -0
  31. package/skills/coding-standards/SKILL.md +60 -0
  32. package/skills/coding-standards/references/clean-code.md +258 -0
  33. package/skills/coding-standards/references/code-review.md +192 -0
  34. package/skills/coding-standards/references/commits-and-prs.md +226 -0
  35. package/skills/coding-standards/references/error-strategy.md +193 -0
  36. package/skills/coding-standards/references/naming.md +185 -0
  37. package/skills/coding-standards/references/tdd.md +171 -0
  38. package/skills/database/SKILL.md +53 -0
  39. package/skills/database/references/indexing.md +190 -0
  40. package/skills/database/references/migrations.md +199 -0
  41. package/skills/database/references/nosql.md +185 -0
  42. package/skills/database/references/queries.md +295 -0
  43. package/skills/database/references/scaling.md +203 -0
  44. package/skills/database/references/schema.md +191 -0
  45. package/skills/database-optimizer/SKILL.md +168 -0
  46. package/skills/debugging-workflow/SKILL.md +244 -0
  47. package/skills/devops/SKILL.md +55 -0
  48. package/skills/devops/references/ci-cd.md +204 -0
  49. package/skills/devops/references/containers.md +272 -0
  50. package/skills/devops/references/deploy.md +201 -0
  51. package/skills/devops/references/iac.md +252 -0
  52. package/skills/devops/references/observability.md +228 -0
  53. package/skills/devops/references/secrets.md +178 -0
  54. package/skills/devops-automator/SKILL.md +164 -0
  55. package/skills/frontend/SKILL.md +52 -0
  56. package/skills/frontend/references/accessibility.md +222 -0
  57. package/skills/frontend/references/components.md +206 -0
  58. package/skills/frontend/references/performance.md +219 -0
  59. package/skills/frontend/references/routing.md +209 -0
  60. package/skills/frontend/references/state.md +190 -0
  61. package/skills/frontend/references/testing.md +216 -0
  62. package/skills/frontend-developer/SKILL.md +115 -0
  63. package/skills/git-workflow/SKILL.md +355 -0
  64. package/skills/golang/SKILL.md +49 -0
  65. package/skills/golang/references/concurrency.md +284 -0
  66. package/skills/golang/references/errors.md +241 -0
  67. package/skills/golang/references/idioms.md +285 -0
  68. package/skills/golang/references/testing.md +238 -0
  69. package/skills/java/SKILL.md +50 -0
  70. package/skills/java/references/concurrency.md +194 -0
  71. package/skills/java/references/idioms.md +283 -0
  72. package/skills/java/references/testing.md +228 -0
  73. package/skills/kotlin/SKILL.md +47 -0
  74. package/skills/kotlin/references/coroutines.md +240 -0
  75. package/skills/kotlin/references/idioms.md +268 -0
  76. package/skills/kotlin/references/testing.md +219 -0
  77. package/skills/mobile/SKILL.md +50 -0
  78. package/skills/mobile/references/architecture.md +204 -0
  79. package/skills/mobile/references/navigation.md +158 -0
  80. package/skills/mobile/references/performance.md +152 -0
  81. package/skills/mobile/references/platform.md +166 -0
  82. package/skills/mobile/references/state-and-data.md +174 -0
  83. package/skills/python/SKILL.md +51 -0
  84. package/skills/python/THIRD_PARTY.md +14 -0
  85. package/skills/python/references/async.md +218 -0
  86. package/skills/python/references/error-handling.md +254 -0
  87. package/skills/python/references/idioms.md +279 -0
  88. package/skills/python/references/packaging.md +233 -0
  89. package/skills/python/references/testing.md +269 -0
  90. package/skills/python/references/typing.md +292 -0
  91. package/skills/qa-tester/SKILL.md +186 -0
  92. package/skills/rust/SKILL.md +50 -0
  93. package/skills/rust/references/async.md +224 -0
  94. package/skills/rust/references/errors.md +240 -0
  95. package/skills/rust/references/ownership.md +263 -0
  96. package/skills/rust/references/testing.md +274 -0
  97. package/skills/rust/references/traits.md +250 -0
  98. package/skills/security-engineer/SKILL.md +157 -0
  99. package/skills/swift/SKILL.md +48 -0
  100. package/skills/swift/references/concurrency.md +280 -0
  101. package/skills/swift/references/idioms.md +334 -0
  102. package/skills/swift/references/testing.md +229 -0
  103. package/skills/typescript/SKILL.md +51 -0
  104. package/skills/typescript/references/async.md +241 -0
  105. package/skills/typescript/references/errors.md +208 -0
  106. package/skills/typescript/references/idioms.md +246 -0
  107. package/skills/typescript/references/testing.md +225 -0
  108. package/skills/typescript/references/tooling.md +208 -0
  109. package/skills/typescript/references/types.md +259 -0
@@ -0,0 +1,152 @@
1
+ # Mobile — Performance
2
+
3
+ Startup, frame rate, memory, battery, app size.
4
+
5
+ ## Measure first
6
+
7
+ - **iOS**: Xcode Instruments — Time Profiler, Allocations, Energy Log, App Launch template.
8
+ - **Android**: Android Studio Profiler, Macrobenchmark, Perfetto, Battery Historian.
9
+ - **Cross-platform**: framework-specific profilers (React Native Flipper, Flutter DevTools).
10
+
11
+ No optimization without a profile. Anecdotes lie; flame graphs don't.
12
+
13
+ ## Startup
14
+
15
+ Cold start = process launch → first meaningful screen. Budget:
16
+ - iOS: < 400 ms to first frame (Apple's guideline).
17
+ - Android: < 5 s for cold start acceptable; < 2 s is good.
18
+
19
+ Common startup killers:
20
+ - Synchronous work in `Application` / `AppDelegate` init (SDK init, network pings).
21
+ - Excessive DI graph construction at cold start.
22
+ - Loading a huge JSON on the main thread.
23
+ - First screen fetching data sequentially.
24
+
25
+ Strategy:
26
+ 1. **Do nothing on launch** that isn't required to render the first screen.
27
+ 2. **Defer SDK init** (analytics, crash reporter) using platform idle callbacks.
28
+ 3. **Show a real UI fast** — skeleton, cached content, progressive hydration.
29
+ 4. **Parallelize first-screen data fetches.**
30
+
31
+ ## Frame rate — 60 fps / 120 fps
32
+
33
+ 16.67 ms per frame at 60 Hz; 8.33 ms at 120 Hz. A frame budget missed = visible jank.
34
+
35
+ - **Never block the UI thread** with disk, network, JSON parsing, or big computations.
36
+ - **Measure jank** with the platform tool (Choreographer on Android, Core Animation FPS on iOS).
37
+ - **Move work off-main**:
38
+ - Android: coroutines on `Dispatchers.Default` / `IO`; Compose's `LaunchedEffect`.
39
+ - iOS: `Task.detached(priority: .utility)` / async functions.
40
+ - Cross-platform: web workers, Dart isolates.
41
+
42
+ ## Lists — virtualize
43
+
44
+ Any list with > ~50 items should virtualize (render only what's visible).
45
+
46
+ - **iOS**: `UITableView` / `UICollectionView` already do; `LazyVStack` in SwiftUI; avoid mapping huge arrays into `ForEach` inside `ScrollView`.
47
+ - **Android**: `RecyclerView` / `LazyColumn` (Compose). Set `contentType` / `key` for recycling.
48
+ - **React Native**: `FlatList` / `SectionList` with `keyExtractor` and `getItemLayout`.
49
+ - **Flutter**: `ListView.builder` / `SliverList`.
50
+
51
+ Rules:
52
+ - Every row has a stable key.
53
+ - `shouldRecompose` / `areItemsTheSame` return correctly.
54
+ - Avoid inline lambdas that change identity every render.
55
+
56
+ ## Images
57
+
58
+ Biggest single memory user in typical apps.
59
+
60
+ - Use a cached image loader (Coil, Glide, SDWebImage, Kingfisher, FastImage for RN).
61
+ - Decode to the display size, not the source size. A 4000 × 3000 photo in a 300-pt avatar is a memory bomb.
62
+ - Cache policies: memory (tight), disk (generous, bounded), TTL for dynamic URLs.
63
+ - Placeholders + fade-in; avoid layout shift.
64
+
65
+ ## Memory
66
+
67
+ - Hold what you're rendering. Let the rest evict.
68
+ - Bitmap-heavy screens (photo grids, video thumbnails) need aggressive recycling.
69
+ - Watch for retain cycles (iOS) / context leaks (Android). A ViewModel holding a View, a Handler with an activity reference — standard leaks.
70
+ - Detekt / leak-detection tools: LeakCanary (Android), Instruments Leaks (iOS), profile before release.
71
+
72
+ ## Battery
73
+
74
+ Users notice battery drain. What costs most:
75
+ - **Network chatter** (small requests often > big requests rarely).
76
+ - **Wakeups** (alarms, background fetches, location).
77
+ - **Sensors** (GPS, accelerometer, BT scan) when used continuously.
78
+ - **Bad CPU loops** (unnecessary re-renders, background polling).
79
+
80
+ Rules:
81
+ - Batch network calls where you can.
82
+ - Use platform background scheduler (`WorkManager`, `BGTaskScheduler`) — they batch across apps.
83
+ - Respect Doze / Low Power Mode signals.
84
+ - Don't hold wake locks or background location without a visible reason.
85
+
86
+ ## App size
87
+
88
+ Each MB costs downloads, installs, abandonment. Rough targets:
89
+ - < 50 MB initial download is great.
90
+ - Over 100 MB, users on cellular are warned.
91
+
92
+ Tools:
93
+ - Android App Bundle splits by ABI / language / density.
94
+ - iOS: App Thinning, on-demand resources.
95
+ - Strip debug symbols in release.
96
+ - Audit deps — one chart library can add 5 MB of unused code.
97
+
98
+ ## Package size audit
99
+
100
+ Largest offenders, in order:
101
+ 1. Unstripped native libraries (x86 + arm + arm64 + armv7).
102
+ 2. Bundled fonts / images / videos.
103
+ 3. Heavy SDKs (ads, analytics) that ship more than they use.
104
+ 4. Translations (if your app ships without user-language stripping).
105
+ 5. Debug info left in release.
106
+
107
+ ## Launch / anim / transition perf
108
+
109
+ - Launch screen: show the UI immediately (Asset catalog on iOS, splash theme on Android). Don't build your own splash from a UIKit / Activity — it's slower.
110
+ - Transitions: use platform defaults; they're hardware-accelerated. Custom animations often miss frames on low-end devices.
111
+ - Prefer `transform` / `opacity` equivalents over layout-triggering properties.
112
+
113
+ ## Network
114
+
115
+ - HTTP/2 or HTTP/3 → multiplexing reduces handshake cost.
116
+ - Response compression (gzip / brotli) on.
117
+ - Cache-Control on static assets; ETag for dynamic.
118
+ - Retry with backoff on failures.
119
+ - Consider **delta** payloads for large lists (send only what changed).
120
+
121
+ ## Ahead-of-time vs JIT
122
+
123
+ - Android R8 / ProGuard: enable in release. Strips unused code and shrinks bundles.
124
+ - iOS: always AOT; no JIT. Focus on link-time optimization (`-Os`, whole-module).
125
+ - Cross-platform: Hermes (RN), Flutter AOT — verify you're in release mode.
126
+
127
+ ## Benchmarks in CI
128
+
129
+ Macrobenchmark (Android) or Instruments via XCTest (iOS) can run critical-flow timing on every merge. Fail builds on regression beyond threshold.
130
+
131
+ ```
132
+ @Test
133
+ fun startup() = benchmarkRule.measureRepeated(
134
+ packageName = PACKAGE,
135
+ metrics = listOf(StartupTimingMetric()),
136
+ ) { pressHome(); startActivityAndWait() }
137
+ ```
138
+
139
+ ## Anti-patterns
140
+
141
+ | Anti-pattern | Fix |
142
+ |---|---|
143
+ | Loading full profile on every screen | Cache; invalidate on change |
144
+ | Images served at 4K for 400 px displays | Server-side resizing or loader |
145
+ | Launch SDK initialization chain takes 2 seconds | Defer; init on first use |
146
+ | Rendering a grid without virtualization | Use the platform list |
147
+ | Polling for notifications every 10 seconds | Push / long-poll |
148
+ | JSON parse on main thread for big payloads | Background + stream |
149
+ | Keeping full Log / PDF in memory | Stream; flush |
150
+ | Shipping debug logs in release | Strip |
151
+ | Background location for features that don't need it | Request only when needed |
152
+ | Running animations during heavy scroll | Throttle or pause |
@@ -0,0 +1,166 @@
1
+ # Mobile — Platform
2
+
3
+ Permissions, notifications, background tasks, biometrics, secure storage.
4
+
5
+ ## Permissions
6
+
7
+ Request at the moment of need, not upfront.
8
+
9
+ ```
10
+ User taps "Add photo" → now request camera / library permission.
11
+ ```
12
+
13
+ Flow:
14
+ 1. Check current status.
15
+ 2. If not determined: show an in-app primer ("to attach photos we need access to…"), then prompt.
16
+ 3. If denied: show clear "open Settings" guidance; don't re-prompt (iOS won't show the sheet again anyway).
17
+
18
+ Never:
19
+ - Ask for all permissions on first launch.
20
+ - Block the app on denied permissions (degrade gracefully).
21
+ - Auto-grant — users must choose.
22
+
23
+ Required: `NSUsageDescription` (iOS) / permission declarations (Android) with accurate copy. App stores reject vague ones.
24
+
25
+ ## Sensitive permissions
26
+
27
+ | Permission | Treat as |
28
+ |---|---|
29
+ | Location (especially background) | Justify prominently, explain precisely how it's used |
30
+ | Camera / microphone | Visible indicator while active (OS usually does this) |
31
+ | Contacts / Photos / Calendar | Scoped access preferred (iOS 14+, Android 13+) |
32
+ | Notifications (iOS) | Explicit opt-in; user deciding = one chance on iOS |
33
+ | Accessibility services (Android) | High review bar; stores scrutinize |
34
+
35
+ ## Notifications
36
+
37
+ ### Local
38
+
39
+ For time / event reminders the device can schedule.
40
+
41
+ ```
42
+ schedule(id, triggerDate, contentTitle, contentBody)
43
+ ```
44
+
45
+ Rules:
46
+ - Idempotent id — rescheduling replaces.
47
+ - Cancel stale notifications on state change (task done → remove reminder).
48
+ - Respect quiet hours / Focus / DND.
49
+
50
+ ### Push
51
+
52
+ Server-driven. Flow:
53
+ 1. App requests token (APNs on iOS, FCM on Android).
54
+ 2. Token sent to server, associated with user.
55
+ 3. Server delivers payloads via APNs / FCM.
56
+
57
+ Content types:
58
+ - **Alert / default** — visible to user.
59
+ - **Silent / data-only** — wakes app to sync; no UI. Limited budget; iOS throttles.
60
+
61
+ Handle:
62
+ - Token rotation (OS may refresh; always sync to server).
63
+ - Logout: unregister token.
64
+ - Quiet / opt-out preferences server-side.
65
+
66
+ ## Background tasks
67
+
68
+ Apps don't run in the background forever. Platforms give scheduled, constrained windows.
69
+
70
+ - **iOS**: `BGAppRefreshTask`, `BGProcessingTask` via `BGTaskScheduler`. Short windows, system-decided.
71
+ - **Android**: `WorkManager` — one API, handles Doze / idle batching. Avoid `AlarmManager` for modern apps.
72
+ - **Cross-platform**: framework wrappers around the above.
73
+
74
+ Rules:
75
+ - Keep work short and idempotent.
76
+ - Don't assume a window will run at a specific time.
77
+ - Don't rely on background work for correctness — network may be off.
78
+
79
+ ## Biometrics
80
+
81
+ ```
82
+ if canAuth(.biometrics):
83
+ await authenticate(reason: "Unlock your vault")
84
+ else:
85
+ await authenticate(.passcode) // fallback
86
+ ```
87
+
88
+ - iOS: `LocalAuthentication` / `LAContext`.
89
+ - Android: `BiometricPrompt`.
90
+
91
+ Never store actual biometric data. Use it to gate access to a key in Keychain / Keystore.
92
+
93
+ ## Secure storage
94
+
95
+ | Need | Store |
96
+ |---|---|
97
+ | API tokens, refresh tokens | Keychain (iOS) / EncryptedSharedPreferences / DataStore with a master key (Android) |
98
+ | Encryption keys | Keychain / Keystore, hardware-backed where available |
99
+ | User preferences (non-sensitive) | UserDefaults / DataStore |
100
+ | Caches | App sandbox directory; wipe on logout |
101
+
102
+ Never:
103
+ - Tokens in `UserDefaults` / `SharedPreferences`.
104
+ - Plain-text credentials anywhere.
105
+ - Logging full tokens (even at DEBUG).
106
+
107
+ ## Network security
108
+
109
+ - HTTPS with modern TLS (1.2 minimum, 1.3 preferred).
110
+ - **ATS** on iOS — use default settings; exceptions require justification.
111
+ - **Network Security Config** on Android — restrict cleartext.
112
+ - **Certificate pinning** for high-value endpoints. Pin the intermediate or leaf; plan the rotation.
113
+
114
+ ## App Transport / Deep Link security
115
+
116
+ - Validate deep-link parameters; treat them as user input.
117
+ - Never execute code based on query string (e.g., "open this URL in WebView" without allow-list).
118
+ - For login-via-deep-link, verify signature; intermediaries may tamper.
119
+
120
+ ## Web views
121
+
122
+ Minimize them. When unavoidable:
123
+ - Use `WKWebView` (iOS) / `WebView` with hardened settings (Android).
124
+ - Disable `allowFileAccess`, `javascriptEnabled` unless required.
125
+ - Never inject tokens into URLs loaded in web views.
126
+
127
+ For OAuth / in-app browser tabs (SFSafariViewController / Chrome Custom Tabs) — safer than a generic WebView because cookies and saved passwords work.
128
+
129
+ ## Hardware surveys
130
+
131
+ When using camera / sensors / Bluetooth:
132
+ - Check availability (`AVCaptureDevice`, hardware feature on Android).
133
+ - Fail gracefully on missing hardware.
134
+ - Release resources on background / pause.
135
+ - Don't leave LEDs on or Bluetooth scanning when the feature is closed.
136
+
137
+ ## Accessibility at the platform level
138
+
139
+ - iOS: VoiceOver, Dynamic Type, Reduce Motion, Bold Text, Smart Invert.
140
+ - Android: TalkBack, font scale, color correction, reduce animations.
141
+
142
+ Use the platform's semantic accessibility APIs, not custom text-to-speech.
143
+
144
+ Test at 200% font scale. Layout should expand gracefully, not truncate.
145
+
146
+ ## Crash reporting
147
+
148
+ - Firebase Crashlytics, Sentry, BugSnag, custom — pick one.
149
+ - Capture: stack trace, device, OS version, app version, user id (hashed or opt-in).
150
+ - Log breadcrumbs — screen views, key user actions — to reconstruct what happened.
151
+ - De-symbolicate iOS crashes with dSYMs uploaded in CI. Android: ProGuard mapping files.
152
+
153
+ ## Anti-patterns
154
+
155
+ | Anti-pattern | Fix |
156
+ |---|---|
157
+ | Requesting all permissions upfront | Ask at point of need |
158
+ | Tokens in UserDefaults / SharedPreferences | Keychain / Keystore |
159
+ | Background location without clear benefit | Foreground only |
160
+ | Polling in the background for "real-time" | Push notifications / WebSockets (when foreground) |
161
+ | Running as foreground service to bypass Doze | Violates Play Store policy |
162
+ | Opening external URLs in an in-app WebView with cookies | Use in-app browser tab |
163
+ | Using the older / deprecated `AlarmManager` for everything | WorkManager on modern Android |
164
+ | Stripping ATS / NSC to "make it easier" | Fix the server; don't open cleartext in prod |
165
+ | Hard-coded production API keys | Environment-specific config; rotate on leak |
166
+ | Silent push used for analytics (abuses the privilege) | Real notification or in-app event |
@@ -0,0 +1,174 @@
1
+ # Mobile — State & Data
2
+
3
+ Local store, sync, offline-first, optimistic updates, reactive streams.
4
+
5
+ ## Offline-first
6
+
7
+ Network is the slow, unreliable layer. Design the app so the local store is the fast path; the network syncs in the background.
8
+
9
+ ```
10
+ UI ──reads──▶ Local Store ◀──writes sync── API
11
+ ──writes──▶ Local Store + Outbox ──drain──▶ API
12
+ ```
13
+
14
+ Benefits:
15
+ - Cold start without network → user still sees cached content.
16
+ - Actions feel instant (optimistic + outbox).
17
+ - Seamless reconnection; app doesn't die on Wi-Fi flip.
18
+
19
+ ## Local storage choices
20
+
21
+ | Store | Platform / Cross | Shape |
22
+ |---|---|---|
23
+ | SQLite (direct) | All | Relational, battle-tested |
24
+ | Room | Android | SQLite ORM; compile-time query checking |
25
+ | Core Data / SwiftData | iOS | Object graph |
26
+ | Realm | Cross | Object DB, live objects |
27
+ | SQLDelight | KMP / cross | SQL-first, multiplatform |
28
+ | MMKV / DataStore | Key-value | Simple prefs, fast, typed |
29
+ | Keychain / Keystore | All | Secrets |
30
+
31
+ Rule: one primary store per domain. Mixing Room + Realm + a JSON cache for the same data creates reconciliation hell.
32
+
33
+ ## Cache + network reconcile
34
+
35
+ ### Stale-while-revalidate
36
+
37
+ Return cached data immediately; refresh in the background.
38
+
39
+ ```
40
+ suspend fun getUser(id: String): Flow<User> = flow {
41
+ emit(cache.get(id)) // instant
42
+ try {
43
+ val fresh = api.getUser(id)
44
+ cache.put(id, fresh)
45
+ emit(fresh) // update UI
46
+ } catch (_: IOException) {
47
+ // offline; keep showing cached
48
+ }
49
+ }
50
+ ```
51
+
52
+ ### Freshness policy
53
+
54
+ Some data is OK to show even if hours old (product catalog); some must be current (bank balance). Per-type policy:
55
+
56
+ ```
57
+ policy[User] = staleAfter(5.minutes)
58
+ policy[ProductList] = staleAfter(24.hours)
59
+ policy[Balance] = alwaysRefresh
60
+ ```
61
+
62
+ ## Optimistic updates + outbox
63
+
64
+ For user-driven writes, show the expected result immediately; queue the server call; reconcile.
65
+
66
+ ```
67
+ place_order(order):
68
+ local.insert(order.copy(status=PENDING))
69
+ outbox.enqueue(PostOrder(order.id))
70
+ return order.id # UI navigates away instantly
71
+ ```
72
+
73
+ The outbox worker:
74
+ 1. Reads next job.
75
+ 2. Calls the server (with retry + backoff).
76
+ 3. On success: update local row (`status=CONFIRMED`), remove job.
77
+ 4. On permanent failure: mark local row (`status=FAILED`), notify user, drop job.
78
+
79
+ Conflict strategy when the server returns a different truth (e.g., order replaced due to out-of-stock): domain decides — replace, merge, prompt user.
80
+
81
+ ## Queue vs. sync protocol
82
+
83
+ Simple apps: an outbox table with next-id, retry count, last-error. Good enough.
84
+
85
+ Complex sync (collaborative editing, multi-device): use a sync framework (CRDTs, Yjs, Automerge, Firebase, CouchDB). Implementing one by hand is a trap.
86
+
87
+ ## Reactive streams everywhere
88
+
89
+ Mobile UIs love reactivity because the underlying data changes often.
90
+
91
+ | Tech | Stream type |
92
+ |---|---|
93
+ | Kotlin | `Flow`, `StateFlow`, `SharedFlow` |
94
+ | Swift (Apple) | `Publisher` (Combine), `AsyncStream`, `Observable` |
95
+ | RxJava / RxSwift | `Observable`, `Flowable` |
96
+ | React Native | Hooks + state libs |
97
+
98
+ Your repository exposes a stream. The ViewModel transforms. The view collects.
99
+
100
+ ```
101
+ // Kotlin
102
+ val user: StateFlow<User?> = userRepo.observe(id)
103
+ .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), null)
104
+ ```
105
+
106
+ `WhileSubscribed(5_000)`: keeps the upstream alive 5s after the last subscriber — survives rotation without a cold re-fetch.
107
+
108
+ ## Pagination
109
+
110
+ Two patterns:
111
+
112
+ ### Offset / page
113
+
114
+ Simple but breaks when rows are inserted during paging. OK for static lists.
115
+
116
+ ### Cursor / keyset
117
+
118
+ Opaque cursor that points to the last-seen item. Stable across inserts.
119
+
120
+ ```
121
+ interface OrderApi {
122
+ suspend fun list(cursor: String?, limit: Int): Page<Order>
123
+ }
124
+
125
+ data class Page<T>(val data: List<T>, val nextCursor: String?)
126
+ ```
127
+
128
+ Platform paging libs (Jetpack Paging, TCA Pagination) handle prefetch, retry, error states. Use them; rolling your own is a maintenance burden.
129
+
130
+ ## Forms & input
131
+
132
+ - **Draft persistence**: save form input to local store keyed by form id. Survive process death.
133
+ - **Validation**: same schema on client and server (share via contract or mirror carefully).
134
+ - **Submit**: optimistic + outbox if idempotent; otherwise show submitting state.
135
+
136
+ ## Images
137
+
138
+ The single biggest memory user and jank source in mobile.
139
+
140
+ - Use the platform image loader (Coil / Glide on Android, SDWebImage / Kingfisher on iOS).
141
+ - Resize to the display size **on the server** (API returns `url?w=400`) or via the loader.
142
+ - Cache aggressively; size the cache (e.g. 100 MB disk, 50 MB memory).
143
+ - Placeholders + cross-fade; never show a flash of broken image.
144
+
145
+ ## Real-time updates
146
+
147
+ - **Polling**: simple, works offline, battery-expensive. OK for low-urgency data.
148
+ - **WebSockets / SSE**: real-time, drains battery if poorly scoped. Tear down in background.
149
+ - **Push notifications**: for out-of-app updates. Use silent push to wake and sync.
150
+
151
+ Rule: subscribe only when the user is looking. Unsubscribe on background / detached views.
152
+
153
+ ## Data security
154
+
155
+ See `security.md` for the big picture. Quick must-dos:
156
+
157
+ - Tokens / secrets → Keychain (iOS) or EncryptedSharedPreferences / Keystore (Android).
158
+ - Never log full tokens.
159
+ - HTTPS only. Pin certificates for critical endpoints where your threat model warrants.
160
+ - Wipe sensitive caches on logout.
161
+
162
+ ## Anti-patterns
163
+
164
+ | Anti-pattern | Fix |
165
+ |---|---|
166
+ | Fetching on every screen entry | Cache + observe; fetch only when stale |
167
+ | Syncing all data up-front on login | Lazy load; fetch on demand |
168
+ | Outbox without retry / backoff | Loop; drain with exponential backoff |
169
+ | Showing "please wait, syncing…" for every write | Optimistic + outbox |
170
+ | Global mutable store for server data | Repository + reactive stream |
171
+ | Ignoring background / killed state | Persist enough state to resume |
172
+ | Unbounded memory caches | Set a size cap with LRU eviction |
173
+ | Network-only fallback for offline | Degrade: cached data + "offline" banner |
174
+ | Duplicate local schemas (Room + SwiftData with different shapes on same domain) | One domain model; platform stores map to it |
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: python
3
+ description: Python language skill — idioms, type hints, error handling, testing, async, packaging. Language-focused. Combine with end skills (`backend`, `frontend`, `mobile`) for architecture, and with persona skills (`backend-architect`, `code-reviewer`) for mindset.
4
+ origin: ecc-fork (https://github.com/affaan-m/everything-claude-code, MIT)
5
+ ---
6
+
7
+ # Python
8
+
9
+ Pythonic idioms, typing, error handling, async, testing, packaging. **Language-focused only**. Architecture decisions belong to end skills (`backend`, `frontend`, `mobile`); general principles (TDD cycle, "specific exceptions only", "tests before code") live in `coding-standards`.
10
+
11
+ ## When to load
12
+
13
+ - Task is a Python project (primary language)
14
+ - Reviewing Python code
15
+ - Setting up Python project structure, packaging, or tests
16
+ - Writing Python-specific logic (generators, decorators, context managers, type hints, async)
17
+
18
+ ## Core principles (The Zen of Python, abridged)
19
+
20
+ 1. **Readability counts** — clear > clever
21
+ 2. **Explicit over implicit** — no hidden side effects
22
+ 3. **EAFP** (Easier to Ask Forgiveness Than Permission) — prefer `try/except` over pre-checks
23
+ 4. **Type hints on public APIs** — modern 3.9+ syntax (`list[str]` not `List[str]`); 3.12+ PEP 695 where available
24
+ 5. **Immutable defaults** — never `def f(x=[])`; use `None` + `x or []` or `frozenset` / `tuple`
25
+ 6. **Pathlib over os.path** — modern filesystem access
26
+ 7. **f-strings** over `.format()` / `%` formatting
27
+ 8. **`pyproject.toml` only** — no `setup.py`, no `requirements.txt` for libraries
28
+
29
+ ## How to use references
30
+
31
+ Load detailed references on demand based on the task:
32
+
33
+ | Reference | When to load |
34
+ |---|---|
35
+ | [`references/idioms.md`](references/idioms.md) | Core language idioms: EAFP, comprehensions, generators, decorators, context managers, match/case, walrus |
36
+ | [`references/typing.md`](references/typing.md) | Type hints, generics (PEP 695), protocols, type aliases, `Self`, `@override`, `ParamSpec` |
37
+ | [`references/error-handling.md`](references/error-handling.md) | Exception hierarchy, chaining, custom exceptions, exception groups / `except*` |
38
+ | [`references/async.md`](references/async.md) | `asyncio`, `TaskGroup`, timeouts, cancellation, offloading blocking code |
39
+ | [`references/testing.md`](references/testing.md) | pytest, fixtures, parametrization, mocking, coverage, `hypothesis` |
40
+ | [`references/packaging.md`](references/packaging.md) | `pyproject.toml`, `uv`, `venv`, project layout, publishing |
41
+
42
+ ## Forbidden patterns (auto-reject)
43
+
44
+ - Mutable default arguments (`def f(x=[])`) — use `None` sentinel
45
+ - `except:` without exception type — always name it
46
+ - `import *` — explicit imports only
47
+ - `time.sleep()` / blocking calls inside `async def` — use `await asyncio.sleep()` or `asyncio.to_thread`
48
+ - Swallowing `asyncio.CancelledError` without re-raising
49
+ - `setup.py` in new projects — use `pyproject.toml`
50
+ - Committing `.venv/` or mixing envs with system Python
51
+ - Dynamic typing in public APIs without type hints
@@ -0,0 +1,14 @@
1
+ # Third-Party Attribution
2
+
3
+ This skill integrates content from:
4
+
5
+ ## everything-claude-code (Affaan Mustafa)
6
+
7
+ - URL: https://github.com/affaan-m/everything-claude-code
8
+ - License: MIT
9
+ - Files used:
10
+ - `skills/python-patterns/SKILL.md` → split into `references/idioms.md`, `references/typing.md`, `references/error-handling.md`
11
+ - `skills/python-testing/SKILL.md` → `references/testing.md`
12
+ - Adaptation: content restructured into multiple reference files (thin SKILL.md entry + topic-specific references), some sections condensed, Pythonic/language-neutral line drawn (language-specific content stays here, architecture moves to `backend` / `frontend` skills).
13
+
14
+ The MIT license notice is preserved in [LICENSE-MIT-everything-claude-code](https://github.com/affaan-m/everything-claude-code/blob/main/LICENSE).