trinity-method-sdk 2.0.9 → 2.2.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/CHANGELOG.md +702 -267
- package/README.md +550 -540
- package/dist/cli/commands/deploy/agents.js +1 -1
- package/dist/cli/commands/deploy/ci-cd.d.ts +4 -3
- package/dist/cli/commands/deploy/ci-cd.js +10 -9
- package/dist/cli/commands/deploy/claude-setup.js +28 -35
- package/dist/cli/commands/deploy/configuration.js +10 -11
- package/dist/cli/commands/deploy/directories.js +13 -14
- package/dist/cli/commands/deploy/gitignore.js +3 -5
- package/dist/cli/commands/deploy/index.d.ts +1 -1
- package/dist/cli/commands/deploy/index.js +7 -3
- package/dist/cli/commands/deploy/knowledge-base.js +3 -3
- package/dist/cli/commands/deploy/pre-flight.js +1 -1
- package/dist/cli/commands/deploy/root-files.js +3 -18
- package/dist/cli/commands/deploy/sdk-install.js +1 -1
- package/dist/cli/commands/deploy/summary.js +3 -3
- package/dist/cli/commands/deploy/templates.js +33 -20
- package/dist/cli/commands/update/agents.js +1 -1
- package/dist/cli/commands/update/backup.js +6 -12
- package/dist/cli/commands/update/commands.d.ts +1 -0
- package/dist/cli/commands/update/commands.js +18 -45
- package/dist/cli/commands/update/knowledge-base.js +2 -2
- package/dist/cli/commands/update/pre-flight.js +11 -11
- package/dist/cli/commands/update/summary.js +5 -5
- package/dist/cli/commands/update/templates.js +35 -13
- package/dist/cli/commands/update/verification.js +5 -5
- package/dist/cli/commands/update/version.js +1 -1
- package/dist/cli/utils/deploy-ci.d.ts +3 -2
- package/dist/cli/utils/deploy-ci.js +24 -24
- package/dist/cli/utils/deploy-linting.js +101 -6
- package/dist/cli/utils/error-classes.d.ts +2 -2
- package/dist/cli/utils/linting-tools.js +14 -6
- package/dist/cli/utils/template-processor.js +2 -4
- package/dist/templates/{claude → .claude}/EMPLOYEE-DIRECTORY.md.template +16 -22
- package/dist/templates/{agents → .claude/agents}/aj-team/apo-documentation-specialist.md.template +10 -10
- package/dist/templates/{agents → .claude/agents}/aj-team/bas-quality-gate.md.template +13 -15
- package/dist/templates/{agents → .claude/agents}/aj-team/bon-dependency-manager.md.template +4 -4
- package/dist/templates/{agents → .claude/agents}/aj-team/cap-configuration-specialist.md.template +3 -3
- package/dist/templates/{agents → .claude/agents}/aj-team/dra-code-reviewer.md.template +8 -10
- package/dist/templates/{agents → .claude/agents}/aj-team/kil-task-executor.md.template +11 -13
- package/dist/templates/{agents → .claude/agents}/aj-team/uro-refactoring-specialist.md.template +3 -3
- package/dist/templates/{agents → .claude/agents}/audit/juno-auditor.md.template +46 -42
- package/dist/templates/{agents → .claude/agents}/deployment/ein-cicd.md.template +59 -164
- package/dist/templates/{agents → .claude/agents}/deployment/ino-context.md.template +25 -22
- package/dist/templates/{agents → .claude/agents}/deployment/tan-structure.md.template +32 -30
- package/dist/templates/{agents → .claude/agents}/deployment/zen-knowledge.md.template +28 -23
- package/dist/templates/{agents → .claude/agents}/leadership/aj-maestro.md.template +10 -6
- package/dist/templates/{agents → .claude/agents}/leadership/aly-cto.md.template +22 -19
- package/dist/templates/{agents → .claude/agents}/planning/eus-decomposer.md.template +8 -4
- package/dist/templates/{agents → .claude/agents}/planning/mon-requirements.md.template +8 -4
- package/dist/templates/{agents → .claude/agents}/planning/ror-design.md.template +8 -4
- package/dist/templates/{agents → .claude/agents}/planning/tra-planner.md.template +10 -4
- package/dist/templates/{shared/claude-commands → .claude/commands/execution}/trinity-audit.md.template +15 -15
- package/dist/templates/.claude/commands/execution/trinity-breakdown.md.template +535 -0
- package/dist/templates/{shared/claude-commands → .claude/commands/execution}/trinity-orchestrate.md.template +48 -48
- package/dist/templates/{shared/claude-commands → .claude/commands/infrastructure}/trinity-init.md.template +32 -54
- package/dist/templates/{shared/claude-commands → .claude/commands/investigation}/trinity-create-investigation.md.template +13 -7
- package/dist/templates/{shared/claude-commands → .claude/commands/investigation}/trinity-investigate-templates.md.template +19 -15
- package/dist/templates/{shared/claude-commands → .claude/commands/investigation}/trinity-plan-investigation.md.template +12 -6
- package/dist/templates/{shared/claude-commands → .claude/commands/maintenance}/trinity-changelog.md.template +9 -8
- package/dist/templates/.claude/commands/maintenance/trinity-docs-update.md.template +279 -0
- package/dist/templates/.claude/commands/maintenance/trinity-docs.md.template +2828 -0
- package/dist/templates/{shared/claude-commands → .claude/commands/maintenance}/trinity-readme.md.template +21 -20
- package/dist/templates/{shared/claude-commands → .claude/commands/planning}/trinity-decompose.md.template +6 -4
- package/dist/templates/{shared/claude-commands → .claude/commands/planning}/trinity-design.md.template +6 -4
- package/dist/templates/{shared/claude-commands → .claude/commands/planning}/trinity-plan.md.template +7 -5
- package/dist/templates/{shared/claude-commands → .claude/commands/planning}/trinity-requirements.md.template +6 -4
- package/dist/templates/{shared/claude-commands → .claude/commands/session}/trinity-continue.md.template +30 -24
- package/dist/templates/{shared/claude-commands → .claude/commands/session}/trinity-end.md.template +403 -397
- package/dist/templates/{shared/claude-commands → .claude/commands/session}/trinity-start.md.template +9 -4
- package/dist/templates/{shared/claude-commands → .claude/commands/utility}/trinity-agents.md.template +11 -8
- package/dist/templates/{shared/claude-commands → .claude/commands/utility}/trinity-verify.md.template +56 -57
- package/dist/templates/{shared/claude-commands → .claude/commands/utility}/trinity-workorder.md.template +13 -9
- package/dist/templates/ci/ci.yml.template +2 -2
- package/dist/templates/root/CLAUDE.md.template +9 -9
- package/dist/templates/root/linting/nodejs/.husky-pre-commit.template +5 -0
- package/dist/templates/source/base-CLAUDE.md.template +310 -310
- package/dist/templates/source/flutter-CLAUDE.md.template +593 -593
- package/dist/templates/source/nodejs-CLAUDE.md.template +531 -531
- package/dist/templates/source/python-CLAUDE.md.template +510 -510
- package/dist/templates/source/react-CLAUDE.md.template +513 -513
- package/dist/templates/source/rust-CLAUDE.md.template +653 -653
- package/dist/templates/trinity/CLAUDE.md.template +14 -14
- package/dist/templates/{knowledge-base → trinity/knowledge-base}/AI-DEVELOPMENT-GUIDE.md.template +1 -1
- package/dist/templates/{knowledge-base → trinity/knowledge-base}/ARCHITECTURE.md.template +5 -5
- package/dist/templates/{knowledge-base → trinity/knowledge-base}/CODING-PRINCIPLES.md.template +1 -1
- package/dist/templates/{knowledge-base → trinity/knowledge-base}/DOCUMENTATION-CRITERIA.md.template +1 -1
- package/dist/templates/{knowledge-base → trinity/knowledge-base}/ISSUES.md.template +9 -9
- package/dist/templates/{knowledge-base → trinity/knowledge-base}/TESTING-PRINCIPLES.md.template +1 -1
- package/dist/templates/{knowledge-base → trinity/knowledge-base}/Technical-Debt.md.template +2 -4
- package/dist/templates/{knowledge-base → trinity/knowledge-base}/To-do.md.template +2 -2
- package/dist/templates/{knowledge-base → trinity/knowledge-base}/Trinity.md.template +6 -6
- package/dist/templates/trinity/templates/documentation/api-docs/README.md.template +218 -0
- package/dist/templates/trinity/templates/documentation/configuration/documentation-structure.md.template +71 -0
- package/dist/templates/trinity/templates/documentation/configuration/env-example-generator.md.template +387 -0
- package/dist/templates/trinity/templates/documentation/discovery/api-endpoint-scanner.md.template +343 -0
- package/dist/templates/trinity/templates/documentation/discovery/component-discovery.md.template +254 -0
- package/dist/templates/trinity/templates/documentation/discovery/env-variable-extraction.md.template +316 -0
- package/dist/templates/trinity/templates/documentation/discovery/framework-detection.md.template +205 -0
- package/dist/templates/trinity/templates/documentation/guides/api-development.md.template +375 -0
- package/dist/templates/trinity/templates/documentation/guides/contributing.md.template +488 -0
- package/dist/templates/trinity/templates/documentation/guides/deployment.md.template +565 -0
- package/dist/templates/trinity/templates/documentation/guides/getting-started.md.template +118 -0
- package/dist/templates/trinity/templates/documentation/mermaid-diagrams/api-endpoint-map.md.template +56 -0
- package/dist/templates/trinity/templates/documentation/mermaid-diagrams/component-hierarchy.md.template +60 -0
- package/dist/templates/trinity/templates/documentation/mermaid-diagrams/database-er.md.template +49 -0
- package/dist/templates/trinity/templates/documentation/mermaid-diagrams/mvc-flow.md.template +41 -0
- package/dist/templates/trinity/templates/documentation/processes/error-handling-protocol.md.template +166 -0
- package/dist/templates/trinity/templates/documentation/processes/fallback-mechanism.md.template +88 -0
- package/dist/templates/trinity/templates/documentation/reports/apo-docs-update-checklist.md.template +343 -0
- package/dist/templates/trinity/templates/documentation/reports/juno-docs-update-checklist.md.template +1337 -0
- package/dist/templates/trinity/templates/documentation/reports/juno-final-report.md.template +237 -0
- package/dist/templates/trinity/templates/documentation/reports/juno-internal-report.md.template +461 -0
- package/dist/templates/trinity/templates/documentation/validation/documentation-verification-rules.md.template +379 -0
- package/dist/templates/trinity/templates/documentation/validation/juno-quality-gates.md.template +282 -0
- package/dist/templates/{investigations → trinity/templates/investigations}/bug.md.template +14 -14
- package/dist/templates/{investigations → trinity/templates/investigations}/feature.md.template +14 -14
- package/dist/templates/{investigations → trinity/templates/investigations}/performance.md.template +14 -14
- package/dist/templates/{investigations → trinity/templates/investigations}/security.md.template +14 -14
- package/dist/templates/{investigations → trinity/templates/investigations}/technical.md.template +14 -14
- package/dist/templates/{work-orders → trinity/templates/work-orders}/ANALYSIS-TEMPLATE.md.template +10 -13
- package/dist/templates/{work-orders → trinity/templates/work-orders}/AUDIT-TEMPLATE.md.template +10 -26
- package/dist/templates/{work-orders → trinity/templates/work-orders}/IMPLEMENTATION-TEMPLATE.md.template +10 -26
- package/dist/templates/{work-orders → trinity/templates/work-orders}/INVESTIGATION-TEMPLATE.md.template +10 -25
- package/dist/templates/{work-orders → trinity/templates/work-orders}/PATTERN-TEMPLATE.md.template +10 -26
- package/dist/templates/{work-orders → trinity/templates/work-orders}/VERIFICATION-TEMPLATE.md.template +10 -26
- package/package.json +99 -94
- package/dist/templates/agents/leadership/aj-cc.md.template +0 -462
- package/dist/templates/ci/cd.yml.template +0 -175
- package/dist/templates/ci/github-actions.yml +0 -86
- package/dist/templates/root/TRINITY.md.template +0 -52
- package/dist/templates/shared/claude-commands/trinity-docs.md.template +0 -2577
- /package/dist/templates/{linting → root/linting}/flutter/.pre-commit-config.yaml.template +0 -0
- /package/dist/templates/{linting → root/linting}/flutter/analysis_options.yaml.template +0 -0
- /package/dist/templates/{linting → root/linting}/nodejs/.eslintrc-commonjs.json.template +0 -0
- /package/dist/templates/{linting → root/linting}/nodejs/.eslintrc-esm.json.template +0 -0
- /package/dist/templates/{linting → root/linting}/nodejs/.eslintrc-typescript.json.template +0 -0
- /package/dist/templates/{linting → root/linting}/nodejs/.pre-commit-config.yaml.template +0 -0
- /package/dist/templates/{linting → root/linting}/nodejs/.prettierrc.json.template +0 -0
- /package/dist/templates/{linting → root/linting}/python/.flake8.template +0 -0
- /package/dist/templates/{linting → root/linting}/python/.pre-commit-config.yaml.template +0 -0
- /package/dist/templates/{linting → root/linting}/python/pyproject.toml.template +0 -0
- /package/dist/templates/{linting → root/linting}/rust/.pre-commit-config.yaml.template +0 -0
- /package/dist/templates/{linting → root/linting}/rust/clippy.toml.template +0 -0
- /package/dist/templates/{linting → root/linting}/rust/rustfmt.toml.template +0 -0
- /package/dist/templates/{documentation → trinity/templates/documentation}/ROOT-README.md.template +0 -0
- /package/dist/templates/{documentation → trinity/templates/documentation}/SUBDIRECTORY-README.md.template +0 -0
|
@@ -1,593 +1,593 @@
|
|
|
1
|
-
# CLAUDE.md - Flutter/Dart Technology-Specific Rules
|
|
2
|
-
## {{PROJECT_NAME}} - Flutter Implementation
|
|
3
|
-
|
|
4
|
-
**Framework:** Flutter
|
|
5
|
-
**Language:** Dart
|
|
6
|
-
**Source Directory:** {{SOURCE_DIR}}
|
|
7
|
-
**Platform:** Cross-platform (iOS, Android, Web, Desktop)
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## Technology Stack Behavioral Modifications
|
|
12
|
-
|
|
13
|
-
### Flutter-Specific Requirements
|
|
14
|
-
- **Widget Patterns**: Use Flutter widget composition patterns
|
|
15
|
-
- **State Management**: Implement appropriate state management (Provider, Riverpod, BLoC, GetX)
|
|
16
|
-
- **Material Design**: Follow Material Design 3 guidelines
|
|
17
|
-
- **Responsive Design**: Build adaptive layouts for all screen sizes
|
|
18
|
-
- **Platform Awareness**: Handle platform-specific behavior (iOS vs Android)
|
|
19
|
-
|
|
20
|
-
### Dart Language Adaptations
|
|
21
|
-
- **Null Safety**: Enforce sound null safety throughout codebase
|
|
22
|
-
- **Async/Await**: Use async/await for asynchronous operations
|
|
23
|
-
- **Streams**: Leverage Dart streams for reactive programming
|
|
24
|
-
- **Isolates**: Use isolates for CPU-intensive tasks
|
|
25
|
-
- **Extension Methods**: Create extension methods for code reusability
|
|
26
|
-
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
## Technology Debugging Standards
|
|
30
|
-
|
|
31
|
-
### Flutter Debugging Framework
|
|
32
|
-
```dart
|
|
33
|
-
// Standard debugging format for Flutter applications
|
|
34
|
-
class DebugLogger {
|
|
35
|
-
static const String _tag = 'TRINITY';
|
|
36
|
-
|
|
37
|
-
static void entry(String className, String functionName, Map<String, dynamic>? params) {
|
|
38
|
-
if (kDebugMode) {
|
|
39
|
-
print('[ENTRY] $_tag.$className.$functionName ${params ?? {}}');
|
|
40
|
-
print(' Timestamp: ${DateTime.now().toIso8601String()}');
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
static void exit(String className, String functionName, dynamic result, DateTime startTime) {
|
|
45
|
-
if (kDebugMode) {
|
|
46
|
-
final duration = DateTime.now().difference(startTime).inMilliseconds;
|
|
47
|
-
print('[EXIT] $_tag.$className.$functionName');
|
|
48
|
-
print(' Result: $result');
|
|
49
|
-
print(' Duration: ${duration}ms');
|
|
50
|
-
print(' Timestamp: ${DateTime.now().toIso8601String()}');
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
static void error(String className, String functionName, dynamic error, StackTrace? stackTrace, {Map<String, dynamic>? context}) {
|
|
55
|
-
print('[ERROR] $_tag.$className.$functionName');
|
|
56
|
-
print(' Error: $error');
|
|
57
|
-
if (stackTrace != null) {
|
|
58
|
-
print(' Stack: $stackTrace');
|
|
59
|
-
}
|
|
60
|
-
if (context != null) {
|
|
61
|
-
print(' Context: $context');
|
|
62
|
-
}
|
|
63
|
-
print(' Timestamp: ${DateTime.now().toIso8601String()}');
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Usage example
|
|
68
|
-
class UserService {
|
|
69
|
-
Future<User?> getUser(String userId) async {
|
|
70
|
-
final startTime = DateTime.now();
|
|
71
|
-
DebugLogger.entry('UserService', 'getUser', {'userId': userId});
|
|
72
|
-
|
|
73
|
-
try {
|
|
74
|
-
final user = await _fetchUser(userId);
|
|
75
|
-
DebugLogger.exit('UserService', 'getUser', user?.toJson(), startTime);
|
|
76
|
-
return user;
|
|
77
|
-
} catch (e, stackTrace) {
|
|
78
|
-
DebugLogger.error('UserService', 'getUser', e, stackTrace, context: {'userId': userId});
|
|
79
|
-
rethrow;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### Widget Debugging
|
|
86
|
-
```dart
|
|
87
|
-
// Debug widget lifecycle
|
|
88
|
-
class DebuggedWidget extends StatefulWidget {
|
|
89
|
-
@override
|
|
90
|
-
State<DebuggedWidget> createState() {
|
|
91
|
-
DebugLogger.entry('DebuggedWidget', 'createState', null);
|
|
92
|
-
return _DebuggedWidgetState();
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
class _DebuggedWidgetState extends State<DebuggedWidget> {
|
|
97
|
-
@override
|
|
98
|
-
void initState() {
|
|
99
|
-
super.initState();
|
|
100
|
-
DebugLogger.entry('DebuggedWidget', 'initState', null);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
@override
|
|
104
|
-
void dispose() {
|
|
105
|
-
DebugLogger.entry('DebuggedWidget', 'dispose', null);
|
|
106
|
-
super.dispose();
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
@override
|
|
110
|
-
Widget build(BuildContext context) {
|
|
111
|
-
return Container(); // Your widget
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
---
|
|
117
|
-
|
|
118
|
-
## Performance Optimization Rules
|
|
119
|
-
|
|
120
|
-
### Flutter Performance Monitoring
|
|
121
|
-
```dart
|
|
122
|
-
// Performance measurement utilities
|
|
123
|
-
class PerformanceMonitor {
|
|
124
|
-
static T measureSync<T>(String name, T Function() operation) {
|
|
125
|
-
final stopwatch = Stopwatch()..start();
|
|
126
|
-
|
|
127
|
-
try {
|
|
128
|
-
final result = operation();
|
|
129
|
-
stopwatch.stop();
|
|
130
|
-
|
|
131
|
-
if (kDebugMode) {
|
|
132
|
-
print('[PERF] $name: ${stopwatch.elapsedMilliseconds}ms');
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return result;
|
|
136
|
-
} catch (e) {
|
|
137
|
-
stopwatch.stop();
|
|
138
|
-
print('[PERF-ERROR] $name: ${stopwatch.elapsedMilliseconds}ms - Error: $e');
|
|
139
|
-
rethrow;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
static Future<T> measureAsync<T>(String name, Future<T> Function() operation) async {
|
|
144
|
-
final stopwatch = Stopwatch()..start();
|
|
145
|
-
|
|
146
|
-
try {
|
|
147
|
-
final result = await operation();
|
|
148
|
-
stopwatch.stop();
|
|
149
|
-
|
|
150
|
-
if (kDebugMode) {
|
|
151
|
-
print('[PERF] $name: ${stopwatch.elapsedMilliseconds}ms');
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
return result;
|
|
155
|
-
} catch (e) {
|
|
156
|
-
stopwatch.stop();
|
|
157
|
-
print('[PERF-ERROR] $name: ${stopwatch.elapsedMilliseconds}ms - Error: $e');
|
|
158
|
-
rethrow;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Usage
|
|
164
|
-
final users = await PerformanceMonitor.measureAsync(
|
|
165
|
-
'fetchUsers',
|
|
166
|
-
() => apiService.getUsers()
|
|
167
|
-
);
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
### Widget Performance Optimization
|
|
171
|
-
```dart
|
|
172
|
-
// Optimize widget rebuilds
|
|
173
|
-
class OptimizedWidget extends StatelessWidget {
|
|
174
|
-
const OptimizedWidget({Key? key}) : super(key: key);
|
|
175
|
-
|
|
176
|
-
@override
|
|
177
|
-
Widget build(BuildContext context) {
|
|
178
|
-
return RepaintBoundary(
|
|
179
|
-
child: ListView.builder(
|
|
180
|
-
itemCount: items.length,
|
|
181
|
-
itemBuilder: (context, index) {
|
|
182
|
-
// Use const constructors where possible
|
|
183
|
-
// Avoid expensive operations in build()
|
|
184
|
-
// Extract widgets to separate classes
|
|
185
|
-
return const ItemWidget(key: ValueKey(index));
|
|
186
|
-
},
|
|
187
|
-
),
|
|
188
|
-
);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
### Memory Management
|
|
194
|
-
```dart
|
|
195
|
-
// Monitor memory usage in dev builds
|
|
196
|
-
void monitorMemory() {
|
|
197
|
-
if (kDebugMode) {
|
|
198
|
-
Timer.periodic(const Duration(minutes: 1), (timer) {
|
|
199
|
-
final info = ProcessInfo.currentRss ~/ (1024 * 1024);
|
|
200
|
-
print('[MEMORY] Current RSS: ${info}MB');
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
---
|
|
207
|
-
|
|
208
|
-
## Security Best Practices
|
|
209
|
-
|
|
210
|
-
### Secure Storage
|
|
211
|
-
```dart
|
|
212
|
-
// Use flutter_secure_storage for sensitive data
|
|
213
|
-
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|
214
|
-
|
|
215
|
-
class SecureStorage {
|
|
216
|
-
static const _storage = FlutterSecureStorage();
|
|
217
|
-
|
|
218
|
-
static Future<void> saveToken(String token) async {
|
|
219
|
-
await _storage.write(key: 'auth_token', value: token);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
static Future<String?> getToken() async {
|
|
223
|
-
return await _storage.read(key: 'auth_token');
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
### Input Validation
|
|
229
|
-
```dart
|
|
230
|
-
// Input validation patterns
|
|
231
|
-
class InputValidator {
|
|
232
|
-
static String? validateEmail(String? value) {
|
|
233
|
-
if (value == null || value.isEmpty) {
|
|
234
|
-
return 'Email is required';
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');
|
|
238
|
-
if (!emailRegex.hasMatch(value)) {
|
|
239
|
-
return 'Invalid email format';
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
return null;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
static String? validatePassword(String? value) {
|
|
246
|
-
if (value == null || value.isEmpty) {
|
|
247
|
-
return 'Password is required';
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
if (value.length < 8) {
|
|
251
|
-
return 'Password must be at least 8 characters';
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
return null;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
---
|
|
260
|
-
|
|
261
|
-
## Testing Requirements
|
|
262
|
-
|
|
263
|
-
### Widget Testing
|
|
264
|
-
```dart
|
|
265
|
-
// Widget test example
|
|
266
|
-
void main() {
|
|
267
|
-
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
|
268
|
-
// Build our app and trigger a frame
|
|
269
|
-
await tester.pumpWidget(const MyApp());
|
|
270
|
-
|
|
271
|
-
// Verify initial state
|
|
272
|
-
expect(find.text('0'), findsOneWidget);
|
|
273
|
-
expect(find.text('1'), findsNothing);
|
|
274
|
-
|
|
275
|
-
// Tap the '+' icon and trigger a frame
|
|
276
|
-
await tester.tap(find.byIcon(Icons.add));
|
|
277
|
-
await tester.pump();
|
|
278
|
-
|
|
279
|
-
// Verify counter incremented
|
|
280
|
-
expect(find.text('0'), findsNothing);
|
|
281
|
-
expect(find.text('1'), findsOneWidget);
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
### Unit Testing
|
|
287
|
-
```dart
|
|
288
|
-
// Unit test example
|
|
289
|
-
void main() {
|
|
290
|
-
group('UserService', () {
|
|
291
|
-
late UserService service;
|
|
292
|
-
|
|
293
|
-
setUp(() {
|
|
294
|
-
service = UserService();
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
test('getUser returns user when found', () async {
|
|
298
|
-
final user = await service.getUser('123');
|
|
299
|
-
|
|
300
|
-
expect(user, isNotNull);
|
|
301
|
-
expect(user?.id, equals('123'));
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
test('getUser throws when not found', () async {
|
|
305
|
-
expect(
|
|
306
|
-
() => service.getUser('invalid'),
|
|
307
|
-
throwsA(isA<UserNotFoundException>()),
|
|
308
|
-
);
|
|
309
|
-
});
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
### Integration Testing
|
|
315
|
-
```dart
|
|
316
|
-
// Integration test example
|
|
317
|
-
void main() {
|
|
318
|
-
testWidgets('full app flow', (WidgetTester tester) async {
|
|
319
|
-
await tester.pumpWidget(const MyApp());
|
|
320
|
-
|
|
321
|
-
// Navigate through app
|
|
322
|
-
await tester.tap(find.byType(LoginButton));
|
|
323
|
-
await tester.pumpAndSettle();
|
|
324
|
-
|
|
325
|
-
// Enter credentials
|
|
326
|
-
await tester.enterText(find.byType(EmailField), 'test@example.com');
|
|
327
|
-
await tester.enterText(find.byType(PasswordField), 'password123');
|
|
328
|
-
|
|
329
|
-
// Submit form
|
|
330
|
-
await tester.tap(find.byType(SubmitButton));
|
|
331
|
-
await tester.pumpAndSettle();
|
|
332
|
-
|
|
333
|
-
// Verify navigation
|
|
334
|
-
expect(find.byType(HomePage), findsOneWidget);
|
|
335
|
-
});
|
|
336
|
-
}
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
---
|
|
340
|
-
|
|
341
|
-
## Framework Best Practices
|
|
342
|
-
|
|
343
|
-
### State Management with Provider
|
|
344
|
-
```dart
|
|
345
|
-
// Provider pattern example
|
|
346
|
-
class CounterNotifier extends ChangeNotifier {
|
|
347
|
-
int _count = 0;
|
|
348
|
-
|
|
349
|
-
int get count => _count;
|
|
350
|
-
|
|
351
|
-
void increment() {
|
|
352
|
-
DebugLogger.entry('CounterNotifier', 'increment', {'currentCount': _count});
|
|
353
|
-
_count++;
|
|
354
|
-
notifyListeners();
|
|
355
|
-
DebugLogger.exit('CounterNotifier', 'increment', _count, DateTime.now());
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// Usage in widget
|
|
360
|
-
class CounterWidget extends StatelessWidget {
|
|
361
|
-
@override
|
|
362
|
-
Widget build(BuildContext context) {
|
|
363
|
-
return Consumer<CounterNotifier>(
|
|
364
|
-
builder: (context, counter, child) {
|
|
365
|
-
return Text('Count: ${counter.count}');
|
|
366
|
-
},
|
|
367
|
-
);
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
### BLoC Pattern
|
|
373
|
-
```dart
|
|
374
|
-
// BLoC pattern example
|
|
375
|
-
class CounterBloc extends Bloc<CounterEvent, CounterState> {
|
|
376
|
-
CounterBloc() : super(CounterInitial()) {
|
|
377
|
-
on<IncrementEvent>((event, emit) {
|
|
378
|
-
DebugLogger.entry('CounterBloc', 'IncrementEvent', {'state': state});
|
|
379
|
-
emit(CounterState(count: state.count + 1));
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
### Navigation
|
|
386
|
-
```dart
|
|
387
|
-
// Named routes navigation
|
|
388
|
-
class AppRouter {
|
|
389
|
-
static const String home = '/';
|
|
390
|
-
static const String profile = '/profile';
|
|
391
|
-
static const String settings = '/settings';
|
|
392
|
-
|
|
393
|
-
static Route<dynamic> generateRoute(RouteSettings settings) {
|
|
394
|
-
DebugLogger.entry('AppRouter', 'generateRoute', {'route': settings.name});
|
|
395
|
-
|
|
396
|
-
switch (settings.name) {
|
|
397
|
-
case home:
|
|
398
|
-
return MaterialPageRoute(builder: (_) => HomePage());
|
|
399
|
-
case profile:
|
|
400
|
-
return MaterialPageRoute(builder: (_) => ProfilePage());
|
|
401
|
-
case settings:
|
|
402
|
-
return MaterialPageRoute(builder: (_) => SettingsPage());
|
|
403
|
-
default:
|
|
404
|
-
return MaterialPageRoute(builder: (_) => NotFoundPage());
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
---
|
|
411
|
-
|
|
412
|
-
## Error Handling Patterns
|
|
413
|
-
|
|
414
|
-
### Comprehensive Error Handling
|
|
415
|
-
```dart
|
|
416
|
-
// Custom exception classes
|
|
417
|
-
class ApplicationException implements Exception {
|
|
418
|
-
final String message;
|
|
419
|
-
final int? statusCode;
|
|
420
|
-
final Map<String, dynamic>? context;
|
|
421
|
-
|
|
422
|
-
ApplicationException(this.message, {this.statusCode, this.context});
|
|
423
|
-
|
|
424
|
-
@override
|
|
425
|
-
String toString() => 'ApplicationException: $message';
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
class NetworkException extends ApplicationException {
|
|
429
|
-
NetworkException(String message, {Map<String, dynamic>? context})
|
|
430
|
-
: super(message, statusCode: 500, context: context);
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
class ValidationException extends ApplicationException {
|
|
434
|
-
ValidationException(String message, {Map<String, dynamic>? context})
|
|
435
|
-
: super(message, statusCode: 400, context: context);
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
// Error handling function
|
|
439
|
-
Future<T> safeOperation<T>(
|
|
440
|
-
Future<T> Function() operation,
|
|
441
|
-
String context,
|
|
442
|
-
) async {
|
|
443
|
-
try {
|
|
444
|
-
return await operation();
|
|
445
|
-
} catch (e, stackTrace) {
|
|
446
|
-
DebugLogger.error('SafeOperation', context, e, stackTrace);
|
|
447
|
-
|
|
448
|
-
if (e is SocketException) {
|
|
449
|
-
throw NetworkException('Network connection failed', context: {'error': e.toString()});
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
rethrow;
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
### Global Error Handler
|
|
458
|
-
```dart
|
|
459
|
-
// Global error handling
|
|
460
|
-
void main() {
|
|
461
|
-
FlutterError.onError = (FlutterErrorDetails details) {
|
|
462
|
-
DebugLogger.error(
|
|
463
|
-
'Flutter',
|
|
464
|
-
'onError',
|
|
465
|
-
details.exception,
|
|
466
|
-
details.stack,
|
|
467
|
-
context: {'library': details.library},
|
|
468
|
-
);
|
|
469
|
-
|
|
470
|
-
// Report to crash analytics in production
|
|
471
|
-
if (kReleaseMode) {
|
|
472
|
-
// FirebaseCrashlytics.instance.recordFlutterError(details);
|
|
473
|
-
}
|
|
474
|
-
};
|
|
475
|
-
|
|
476
|
-
PlatformDispatcher.instance.onError = (error, stack) {
|
|
477
|
-
DebugLogger.error('Platform', 'onError', error, stack);
|
|
478
|
-
|
|
479
|
-
if (kReleaseMode) {
|
|
480
|
-
// Report to crash analytics
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
return true;
|
|
484
|
-
};
|
|
485
|
-
|
|
486
|
-
runApp(const MyApp());
|
|
487
|
-
}
|
|
488
|
-
```
|
|
489
|
-
|
|
490
|
-
---
|
|
491
|
-
|
|
492
|
-
## Technology-Specific Command References
|
|
493
|
-
|
|
494
|
-
### Development Commands
|
|
495
|
-
```bash
|
|
496
|
-
# Flutter Development
|
|
497
|
-
flutter run # Run app in debug mode
|
|
498
|
-
flutter run -d chrome # Run on Chrome
|
|
499
|
-
flutter run -d ios # Run on iOS simulator
|
|
500
|
-
flutter run --release # Run in release mode
|
|
501
|
-
|
|
502
|
-
# Hot Reload & Restart
|
|
503
|
-
# Press 'r' in terminal for hot reload
|
|
504
|
-
# Press 'R' in terminal for hot restart
|
|
505
|
-
|
|
506
|
-
# Dependencies
|
|
507
|
-
flutter pub get # Get dependencies
|
|
508
|
-
flutter pub upgrade # Upgrade dependencies
|
|
509
|
-
flutter pub outdated # Check outdated packages
|
|
510
|
-
```
|
|
511
|
-
|
|
512
|
-
### Testing Commands
|
|
513
|
-
```bash
|
|
514
|
-
# Testing
|
|
515
|
-
flutter test # Run unit tests
|
|
516
|
-
flutter test --coverage # Generate coverage
|
|
517
|
-
flutter test integration_test/app_test.dart # Integration tests
|
|
518
|
-
flutter drive --target=test_driver/app.dart # Driver tests
|
|
519
|
-
```
|
|
520
|
-
|
|
521
|
-
### Build Commands
|
|
522
|
-
```bash
|
|
523
|
-
# Building
|
|
524
|
-
flutter build apk # Build Android APK
|
|
525
|
-
flutter build appbundle # Build Android App Bundle
|
|
526
|
-
flutter build ios # Build iOS app
|
|
527
|
-
flutter build web # Build web app
|
|
528
|
-
flutter build windows # Build Windows app
|
|
529
|
-
|
|
530
|
-
# Clean & Rebuild
|
|
531
|
-
flutter clean # Clean build files
|
|
532
|
-
flutter pub get # Get dependencies
|
|
533
|
-
flutter build apk # Rebuild
|
|
534
|
-
```
|
|
535
|
-
|
|
536
|
-
---
|
|
537
|
-
|
|
538
|
-
## Component-Level Customizations
|
|
539
|
-
|
|
540
|
-
### Project Structure
|
|
541
|
-
```
|
|
542
|
-
{{SOURCE_DIR}}/
|
|
543
|
-
├── main.dart # App entry point
|
|
544
|
-
├── app.dart # App widget
|
|
545
|
-
├── screens/ # Screen widgets
|
|
546
|
-
├── widgets/ # Reusable widgets
|
|
547
|
-
├── models/ # Data models
|
|
548
|
-
├── services/ # Business logic
|
|
549
|
-
├── providers/ # State management
|
|
550
|
-
├── utils/ # Utility functions
|
|
551
|
-
├── constants/ # App constants
|
|
552
|
-
└── theme/ # Theme configuration
|
|
553
|
-
```
|
|
554
|
-
|
|
555
|
-
### Asset Management
|
|
556
|
-
```yaml
|
|
557
|
-
# pubspec.yaml
|
|
558
|
-
flutter:
|
|
559
|
-
assets:
|
|
560
|
-
- assets/images/
|
|
561
|
-
- assets/icons/
|
|
562
|
-
- assets/fonts/
|
|
563
|
-
|
|
564
|
-
fonts:
|
|
565
|
-
- family: CustomFont
|
|
566
|
-
fonts:
|
|
567
|
-
- asset: assets/fonts/CustomFont-Regular.ttf
|
|
568
|
-
- asset: assets/fonts/CustomFont-Bold.ttf
|
|
569
|
-
weight: 700
|
|
570
|
-
```
|
|
571
|
-
|
|
572
|
-
---
|
|
573
|
-
|
|
574
|
-
## Reference to Parent Context
|
|
575
|
-
|
|
576
|
-
This file extends the Trinity Method protocols defined in
|
|
577
|
-
|
|
578
|
-
- Trinity Method investigation requirements ([
|
|
579
|
-
- Global performance baselines ([
|
|
580
|
-
- Quality gate standards (BAS 6-phase) ([
|
|
581
|
-
- Crisis management protocols ([
|
|
582
|
-
|
|
583
|
-
All Flutter code must implement the debugging frameworks, error handling patterns, and performance monitoring specified in this document.
|
|
584
|
-
|
|
585
|
-
---
|
|
586
|
-
|
|
587
|
-
**Technology Context**: Flutter/Dart Implementation
|
|
588
|
-
**Parent References**:
|
|
589
|
-
- `../CLAUDE.md` - Global project requirements
|
|
590
|
-
-
|
|
591
|
-
|
|
592
|
-
**Last Updated**: {{CURRENT_DATE}}
|
|
593
|
-
**Trinity Version**: {{TRINITY_VERSION}}
|
|
1
|
+
# CLAUDE.md - Flutter/Dart Technology-Specific Rules
|
|
2
|
+
## {{PROJECT_NAME}} - Flutter Implementation
|
|
3
|
+
|
|
4
|
+
**Framework:** Flutter
|
|
5
|
+
**Language:** Dart
|
|
6
|
+
**Source Directory:** {{SOURCE_DIR}}
|
|
7
|
+
**Platform:** Cross-platform (iOS, Android, Web, Desktop)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Technology Stack Behavioral Modifications
|
|
12
|
+
|
|
13
|
+
### Flutter-Specific Requirements
|
|
14
|
+
- **Widget Patterns**: Use Flutter widget composition patterns
|
|
15
|
+
- **State Management**: Implement appropriate state management (Provider, Riverpod, BLoC, GetX)
|
|
16
|
+
- **Material Design**: Follow Material Design 3 guidelines
|
|
17
|
+
- **Responsive Design**: Build adaptive layouts for all screen sizes
|
|
18
|
+
- **Platform Awareness**: Handle platform-specific behavior (iOS vs Android)
|
|
19
|
+
|
|
20
|
+
### Dart Language Adaptations
|
|
21
|
+
- **Null Safety**: Enforce sound null safety throughout codebase
|
|
22
|
+
- **Async/Await**: Use async/await for asynchronous operations
|
|
23
|
+
- **Streams**: Leverage Dart streams for reactive programming
|
|
24
|
+
- **Isolates**: Use isolates for CPU-intensive tasks
|
|
25
|
+
- **Extension Methods**: Create extension methods for code reusability
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Technology Debugging Standards
|
|
30
|
+
|
|
31
|
+
### Flutter Debugging Framework
|
|
32
|
+
```dart
|
|
33
|
+
// Standard debugging format for Flutter applications
|
|
34
|
+
class DebugLogger {
|
|
35
|
+
static const String _tag = 'TRINITY';
|
|
36
|
+
|
|
37
|
+
static void entry(String className, String functionName, Map<String, dynamic>? params) {
|
|
38
|
+
if (kDebugMode) {
|
|
39
|
+
print('[ENTRY] $_tag.$className.$functionName ${params ?? {}}');
|
|
40
|
+
print(' Timestamp: ${DateTime.now().toIso8601String()}');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
static void exit(String className, String functionName, dynamic result, DateTime startTime) {
|
|
45
|
+
if (kDebugMode) {
|
|
46
|
+
final duration = DateTime.now().difference(startTime).inMilliseconds;
|
|
47
|
+
print('[EXIT] $_tag.$className.$functionName');
|
|
48
|
+
print(' Result: $result');
|
|
49
|
+
print(' Duration: ${duration}ms');
|
|
50
|
+
print(' Timestamp: ${DateTime.now().toIso8601String()}');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static void error(String className, String functionName, dynamic error, StackTrace? stackTrace, {Map<String, dynamic>? context}) {
|
|
55
|
+
print('[ERROR] $_tag.$className.$functionName');
|
|
56
|
+
print(' Error: $error');
|
|
57
|
+
if (stackTrace != null) {
|
|
58
|
+
print(' Stack: $stackTrace');
|
|
59
|
+
}
|
|
60
|
+
if (context != null) {
|
|
61
|
+
print(' Context: $context');
|
|
62
|
+
}
|
|
63
|
+
print(' Timestamp: ${DateTime.now().toIso8601String()}');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Usage example
|
|
68
|
+
class UserService {
|
|
69
|
+
Future<User?> getUser(String userId) async {
|
|
70
|
+
final startTime = DateTime.now();
|
|
71
|
+
DebugLogger.entry('UserService', 'getUser', {'userId': userId});
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
final user = await _fetchUser(userId);
|
|
75
|
+
DebugLogger.exit('UserService', 'getUser', user?.toJson(), startTime);
|
|
76
|
+
return user;
|
|
77
|
+
} catch (e, stackTrace) {
|
|
78
|
+
DebugLogger.error('UserService', 'getUser', e, stackTrace, context: {'userId': userId});
|
|
79
|
+
rethrow;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Widget Debugging
|
|
86
|
+
```dart
|
|
87
|
+
// Debug widget lifecycle
|
|
88
|
+
class DebuggedWidget extends StatefulWidget {
|
|
89
|
+
@override
|
|
90
|
+
State<DebuggedWidget> createState() {
|
|
91
|
+
DebugLogger.entry('DebuggedWidget', 'createState', null);
|
|
92
|
+
return _DebuggedWidgetState();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
class _DebuggedWidgetState extends State<DebuggedWidget> {
|
|
97
|
+
@override
|
|
98
|
+
void initState() {
|
|
99
|
+
super.initState();
|
|
100
|
+
DebugLogger.entry('DebuggedWidget', 'initState', null);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
@override
|
|
104
|
+
void dispose() {
|
|
105
|
+
DebugLogger.entry('DebuggedWidget', 'dispose', null);
|
|
106
|
+
super.dispose();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@override
|
|
110
|
+
Widget build(BuildContext context) {
|
|
111
|
+
return Container(); // Your widget
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Performance Optimization Rules
|
|
119
|
+
|
|
120
|
+
### Flutter Performance Monitoring
|
|
121
|
+
```dart
|
|
122
|
+
// Performance measurement utilities
|
|
123
|
+
class PerformanceMonitor {
|
|
124
|
+
static T measureSync<T>(String name, T Function() operation) {
|
|
125
|
+
final stopwatch = Stopwatch()..start();
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
final result = operation();
|
|
129
|
+
stopwatch.stop();
|
|
130
|
+
|
|
131
|
+
if (kDebugMode) {
|
|
132
|
+
print('[PERF] $name: ${stopwatch.elapsedMilliseconds}ms');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return result;
|
|
136
|
+
} catch (e) {
|
|
137
|
+
stopwatch.stop();
|
|
138
|
+
print('[PERF-ERROR] $name: ${stopwatch.elapsedMilliseconds}ms - Error: $e');
|
|
139
|
+
rethrow;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
static Future<T> measureAsync<T>(String name, Future<T> Function() operation) async {
|
|
144
|
+
final stopwatch = Stopwatch()..start();
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
final result = await operation();
|
|
148
|
+
stopwatch.stop();
|
|
149
|
+
|
|
150
|
+
if (kDebugMode) {
|
|
151
|
+
print('[PERF] $name: ${stopwatch.elapsedMilliseconds}ms');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return result;
|
|
155
|
+
} catch (e) {
|
|
156
|
+
stopwatch.stop();
|
|
157
|
+
print('[PERF-ERROR] $name: ${stopwatch.elapsedMilliseconds}ms - Error: $e');
|
|
158
|
+
rethrow;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Usage
|
|
164
|
+
final users = await PerformanceMonitor.measureAsync(
|
|
165
|
+
'fetchUsers',
|
|
166
|
+
() => apiService.getUsers()
|
|
167
|
+
);
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Widget Performance Optimization
|
|
171
|
+
```dart
|
|
172
|
+
// Optimize widget rebuilds
|
|
173
|
+
class OptimizedWidget extends StatelessWidget {
|
|
174
|
+
const OptimizedWidget({Key? key}) : super(key: key);
|
|
175
|
+
|
|
176
|
+
@override
|
|
177
|
+
Widget build(BuildContext context) {
|
|
178
|
+
return RepaintBoundary(
|
|
179
|
+
child: ListView.builder(
|
|
180
|
+
itemCount: items.length,
|
|
181
|
+
itemBuilder: (context, index) {
|
|
182
|
+
// Use const constructors where possible
|
|
183
|
+
// Avoid expensive operations in build()
|
|
184
|
+
// Extract widgets to separate classes
|
|
185
|
+
return const ItemWidget(key: ValueKey(index));
|
|
186
|
+
},
|
|
187
|
+
),
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Memory Management
|
|
194
|
+
```dart
|
|
195
|
+
// Monitor memory usage in dev builds
|
|
196
|
+
void monitorMemory() {
|
|
197
|
+
if (kDebugMode) {
|
|
198
|
+
Timer.periodic(const Duration(minutes: 1), (timer) {
|
|
199
|
+
final info = ProcessInfo.currentRss ~/ (1024 * 1024);
|
|
200
|
+
print('[MEMORY] Current RSS: ${info}MB');
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Security Best Practices
|
|
209
|
+
|
|
210
|
+
### Secure Storage
|
|
211
|
+
```dart
|
|
212
|
+
// Use flutter_secure_storage for sensitive data
|
|
213
|
+
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|
214
|
+
|
|
215
|
+
class SecureStorage {
|
|
216
|
+
static const _storage = FlutterSecureStorage();
|
|
217
|
+
|
|
218
|
+
static Future<void> saveToken(String token) async {
|
|
219
|
+
await _storage.write(key: 'auth_token', value: token);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
static Future<String?> getToken() async {
|
|
223
|
+
return await _storage.read(key: 'auth_token');
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Input Validation
|
|
229
|
+
```dart
|
|
230
|
+
// Input validation patterns
|
|
231
|
+
class InputValidator {
|
|
232
|
+
static String? validateEmail(String? value) {
|
|
233
|
+
if (value == null || value.isEmpty) {
|
|
234
|
+
return 'Email is required';
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');
|
|
238
|
+
if (!emailRegex.hasMatch(value)) {
|
|
239
|
+
return 'Invalid email format';
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
static String? validatePassword(String? value) {
|
|
246
|
+
if (value == null || value.isEmpty) {
|
|
247
|
+
return 'Password is required';
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (value.length < 8) {
|
|
251
|
+
return 'Password must be at least 8 characters';
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Testing Requirements
|
|
262
|
+
|
|
263
|
+
### Widget Testing
|
|
264
|
+
```dart
|
|
265
|
+
// Widget test example
|
|
266
|
+
void main() {
|
|
267
|
+
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
|
268
|
+
// Build our app and trigger a frame
|
|
269
|
+
await tester.pumpWidget(const MyApp());
|
|
270
|
+
|
|
271
|
+
// Verify initial state
|
|
272
|
+
expect(find.text('0'), findsOneWidget);
|
|
273
|
+
expect(find.text('1'), findsNothing);
|
|
274
|
+
|
|
275
|
+
// Tap the '+' icon and trigger a frame
|
|
276
|
+
await tester.tap(find.byIcon(Icons.add));
|
|
277
|
+
await tester.pump();
|
|
278
|
+
|
|
279
|
+
// Verify counter incremented
|
|
280
|
+
expect(find.text('0'), findsNothing);
|
|
281
|
+
expect(find.text('1'), findsOneWidget);
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Unit Testing
|
|
287
|
+
```dart
|
|
288
|
+
// Unit test example
|
|
289
|
+
void main() {
|
|
290
|
+
group('UserService', () {
|
|
291
|
+
late UserService service;
|
|
292
|
+
|
|
293
|
+
setUp(() {
|
|
294
|
+
service = UserService();
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
test('getUser returns user when found', () async {
|
|
298
|
+
final user = await service.getUser('123');
|
|
299
|
+
|
|
300
|
+
expect(user, isNotNull);
|
|
301
|
+
expect(user?.id, equals('123'));
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
test('getUser throws when not found', () async {
|
|
305
|
+
expect(
|
|
306
|
+
() => service.getUser('invalid'),
|
|
307
|
+
throwsA(isA<UserNotFoundException>()),
|
|
308
|
+
);
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Integration Testing
|
|
315
|
+
```dart
|
|
316
|
+
// Integration test example
|
|
317
|
+
void main() {
|
|
318
|
+
testWidgets('full app flow', (WidgetTester tester) async {
|
|
319
|
+
await tester.pumpWidget(const MyApp());
|
|
320
|
+
|
|
321
|
+
// Navigate through app
|
|
322
|
+
await tester.tap(find.byType(LoginButton));
|
|
323
|
+
await tester.pumpAndSettle();
|
|
324
|
+
|
|
325
|
+
// Enter credentials
|
|
326
|
+
await tester.enterText(find.byType(EmailField), 'test@example.com');
|
|
327
|
+
await tester.enterText(find.byType(PasswordField), 'password123');
|
|
328
|
+
|
|
329
|
+
// Submit form
|
|
330
|
+
await tester.tap(find.byType(SubmitButton));
|
|
331
|
+
await tester.pumpAndSettle();
|
|
332
|
+
|
|
333
|
+
// Verify navigation
|
|
334
|
+
expect(find.byType(HomePage), findsOneWidget);
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## Framework Best Practices
|
|
342
|
+
|
|
343
|
+
### State Management with Provider
|
|
344
|
+
```dart
|
|
345
|
+
// Provider pattern example
|
|
346
|
+
class CounterNotifier extends ChangeNotifier {
|
|
347
|
+
int _count = 0;
|
|
348
|
+
|
|
349
|
+
int get count => _count;
|
|
350
|
+
|
|
351
|
+
void increment() {
|
|
352
|
+
DebugLogger.entry('CounterNotifier', 'increment', {'currentCount': _count});
|
|
353
|
+
_count++;
|
|
354
|
+
notifyListeners();
|
|
355
|
+
DebugLogger.exit('CounterNotifier', 'increment', _count, DateTime.now());
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Usage in widget
|
|
360
|
+
class CounterWidget extends StatelessWidget {
|
|
361
|
+
@override
|
|
362
|
+
Widget build(BuildContext context) {
|
|
363
|
+
return Consumer<CounterNotifier>(
|
|
364
|
+
builder: (context, counter, child) {
|
|
365
|
+
return Text('Count: ${counter.count}');
|
|
366
|
+
},
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### BLoC Pattern
|
|
373
|
+
```dart
|
|
374
|
+
// BLoC pattern example
|
|
375
|
+
class CounterBloc extends Bloc<CounterEvent, CounterState> {
|
|
376
|
+
CounterBloc() : super(CounterInitial()) {
|
|
377
|
+
on<IncrementEvent>((event, emit) {
|
|
378
|
+
DebugLogger.entry('CounterBloc', 'IncrementEvent', {'state': state});
|
|
379
|
+
emit(CounterState(count: state.count + 1));
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### Navigation
|
|
386
|
+
```dart
|
|
387
|
+
// Named routes navigation
|
|
388
|
+
class AppRouter {
|
|
389
|
+
static const String home = '/';
|
|
390
|
+
static const String profile = '/profile';
|
|
391
|
+
static const String settings = '/settings';
|
|
392
|
+
|
|
393
|
+
static Route<dynamic> generateRoute(RouteSettings settings) {
|
|
394
|
+
DebugLogger.entry('AppRouter', 'generateRoute', {'route': settings.name});
|
|
395
|
+
|
|
396
|
+
switch (settings.name) {
|
|
397
|
+
case home:
|
|
398
|
+
return MaterialPageRoute(builder: (_) => HomePage());
|
|
399
|
+
case profile:
|
|
400
|
+
return MaterialPageRoute(builder: (_) => ProfilePage());
|
|
401
|
+
case settings:
|
|
402
|
+
return MaterialPageRoute(builder: (_) => SettingsPage());
|
|
403
|
+
default:
|
|
404
|
+
return MaterialPageRoute(builder: (_) => NotFoundPage());
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
## Error Handling Patterns
|
|
413
|
+
|
|
414
|
+
### Comprehensive Error Handling
|
|
415
|
+
```dart
|
|
416
|
+
// Custom exception classes
|
|
417
|
+
class ApplicationException implements Exception {
|
|
418
|
+
final String message;
|
|
419
|
+
final int? statusCode;
|
|
420
|
+
final Map<String, dynamic>? context;
|
|
421
|
+
|
|
422
|
+
ApplicationException(this.message, {this.statusCode, this.context});
|
|
423
|
+
|
|
424
|
+
@override
|
|
425
|
+
String toString() => 'ApplicationException: $message';
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
class NetworkException extends ApplicationException {
|
|
429
|
+
NetworkException(String message, {Map<String, dynamic>? context})
|
|
430
|
+
: super(message, statusCode: 500, context: context);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
class ValidationException extends ApplicationException {
|
|
434
|
+
ValidationException(String message, {Map<String, dynamic>? context})
|
|
435
|
+
: super(message, statusCode: 400, context: context);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Error handling function
|
|
439
|
+
Future<T> safeOperation<T>(
|
|
440
|
+
Future<T> Function() operation,
|
|
441
|
+
String context,
|
|
442
|
+
) async {
|
|
443
|
+
try {
|
|
444
|
+
return await operation();
|
|
445
|
+
} catch (e, stackTrace) {
|
|
446
|
+
DebugLogger.error('SafeOperation', context, e, stackTrace);
|
|
447
|
+
|
|
448
|
+
if (e is SocketException) {
|
|
449
|
+
throw NetworkException('Network connection failed', context: {'error': e.toString()});
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
rethrow;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
### Global Error Handler
|
|
458
|
+
```dart
|
|
459
|
+
// Global error handling
|
|
460
|
+
void main() {
|
|
461
|
+
FlutterError.onError = (FlutterErrorDetails details) {
|
|
462
|
+
DebugLogger.error(
|
|
463
|
+
'Flutter',
|
|
464
|
+
'onError',
|
|
465
|
+
details.exception,
|
|
466
|
+
details.stack,
|
|
467
|
+
context: {'library': details.library},
|
|
468
|
+
);
|
|
469
|
+
|
|
470
|
+
// Report to crash analytics in production
|
|
471
|
+
if (kReleaseMode) {
|
|
472
|
+
// FirebaseCrashlytics.instance.recordFlutterError(details);
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
PlatformDispatcher.instance.onError = (error, stack) {
|
|
477
|
+
DebugLogger.error('Platform', 'onError', error, stack);
|
|
478
|
+
|
|
479
|
+
if (kReleaseMode) {
|
|
480
|
+
// Report to crash analytics
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
return true;
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
runApp(const MyApp());
|
|
487
|
+
}
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
---
|
|
491
|
+
|
|
492
|
+
## Technology-Specific Command References
|
|
493
|
+
|
|
494
|
+
### Development Commands
|
|
495
|
+
```bash
|
|
496
|
+
# Flutter Development
|
|
497
|
+
flutter run # Run app in debug mode
|
|
498
|
+
flutter run -d chrome # Run on Chrome
|
|
499
|
+
flutter run -d ios # Run on iOS simulator
|
|
500
|
+
flutter run --release # Run in release mode
|
|
501
|
+
|
|
502
|
+
# Hot Reload & Restart
|
|
503
|
+
# Press 'r' in terminal for hot reload
|
|
504
|
+
# Press 'R' in terminal for hot restart
|
|
505
|
+
|
|
506
|
+
# Dependencies
|
|
507
|
+
flutter pub get # Get dependencies
|
|
508
|
+
flutter pub upgrade # Upgrade dependencies
|
|
509
|
+
flutter pub outdated # Check outdated packages
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
### Testing Commands
|
|
513
|
+
```bash
|
|
514
|
+
# Testing
|
|
515
|
+
flutter test # Run unit tests
|
|
516
|
+
flutter test --coverage # Generate coverage
|
|
517
|
+
flutter test integration_test/app_test.dart # Integration tests
|
|
518
|
+
flutter drive --target=test_driver/app.dart # Driver tests
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
### Build Commands
|
|
522
|
+
```bash
|
|
523
|
+
# Building
|
|
524
|
+
flutter build apk # Build Android APK
|
|
525
|
+
flutter build appbundle # Build Android App Bundle
|
|
526
|
+
flutter build ios # Build iOS app
|
|
527
|
+
flutter build web # Build web app
|
|
528
|
+
flutter build windows # Build Windows app
|
|
529
|
+
|
|
530
|
+
# Clean & Rebuild
|
|
531
|
+
flutter clean # Clean build files
|
|
532
|
+
flutter pub get # Get dependencies
|
|
533
|
+
flutter build apk # Rebuild
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
---
|
|
537
|
+
|
|
538
|
+
## Component-Level Customizations
|
|
539
|
+
|
|
540
|
+
### Project Structure
|
|
541
|
+
```
|
|
542
|
+
{{SOURCE_DIR}}/
|
|
543
|
+
├── main.dart # App entry point
|
|
544
|
+
├── app.dart # App widget
|
|
545
|
+
├── screens/ # Screen widgets
|
|
546
|
+
├── widgets/ # Reusable widgets
|
|
547
|
+
├── models/ # Data models
|
|
548
|
+
├── services/ # Business logic
|
|
549
|
+
├── providers/ # State management
|
|
550
|
+
├── utils/ # Utility functions
|
|
551
|
+
├── constants/ # App constants
|
|
552
|
+
└── theme/ # Theme configuration
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
### Asset Management
|
|
556
|
+
```yaml
|
|
557
|
+
# pubspec.yaml
|
|
558
|
+
flutter:
|
|
559
|
+
assets:
|
|
560
|
+
- assets/images/
|
|
561
|
+
- assets/icons/
|
|
562
|
+
- assets/fonts/
|
|
563
|
+
|
|
564
|
+
fonts:
|
|
565
|
+
- family: CustomFont
|
|
566
|
+
fonts:
|
|
567
|
+
- asset: assets/fonts/CustomFont-Regular.ttf
|
|
568
|
+
- asset: assets/fonts/CustomFont-Bold.ttf
|
|
569
|
+
weight: 700
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
---
|
|
573
|
+
|
|
574
|
+
## Reference to Parent Context
|
|
575
|
+
|
|
576
|
+
This file extends the Trinity Method protocols defined in `../.claude/trinity/CLAUDE.md` and global requirements from `../CLAUDE.md`. Flutter/Dart implementations must comply with:
|
|
577
|
+
|
|
578
|
+
- Trinity Method investigation requirements ([../.claude/trinity/CLAUDE.md](../.claude/trinity/CLAUDE.md))
|
|
579
|
+
- Global performance baselines ([../.claude/trinity/knowledge-base/ARCHITECTURE.md](../.claude/trinity/knowledge-base/ARCHITECTURE.md#performance-baseline))
|
|
580
|
+
- Quality gate standards (BAS 6-phase) ([../.claude/trinity/CLAUDE.md](../.claude/trinity/CLAUDE.md#quality-standards))
|
|
581
|
+
- Crisis management protocols ([../.claude/trinity/CLAUDE.md](../.claude/trinity/CLAUDE.md#crisis-management))
|
|
582
|
+
|
|
583
|
+
All Flutter code must implement the debugging frameworks, error handling patterns, and performance monitoring specified in this document.
|
|
584
|
+
|
|
585
|
+
---
|
|
586
|
+
|
|
587
|
+
**Technology Context**: Flutter/Dart Implementation
|
|
588
|
+
**Parent References**:
|
|
589
|
+
- `../CLAUDE.md` - Global project requirements
|
|
590
|
+
- `../.claude/trinity/CLAUDE.md` - Trinity Method enforcement
|
|
591
|
+
|
|
592
|
+
**Last Updated**: {{CURRENT_DATE}}
|
|
593
|
+
**Trinity Version**: {{TRINITY_VERSION}}
|