reis-mobile 0.3.5

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 (105) hide show
  1. package/.claude-plugin/marketplace.json +24 -0
  2. package/.claude-plugin/plugin.json +12 -0
  3. package/CHANGELOG.md +103 -0
  4. package/LICENSE +21 -0
  5. package/README.md +631 -0
  6. package/THIRD_PARTY_NOTICES.md +105 -0
  7. package/agents/flutter-architect.md +92 -0
  8. package/agents/flutter-performance-engineer.md +103 -0
  9. package/agents/flutter-test-engineer.md +100 -0
  10. package/agents/lead-mobile.md +107 -0
  11. package/agents/mobile-code-reviewer.md +66 -0
  12. package/agents/mobile-staff-engineer.md +85 -0
  13. package/agents/plugin-native-expert.md +97 -0
  14. package/bin/reis-mobile.mjs +256 -0
  15. package/commands/debate.md +135 -0
  16. package/commands/doctor.md +23 -0
  17. package/commands/reis-mobile.md +50 -0
  18. package/commands/review.md +53 -0
  19. package/core/config/language.mjs +83 -0
  20. package/core/context/context-engine.mjs +113 -0
  21. package/core/detection/project-probe.mjs +104 -0
  22. package/core/detection/stack-detector.mjs +204 -0
  23. package/core/diagnostics/doctor.mjs +181 -0
  24. package/core/install/claude-plugin.mjs +76 -0
  25. package/core/paths.mjs +4 -0
  26. package/core/registry/frontmatter.mjs +81 -0
  27. package/core/registry/registry.mjs +140 -0
  28. package/core/router/intent-detector.mjs +75 -0
  29. package/core/router/intents.mjs +91 -0
  30. package/core/router/router.mjs +83 -0
  31. package/core/security/redact.mjs +24 -0
  32. package/package.json +35 -0
  33. package/skills/architecture-feature-first/SKILL.md +116 -0
  34. package/skills/bloc/SKILL.md +354 -0
  35. package/skills/code-review/SKILL.md +89 -0
  36. package/skills/dart-3-updates/SKILL.md +223 -0
  37. package/skills/dart-add-unit-test/SKILL.md +126 -0
  38. package/skills/dart-collect-coverage/SKILL.md +145 -0
  39. package/skills/dart-fix-runtime-errors/SKILL.md +170 -0
  40. package/skills/dart-generate-test-mocks/SKILL.md +159 -0
  41. package/skills/dart-migrate-to-checks-package/SKILL.md +532 -0
  42. package/skills/dart-resolve-package-conflicts/SKILL.md +120 -0
  43. package/skills/dart-run-static-analysis/SKILL.md +108 -0
  44. package/skills/dart-use-pattern-matching/SKILL.md +240 -0
  45. package/skills/dart-use-pattern-matching/examples/json_patterns.dart +85 -0
  46. package/skills/detect-mobile-stack/SKILL.md +33 -0
  47. package/skills/effective-dart/SKILL.md +187 -0
  48. package/skills/firebase-ai/SKILL.md +93 -0
  49. package/skills/firebase-analytics/SKILL.md +129 -0
  50. package/skills/firebase-app-check/SKILL.md +124 -0
  51. package/skills/firebase-auth/SKILL.md +224 -0
  52. package/skills/firebase-cloud-firestore/SKILL.md +165 -0
  53. package/skills/firebase-cloud-functions/SKILL.md +148 -0
  54. package/skills/firebase-crashlytics/SKILL.md +182 -0
  55. package/skills/firebase-data-connect/SKILL.md +80 -0
  56. package/skills/firebase-database/SKILL.md +224 -0
  57. package/skills/firebase-in-app-messaging/SKILL.md +111 -0
  58. package/skills/firebase-messaging/SKILL.md +201 -0
  59. package/skills/firebase-remote-config/SKILL.md +131 -0
  60. package/skills/firebase-storage/SKILL.md +158 -0
  61. package/skills/flutter-add-integration-test/SKILL.md +167 -0
  62. package/skills/flutter-add-widget-preview/SKILL.md +149 -0
  63. package/skills/flutter-add-widget-test/SKILL.md +158 -0
  64. package/skills/flutter-adding-home-screen-widgets/SKILL.md +205 -0
  65. package/skills/flutter-animating-apps/SKILL.md +185 -0
  66. package/skills/flutter-app-architecture/SKILL.md +80 -0
  67. package/skills/flutter-apply-architecture-best-practices/SKILL.md +166 -0
  68. package/skills/flutter-build-responsive-layout/SKILL.md +143 -0
  69. package/skills/flutter-building-forms/SKILL.md +125 -0
  70. package/skills/flutter-building-layouts/SKILL.md +131 -0
  71. package/skills/flutter-building-plugins/SKILL.md +209 -0
  72. package/skills/flutter-caching-data/SKILL.md +171 -0
  73. package/skills/flutter-change-notifier/SKILL.md +138 -0
  74. package/skills/flutter-embedding-native-views/SKILL.md +200 -0
  75. package/skills/flutter-errors/SKILL.md +126 -0
  76. package/skills/flutter-fix-layout-issues/SKILL.md +134 -0
  77. package/skills/flutter-handling-concurrency/SKILL.md +182 -0
  78. package/skills/flutter-implement-json-serialization/SKILL.md +157 -0
  79. package/skills/flutter-improving-accessibility/SKILL.md +113 -0
  80. package/skills/flutter-interoperating-with-native-apis/SKILL.md +130 -0
  81. package/skills/flutter-login-usecase/SKILL.md +38 -0
  82. package/skills/flutter-managing-state/SKILL.md +206 -0
  83. package/skills/flutter-project-audit/SKILL.md +66 -0
  84. package/skills/flutter-reducing-app-size/SKILL.md +103 -0
  85. package/skills/flutter-secure-token-store/SKILL.md +35 -0
  86. package/skills/flutter-setting-up-on-macos/SKILL.md +78 -0
  87. package/skills/flutter-setup-declarative-routing/SKILL.md +259 -0
  88. package/skills/flutter-setup-localization/SKILL.md +214 -0
  89. package/skills/flutter-theming-apps/SKILL.md +163 -0
  90. package/skills/flutter-use-http-package/SKILL.md +178 -0
  91. package/skills/flutter-widget-review/SKILL.md +54 -0
  92. package/skills/flutter-working-with-databases/SKILL.md +203 -0
  93. package/skills/flutterfire-configure/SKILL.md +143 -0
  94. package/skills/mobile-security-audit/SKILL.md +101 -0
  95. package/skills/mockito/SKILL.md +149 -0
  96. package/skills/mocktail/SKILL.md +122 -0
  97. package/skills/patrol-e2e-testing/SKILL.md +224 -0
  98. package/skills/provider/SKILL.md +139 -0
  99. package/skills/riverpod/SKILL.md +246 -0
  100. package/skills/testing/SKILL.md +50 -0
  101. package/stacks/android/stack.json +8 -0
  102. package/stacks/flutter/stack.json +8 -0
  103. package/stacks/ios/stack.json +8 -0
  104. package/stacks/kotlin-multiplatform/stack.json +8 -0
  105. package/stacks/react-native/stack.json +8 -0
@@ -0,0 +1,246 @@
1
+ ---
2
+ name: riverpod
3
+ description: Uses Riverpod for state management in Flutter/Dart. Use when setting up providers, combining requests, managing state disposal, passing arguments, performing side effects, testing providers, or applying Riverpod best practices.
4
+ routing: manual
5
+ stacks: [flutter]
6
+ source: https://github.com/evanca/flutter-ai-rules
7
+ license: MIT
8
+ ---
9
+
10
+ # Riverpod Skill
11
+
12
+ This skill defines how to correctly use Riverpod for state management in Flutter and Dart applications.
13
+
14
+ ---
15
+
16
+ ## 1. Setup
17
+
18
+ ```dart
19
+ void main() {
20
+ runApp(const ProviderScope(child: MyApp()));
21
+ }
22
+ ```
23
+
24
+ - Wrap your app with `ProviderScope` directly in `runApp` — never inside `MyApp`.
25
+ - Install and use `riverpod_lint` to enable IDE refactoring and enforce best practices.
26
+
27
+ ---
28
+
29
+ ## 2. Defining Providers
30
+
31
+ ```dart
32
+ // Functional provider (codegen)
33
+ @riverpod
34
+ int example(Ref ref) => 0;
35
+
36
+ // FutureProvider (codegen)
37
+ @riverpod
38
+ Future<List<Todo>> todos(Ref ref) async {
39
+ return ref.watch(repositoryProvider).fetchTodos();
40
+ }
41
+
42
+ // Notifier (codegen)
43
+ @riverpod
44
+ class TodosNotifier extends _$TodosNotifier {
45
+ @override
46
+ Future<List<Todo>> build() async {
47
+ return ref.watch(repositoryProvider).fetchTodos();
48
+ }
49
+
50
+ Future<void> addTodo(Todo todo) async { ... }
51
+ }
52
+ ```
53
+
54
+ - Define all providers as **`final` top-level variables**.
55
+ - Use `Provider`, `FutureProvider`, or `StreamProvider` based on the return type.
56
+ - Use `ConsumerWidget` or `ConsumerStatefulWidget` instead of `StatelessWidget`/`StatefulWidget` when accessing providers.
57
+
58
+ ---
59
+
60
+ ## 3. Using Ref
61
+
62
+ | Method | Use for |
63
+ |---|---|
64
+ | `ref.watch` | Reactively listen — rebuilds when value changes. Use during build phase only. |
65
+ | `ref.read` | One-time access — use in callbacks/Notifier methods, not in build. |
66
+ | `ref.listen` | Imperative subscription — prefer `ref.watch` where possible. |
67
+ | `ref.onDispose` | Cleanup when provider state is destroyed. |
68
+
69
+ ```dart
70
+ // In a widget
71
+ class MyWidget extends ConsumerWidget {
72
+ @override
73
+ Widget build(BuildContext context, WidgetRef ref) {
74
+ final value = ref.watch(myProvider);
75
+ return Text('$value');
76
+ }
77
+ }
78
+
79
+ // Cleanup in a provider
80
+ final provider = StreamProvider<int>((ref) {
81
+ final controller = StreamController<int>();
82
+ ref.onDispose(controller.close);
83
+ return controller.stream;
84
+ });
85
+ ```
86
+
87
+ - **Never** call `ref.watch` inside callbacks, listeners, or Notifier methods.
88
+ - Use `ref.read(yourNotifierProvider.notifier).method()` to call Notifier methods from the UI.
89
+ - Check `context.mounted` before using `ref` after an `await` in async callbacks.
90
+
91
+ ---
92
+
93
+ ## 4. Combining Providers
94
+
95
+ ```dart
96
+ @riverpod
97
+ Future<String> userGreeting(Ref ref) async {
98
+ final user = await ref.watch(userProvider.future);
99
+ return 'Hello, ${user.name}!';
100
+ }
101
+ ```
102
+
103
+ - Use `ref.watch(asyncProvider.future)` to await an async provider's resolved value.
104
+ - Providers only execute once and cache the result — multiple widgets listening to the same provider share one computation.
105
+
106
+ ---
107
+
108
+ ## 5. Passing Arguments (Families)
109
+
110
+ ```dart
111
+ @riverpod
112
+ Future<Todo> todo(Ref ref, String id) async {
113
+ return ref.watch(repositoryProvider).fetchTodo(id);
114
+ }
115
+
116
+ // Usage
117
+ final todo = ref.watch(todoProvider('some-id'));
118
+ ```
119
+
120
+ - Always enable `autoDispose` for parameterized providers to prevent memory leaks.
121
+ - Use `Dart 3 records` or code generation for multiple parameters — they naturally override `==`.
122
+ - Avoid passing plain `List` or `Map` as parameters (no `==` override); use `const` collections, records, or classes with proper equality.
123
+ - Use the `provider_parameters` lint rule from `riverpod_lint` to catch equality mistakes.
124
+
125
+ ---
126
+
127
+ ## 6. Auto Dispose & State Lifecycle
128
+
129
+ - With codegen: state is **destroyed by default** when no longer listened to. Opt out with `keepAlive: true`.
130
+ - Without codegen: state is **kept alive by default**. Use `.autoDispose` to enable disposal.
131
+ - State is always destroyed when a provider is recomputed.
132
+
133
+ ```dart
134
+ // keepAlive with timer
135
+ ref.onCancel(() {
136
+ final link = ref.keepAlive();
137
+ Timer(const Duration(minutes: 5), link.close);
138
+ });
139
+ ```
140
+
141
+ - Use `ref.onDispose` for cleanup; do not trigger side effects or modify providers inside it.
142
+ - Use `ref.invalidate(provider)` to force destruction; use `ref.invalidateSelf()` from within the provider.
143
+ - Use `ref.refresh(provider)` to invalidate and immediately read the new value — always use the return value.
144
+
145
+ ---
146
+
147
+ ## 7. Eager Initialization
148
+
149
+ Providers are **lazy** by default. To eagerly initialize:
150
+
151
+ ```dart
152
+ // In MyApp or a dedicated widget under ProviderScope:
153
+ Consumer(
154
+ builder: (context, ref, _) {
155
+ ref.watch(myEagerProvider); // forces initialization
156
+ return const MyApp();
157
+ },
158
+ )
159
+ ```
160
+
161
+ - Place eager initialization in a public widget (not `main()`) for consistent test behavior.
162
+ - Use `AsyncValue.requireValue` to read data directly and throw clearly if not ready.
163
+
164
+ ---
165
+
166
+ ## 8. Performing Side Effects
167
+
168
+ ```dart
169
+ @riverpod
170
+ class TodosNotifier extends _$TodosNotifier {
171
+ Future<void> addTodo(Todo todo) async {
172
+ state = const AsyncLoading();
173
+ state = await AsyncValue.guard(() async {
174
+ await ref.read(repositoryProvider).addTodo(todo);
175
+ return [...?state.value, todo];
176
+ });
177
+ }
178
+ }
179
+
180
+ // In UI:
181
+ ElevatedButton(
182
+ onPressed: () => ref.read(todosNotifierProvider.notifier).addTodo(todo),
183
+ child: const Text('Add'),
184
+ )
185
+ ```
186
+
187
+ - Use `ref.read` (not `ref.watch`) in event handlers.
188
+ - After a side effect, update state by: setting it directly, calling `ref.invalidateSelf()`, or manually updating the cache.
189
+ - Always handle loading and error states in the UI.
190
+ - Do not perform side effects in provider constructors or build methods.
191
+
192
+ ---
193
+
194
+ ## 9. Provider Observers
195
+
196
+ ```dart
197
+ class MyObserver extends ProviderObserver {
198
+ @override
199
+ void didUpdateProvider(ProviderObserverContext context, Object? previousValue, Object? newValue) {
200
+ print('[${context.provider}] updated: $previousValue → $newValue');
201
+ }
202
+
203
+ @override
204
+ void providerDidFail(ProviderObserverContext context, Object error, StackTrace stackTrace) {
205
+ // Report to error service
206
+ }
207
+ }
208
+
209
+ runApp(ProviderScope(observers: [MyObserver()], child: MyApp()));
210
+ ```
211
+
212
+ ---
213
+
214
+ ## 10. Testing
215
+
216
+ ```dart
217
+ // Unit test
218
+ final container = ProviderContainer(
219
+ overrides: [repositoryProvider.overrideWith((_) => FakeRepository())],
220
+ );
221
+ addTearDown(container.dispose);
222
+
223
+ expect(await container.read(todosProvider.future), isNotEmpty);
224
+
225
+ // Widget test
226
+ await tester.pumpWidget(
227
+ ProviderScope(
228
+ overrides: [repositoryProvider.overrideWith((_) => FakeRepository())],
229
+ child: const MyApp(),
230
+ ),
231
+ );
232
+ ```
233
+
234
+ - Create a **new** `ProviderContainer` or `ProviderScope` for each test — never share state between tests.
235
+ - Use `container.listen` over `container.read` for `autoDispose` providers to keep state alive during the test.
236
+ - Use `overrides` to inject mocks or fakes.
237
+ - Prefer mocking **dependencies** (repositories) rather than Notifiers directly.
238
+ - If you must mock a Notifier, **subclass** the original — don't use `implements` or `with Mock`.
239
+ - Place Notifier mocks in the same file as the Notifier if using code generation.
240
+ - Obtain the container in widget tests with `ProviderScope.containerOf(tester.element(...))`.
241
+
242
+ ---
243
+
244
+ ## References
245
+
246
+ - [Riverpod GitHub Repository](https://github.com/rrousselGit/riverpod)
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: testing
3
+ description: Writes and reviews Flutter/Dart tests. Use when writing unit tests, widget tests, or reviewing existing tests for correctness, structure, and naming conventions.
4
+ intents: [test]
5
+ stacks: [flutter]
6
+ source: https://github.com/evanca/flutter-ai-rules
7
+ license: MIT
8
+ ---
9
+
10
+ # Testing Skill
11
+
12
+ This skill defines how to write effective, meaningful Flutter and Dart tests.
13
+
14
+ ---
15
+
16
+ ## 1. Test Validity
17
+
18
+ Before writing or accepting a test, ask:
19
+
20
+ > **"Can this test actually fail if the real code is broken?"**
21
+
22
+ - Avoid tests that only confirm mocked/fake behavior that doesn't reflect real logic.
23
+ - Avoid tests that confirm behavior guaranteed by the language, the standard library, or trivially obvious code that cannot fail unless the environment is broken.
24
+ - Every test should be capable of catching a real regression.
25
+
26
+ ---
27
+
28
+ ## 2. Structure
29
+
30
+ Always use `group()` in test files — even when there is only one test. Name the group after the **class under test**:
31
+
32
+ ```dart
33
+ group('Counter', () {
34
+ test('value should start at 0', () {
35
+ final counter = Counter();
36
+ expect(counter.value, 0);
37
+ });
38
+ });
39
+ ```
40
+
41
+ ---
42
+
43
+ ## 3. Naming
44
+
45
+ Name test cases using **"should"** to clearly describe the expected behavior:
46
+
47
+ ```dart
48
+ test('should emit updated list when item is added', () { ... });
49
+ test('should throw ArgumentError when input is negative', () { ... });
50
+ ```
@@ -0,0 +1,8 @@
1
+ {
2
+ "id": "android",
3
+ "name": "Android (native)",
4
+ "languages": ["kotlin", "java"],
5
+ "platforms": ["android"],
6
+ "markers": ["settings.gradle(.kts)", "build.gradle(.kts) with com.android.application", "AndroidManifest.xml"],
7
+ "toolchain": ["java", "android-sdk"]
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "id": "flutter",
3
+ "name": "Flutter",
4
+ "languages": ["dart", "kotlin", "java", "swift", "objective-c"],
5
+ "platforms": ["android", "ios", "web", "macos", "linux", "windows"],
6
+ "markers": ["pubspec.yaml (sdk: flutter)", "lib/**/*.dart"],
7
+ "toolchain": ["flutter", "dart", "java", "android-sdk", "xcode", "cocoapods"]
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "id": "ios",
3
+ "name": "iOS (native)",
4
+ "languages": ["swift", "objective-c"],
5
+ "platforms": ["ios"],
6
+ "markers": ["*.xcodeproj", "*.xcworkspace", "Podfile", "Package.swift with .iOS platform"],
7
+ "toolchain": ["xcode", "swift", "cocoapods"]
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "id": "kotlin-multiplatform",
3
+ "name": "Kotlin Multiplatform",
4
+ "languages": ["kotlin", "swift"],
5
+ "platforms": ["android", "ios", "desktop", "web"],
6
+ "markers": ["build.gradle.kts applying kotlin(\"multiplatform\")"],
7
+ "toolchain": ["java", "android-sdk", "xcode"]
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "id": "react-native",
3
+ "name": "React Native",
4
+ "languages": ["typescript", "javascript", "kotlin", "java", "swift", "objective-c"],
5
+ "platforms": ["android", "ios"],
6
+ "markers": ["package.json depending on react-native", "app.json (Expo)"],
7
+ "toolchain": ["node", "java", "android-sdk", "xcode", "cocoapods"]
8
+ }