oh-my-ag 1.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.
Files changed (77) hide show
  1. package/.agent/skills/_shared/api-contracts/README.md +56 -0
  2. package/.agent/skills/_shared/api-contracts/template.md +88 -0
  3. package/.agent/skills/_shared/clarification-protocol.md +217 -0
  4. package/.agent/skills/_shared/common-checklist.md +31 -0
  5. package/.agent/skills/_shared/context-budget.md +118 -0
  6. package/.agent/skills/_shared/context-loading.md +105 -0
  7. package/.agent/skills/_shared/difficulty-guide.md +55 -0
  8. package/.agent/skills/_shared/lessons-learned.md +113 -0
  9. package/.agent/skills/_shared/memory-protocol.md +79 -0
  10. package/.agent/skills/_shared/reasoning-templates.md +161 -0
  11. package/.agent/skills/_shared/skill-routing.md +80 -0
  12. package/.agent/skills/_shared/verify.sh +252 -0
  13. package/.agent/skills/backend-agent/SKILL.md +47 -0
  14. package/.agent/skills/backend-agent/resources/api-template.py +326 -0
  15. package/.agent/skills/backend-agent/resources/checklist.md +36 -0
  16. package/.agent/skills/backend-agent/resources/error-playbook.md +98 -0
  17. package/.agent/skills/backend-agent/resources/examples.md +85 -0
  18. package/.agent/skills/backend-agent/resources/execution-protocol.md +45 -0
  19. package/.agent/skills/backend-agent/resources/snippets.md +197 -0
  20. package/.agent/skills/backend-agent/resources/tech-stack.md +39 -0
  21. package/.agent/skills/commit/SKILL.md +121 -0
  22. package/.agent/skills/commit/config/commit-config.yaml +55 -0
  23. package/.agent/skills/commit/resources/conventional-commits.md +166 -0
  24. package/.agent/skills/debug-agent/SKILL.md +51 -0
  25. package/.agent/skills/debug-agent/resources/bug-report-template.md +332 -0
  26. package/.agent/skills/debug-agent/resources/checklist.md +30 -0
  27. package/.agent/skills/debug-agent/resources/common-patterns.md +734 -0
  28. package/.agent/skills/debug-agent/resources/debugging-checklist.md +362 -0
  29. package/.agent/skills/debug-agent/resources/error-playbook.md +94 -0
  30. package/.agent/skills/debug-agent/resources/examples.md +87 -0
  31. package/.agent/skills/debug-agent/resources/execution-protocol.md +51 -0
  32. package/.agent/skills/frontend-agent/SKILL.md +48 -0
  33. package/.agent/skills/frontend-agent/resources/checklist.md +38 -0
  34. package/.agent/skills/frontend-agent/resources/component-template.tsx +92 -0
  35. package/.agent/skills/frontend-agent/resources/error-playbook.md +108 -0
  36. package/.agent/skills/frontend-agent/resources/examples.md +77 -0
  37. package/.agent/skills/frontend-agent/resources/execution-protocol.md +49 -0
  38. package/.agent/skills/frontend-agent/resources/snippets.md +205 -0
  39. package/.agent/skills/frontend-agent/resources/tailwind-rules.md +343 -0
  40. package/.agent/skills/frontend-agent/resources/tech-stack.md +36 -0
  41. package/.agent/skills/mobile-agent/SKILL.md +46 -0
  42. package/.agent/skills/mobile-agent/resources/checklist.md +35 -0
  43. package/.agent/skills/mobile-agent/resources/error-playbook.md +106 -0
  44. package/.agent/skills/mobile-agent/resources/examples.md +79 -0
  45. package/.agent/skills/mobile-agent/resources/execution-protocol.md +49 -0
  46. package/.agent/skills/mobile-agent/resources/screen-template.dart +298 -0
  47. package/.agent/skills/mobile-agent/resources/snippets.md +235 -0
  48. package/.agent/skills/mobile-agent/resources/tech-stack.md +45 -0
  49. package/.agent/skills/orchestrator/SKILL.md +99 -0
  50. package/.agent/skills/orchestrator/config/cli-config.yaml +78 -0
  51. package/.agent/skills/orchestrator/resources/memory-schema.md +212 -0
  52. package/.agent/skills/orchestrator/resources/subagent-prompt-template.md +153 -0
  53. package/.agent/skills/orchestrator/scripts/parallel-run.sh +330 -0
  54. package/.agent/skills/orchestrator/scripts/spawn-agent.sh +263 -0
  55. package/.agent/skills/orchestrator/templates/backend-task.md +18 -0
  56. package/.agent/skills/orchestrator/templates/debug-task.md +16 -0
  57. package/.agent/skills/orchestrator/templates/frontend-task.md +17 -0
  58. package/.agent/skills/orchestrator/templates/mobile-task.md +17 -0
  59. package/.agent/skills/orchestrator/templates/qa-task.md +16 -0
  60. package/.agent/skills/orchestrator/templates/tasks-example.yaml +15 -0
  61. package/.agent/skills/pm-agent/SKILL.md +47 -0
  62. package/.agent/skills/pm-agent/resources/error-playbook.md +75 -0
  63. package/.agent/skills/pm-agent/resources/examples.md +121 -0
  64. package/.agent/skills/pm-agent/resources/execution-protocol.md +46 -0
  65. package/.agent/skills/pm-agent/resources/task-template.json +57 -0
  66. package/.agent/skills/qa-agent/SKILL.md +43 -0
  67. package/.agent/skills/qa-agent/resources/checklist.md +294 -0
  68. package/.agent/skills/qa-agent/resources/error-playbook.md +95 -0
  69. package/.agent/skills/qa-agent/resources/examples.md +100 -0
  70. package/.agent/skills/qa-agent/resources/execution-protocol.md +50 -0
  71. package/.agent/skills/qa-agent/resources/self-check.md +27 -0
  72. package/.agent/skills/workflow-guide/SKILL.md +57 -0
  73. package/.agent/skills/workflow-guide/resources/examples.md +68 -0
  74. package/README.ko.md +459 -0
  75. package/README.md +563 -0
  76. package/bin/cli.js +205 -0
  77. package/package.json +75 -0
@@ -0,0 +1,298 @@
1
+ /**
2
+ * Screen Template for Mobile Agent (Flutter)
3
+ *
4
+ * This template demonstrates best practices for Flutter screens.
5
+ */
6
+
7
+ import 'package:flutter/material.dart';
8
+ import 'package:flutter_riverpod/flutter_riverpod.dart';
9
+
10
+ // Provider definition (in separate file: providers/example_providers.dart)
11
+ /*
12
+ final exampleProvider = FutureProvider<List<ExampleModel>>((ref) async {
13
+ final repository = ref.watch(exampleRepositoryProvider);
14
+ return repository.fetchData();
15
+ });
16
+ */
17
+
18
+ /// Example screen demonstrating common patterns
19
+ class ExampleScreen extends ConsumerStatefulWidget {
20
+ /// Route name for navigation
21
+ static const routeName = '/example';
22
+
23
+ /// Constructor
24
+ const ExampleScreen({super.key});
25
+
26
+ @override
27
+ ConsumerState<ExampleScreen> createState() => _ExampleScreenState();
28
+ }
29
+
30
+ class _ExampleScreenState extends ConsumerState<ExampleScreen> {
31
+ // Local state (if needed)
32
+ final _scrollController = ScrollController();
33
+ bool _showScrollToTop = false;
34
+
35
+ @override
36
+ void initState() {
37
+ super.initState();
38
+ _setupScrollListener();
39
+ }
40
+
41
+ @override
42
+ void dispose() {
43
+ _scrollController.dispose();
44
+ super.dispose();
45
+ }
46
+
47
+ void _setupScrollListener() {
48
+ _scrollController.addListener(() {
49
+ final shouldShow = _scrollController.offset > 200;
50
+ if (shouldShow != _showScrollToTop) {
51
+ setState(() => _showScrollToTop = shouldShow);
52
+ }
53
+ });
54
+ }
55
+
56
+ @override
57
+ Widget build(BuildContext context) {
58
+ // Watch providers
59
+ final dataAsync = ref.watch(exampleProvider);
60
+
61
+ return Scaffold(
62
+ // App bar
63
+ appBar: AppBar(
64
+ title: const Text('Example Screen'),
65
+ actions: [
66
+ IconButton(
67
+ icon: const Icon(Icons.refresh),
68
+ onPressed: () => ref.invalidate(exampleProvider),
69
+ tooltip: 'Refresh',
70
+ ),
71
+ IconButton(
72
+ icon: const Icon(Icons.settings),
73
+ onPressed: _navigateToSettings,
74
+ tooltip: 'Settings',
75
+ ),
76
+ ],
77
+ ),
78
+
79
+ // Body with async handling
80
+ body: dataAsync.when(
81
+ // Success state
82
+ data: (items) => _buildContent(items),
83
+
84
+ // Loading state
85
+ loading: () => const Center(
86
+ child: CircularProgressIndicator(),
87
+ ),
88
+
89
+ // Error state
90
+ error: (error, stackTrace) => _buildErrorState(error),
91
+ ),
92
+
93
+ // Floating action button
94
+ floatingActionButton: _showScrollToTop
95
+ ? FloatingActionButton(
96
+ onPressed: _scrollToTop,
97
+ child: const Icon(Icons.arrow_upward),
98
+ )
99
+ : null,
100
+ );
101
+ }
102
+
103
+ /// Builds main content
104
+ Widget _buildContent(List<dynamic> items) {
105
+ if (items.isEmpty) {
106
+ return _buildEmptyState();
107
+ }
108
+
109
+ return RefreshIndicator(
110
+ onRefresh: _handleRefresh,
111
+ child: CustomScrollView(
112
+ controller: _scrollController,
113
+ slivers: [
114
+ // Header
115
+ SliverToBoxAdapter(
116
+ child: Padding(
117
+ padding: const EdgeInsets.all(16),
118
+ child: Text(
119
+ '${items.length} Items',
120
+ style: Theme.of(context).textTheme.titleMedium,
121
+ ),
122
+ ),
123
+ ),
124
+
125
+ // List
126
+ SliverList(
127
+ delegate: SliverChildBuilderDelegate(
128
+ (context, index) {
129
+ final item = items[index];
130
+ return _buildListItem(item, index);
131
+ },
132
+ childCount: items.length,
133
+ ),
134
+ ),
135
+ ],
136
+ ),
137
+ );
138
+ }
139
+
140
+ /// Builds individual list item
141
+ Widget _buildListItem(dynamic item, int index) {
142
+ return Card(
143
+ margin: const EdgeInsets.symmetric(
144
+ horizontal: 16,
145
+ vertical: 8,
146
+ ),
147
+ child: ListTile(
148
+ leading: CircleAvatar(
149
+ child: Text('${index + 1}'),
150
+ ),
151
+ title: Text(item.title ?? 'Untitled'),
152
+ subtitle: Text(item.description ?? ''),
153
+ trailing: IconButton(
154
+ icon: const Icon(Icons.chevron_right),
155
+ onPressed: () => _navigateToDetail(item),
156
+ ),
157
+ onTap: () => _navigateToDetail(item),
158
+ ),
159
+ );
160
+ }
161
+
162
+ /// Builds empty state
163
+ Widget _buildEmptyState() {
164
+ return Center(
165
+ child: Column(
166
+ mainAxisAlignment: MainAxisAlignment.center,
167
+ children: [
168
+ Icon(
169
+ Icons.inbox,
170
+ size: 64,
171
+ color: Theme.of(context).colorScheme.secondary,
172
+ ),
173
+ const SizedBox(height: 16),
174
+ Text(
175
+ 'No items yet',
176
+ style: Theme.of(context).textTheme.titleLarge,
177
+ ),
178
+ const SizedBox(height: 8),
179
+ Text(
180
+ 'Add your first item to get started',
181
+ style: Theme.of(context).textTheme.bodyMedium?.copyWith(
182
+ color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6),
183
+ ),
184
+ ),
185
+ const SizedBox(height: 24),
186
+ ElevatedButton.icon(
187
+ onPressed: _showAddDialog,
188
+ icon: const Icon(Icons.add),
189
+ label: const Text('Add Item'),
190
+ ),
191
+ ],
192
+ ),
193
+ );
194
+ }
195
+
196
+ /// Builds error state
197
+ Widget _buildErrorState(Object error) {
198
+ return Center(
199
+ child: Padding(
200
+ padding: const EdgeInsets.all(24),
201
+ child: Column(
202
+ mainAxisAlignment: MainAxisAlignment.center,
203
+ children: [
204
+ Icon(
205
+ Icons.error_outline,
206
+ size: 64,
207
+ color: Theme.of(context).colorScheme.error,
208
+ ),
209
+ const SizedBox(height: 16),
210
+ Text(
211
+ 'Oops! Something went wrong',
212
+ style: Theme.of(context).textTheme.titleLarge,
213
+ textAlign: TextAlign.center,
214
+ ),
215
+ const SizedBox(height: 8),
216
+ Text(
217
+ error.toString(),
218
+ style: Theme.of(context).textTheme.bodyMedium?.copyWith(
219
+ color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6),
220
+ ),
221
+ textAlign: TextAlign.center,
222
+ ),
223
+ const SizedBox(height: 24),
224
+ ElevatedButton.icon(
225
+ onPressed: () => ref.invalidate(exampleProvider),
226
+ icon: const Icon(Icons.refresh),
227
+ label: const Text('Try Again'),
228
+ ),
229
+ ],
230
+ ),
231
+ ),
232
+ );
233
+ }
234
+
235
+ // Event handlers
236
+
237
+ Future<void> _handleRefresh() async {
238
+ await ref.refresh(exampleProvider.future);
239
+ }
240
+
241
+ void _scrollToTop() {
242
+ _scrollController.animateTo(
243
+ 0,
244
+ duration: const Duration(milliseconds: 500),
245
+ curve: Curves.easeOut,
246
+ );
247
+ }
248
+
249
+ void _navigateToDetail(dynamic item) {
250
+ Navigator.of(context).pushNamed(
251
+ '/detail',
252
+ arguments: item,
253
+ );
254
+ }
255
+
256
+ void _navigateToSettings() {
257
+ Navigator.of(context).pushNamed('/settings');
258
+ }
259
+
260
+ void _showAddDialog() {
261
+ showDialog(
262
+ context: context,
263
+ builder: (context) => AlertDialog(
264
+ title: const Text('Add Item'),
265
+ content: TextField(
266
+ decoration: const InputDecoration(
267
+ labelText: 'Title',
268
+ hintText: 'Enter title',
269
+ ),
270
+ onSubmitted: (value) {
271
+ // Handle submission
272
+ Navigator.of(context).pop();
273
+ },
274
+ ),
275
+ actions: [
276
+ TextButton(
277
+ onPressed: () => Navigator.of(context).pop(),
278
+ child: const Text('Cancel'),
279
+ ),
280
+ ElevatedButton(
281
+ onPressed: () {
282
+ // Handle add
283
+ Navigator.of(context).pop();
284
+ },
285
+ child: const Text('Add'),
286
+ ),
287
+ ],
288
+ ),
289
+ );
290
+ }
291
+ }
292
+
293
+ // Placeholder provider (move to separate file)
294
+ final exampleProvider = FutureProvider<List<dynamic>>((ref) async {
295
+ // Simulate API call
296
+ await Future.delayed(const Duration(seconds: 1));
297
+ return [];
298
+ });
@@ -0,0 +1,235 @@
1
+ # Mobile Agent - Code Snippets
2
+
3
+ Copy-paste ready patterns. Use these as starting points, adapt to the specific task.
4
+
5
+ ---
6
+
7
+ ## Riverpod AsyncNotifier
8
+
9
+ ```dart
10
+ import 'package:riverpod_annotation/riverpod_annotation.dart';
11
+
12
+ part 'todo_provider.g.dart';
13
+
14
+ @riverpod
15
+ class TodoList extends _$TodoList {
16
+ @override
17
+ Future<List<Todo>> build() async {
18
+ final repository = ref.watch(todoRepositoryProvider);
19
+ return repository.fetchAll();
20
+ }
21
+
22
+ Future<void> add(String title) async {
23
+ final repository = ref.read(todoRepositoryProvider);
24
+ await repository.create(title);
25
+ ref.invalidateSelf();
26
+ }
27
+
28
+ Future<void> toggle(String id) async {
29
+ final repository = ref.read(todoRepositoryProvider);
30
+ await repository.toggle(id);
31
+ ref.invalidateSelf();
32
+ }
33
+
34
+ Future<void> delete(String id) async {
35
+ final repository = ref.read(todoRepositoryProvider);
36
+ await repository.delete(id);
37
+ ref.invalidateSelf();
38
+ }
39
+ }
40
+ ```
41
+
42
+ ---
43
+
44
+ ## Screen with AsyncValue
45
+
46
+ ```dart
47
+ import 'package:flutter/material.dart';
48
+ import 'package:flutter_riverpod/flutter_riverpod.dart';
49
+
50
+ class TodoListScreen extends ConsumerWidget {
51
+ const TodoListScreen({super.key});
52
+
53
+ @override
54
+ Widget build(BuildContext context, WidgetRef ref) {
55
+ final todosAsync = ref.watch(todoListProvider);
56
+
57
+ return Scaffold(
58
+ appBar: AppBar(title: const Text('Todos')),
59
+ body: todosAsync.when(
60
+ loading: () => const Center(child: CircularProgressIndicator()),
61
+ error: (error, stack) => Center(
62
+ child: Column(
63
+ mainAxisSize: MainAxisSize.min,
64
+ children: [
65
+ Text('Error: $error'),
66
+ const SizedBox(height: 8),
67
+ ElevatedButton(
68
+ onPressed: () => ref.invalidate(todoListProvider),
69
+ child: const Text('Retry'),
70
+ ),
71
+ ],
72
+ ),
73
+ ),
74
+ data: (todos) => todos.isEmpty
75
+ ? const Center(child: Text('No todos yet'))
76
+ : ListView.builder(
77
+ itemCount: todos.length,
78
+ itemBuilder: (context, index) => TodoItem(todo: todos[index]),
79
+ ),
80
+ ),
81
+ floatingActionButton: FloatingActionButton(
82
+ onPressed: () => _showAddDialog(context, ref),
83
+ child: const Icon(Icons.add),
84
+ ),
85
+ );
86
+ }
87
+ }
88
+ ```
89
+
90
+ ---
91
+
92
+ ## Repository Pattern
93
+
94
+ ```dart
95
+ abstract class TodoRepository {
96
+ Future<List<Todo>> fetchAll();
97
+ Future<Todo> create(String title);
98
+ Future<void> toggle(String id);
99
+ Future<void> delete(String id);
100
+ }
101
+
102
+ class TodoRepositoryImpl implements TodoRepository {
103
+ final Dio _dio;
104
+
105
+ TodoRepositoryImpl(this._dio);
106
+
107
+ @override
108
+ Future<List<Todo>> fetchAll() async {
109
+ final response = await _dio.get('/api/todos');
110
+ return (response.data as List).map((e) => Todo.fromJson(e)).toList();
111
+ }
112
+
113
+ @override
114
+ Future<Todo> create(String title) async {
115
+ final response = await _dio.post('/api/todos', data: {'title': title});
116
+ return Todo.fromJson(response.data);
117
+ }
118
+
119
+ @override
120
+ Future<void> toggle(String id) async {
121
+ await _dio.patch('/api/todos/$id/toggle');
122
+ }
123
+
124
+ @override
125
+ Future<void> delete(String id) async {
126
+ await _dio.delete('/api/todos/$id');
127
+ }
128
+ }
129
+ ```
130
+
131
+ ---
132
+
133
+ ## Dio with Auth Interceptor
134
+
135
+ ```dart
136
+ class AuthInterceptor extends Interceptor {
137
+ final Ref _ref;
138
+
139
+ AuthInterceptor(this._ref);
140
+
141
+ @override
142
+ void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
143
+ final token = _ref.read(authProvider).accessToken;
144
+ if (token != null) {
145
+ options.headers['Authorization'] = 'Bearer $token';
146
+ }
147
+ handler.next(options);
148
+ }
149
+
150
+ @override
151
+ void onError(DioException err, ErrorInterceptorHandler handler) {
152
+ if (err.response?.statusCode == 401) {
153
+ _ref.read(authProvider.notifier).logout();
154
+ }
155
+ handler.next(err);
156
+ }
157
+ }
158
+ ```
159
+
160
+ ---
161
+
162
+ ## GoRouter Config
163
+
164
+ ```dart
165
+ final routerProvider = Provider<GoRouter>((ref) {
166
+ final auth = ref.watch(authProvider);
167
+
168
+ return GoRouter(
169
+ redirect: (context, state) {
170
+ final isLoggedIn = auth.isAuthenticated;
171
+ final isAuthRoute = state.matchedLocation.startsWith('/auth');
172
+
173
+ if (!isLoggedIn && !isAuthRoute) return '/auth/login';
174
+ if (isLoggedIn && isAuthRoute) return '/';
175
+ return null;
176
+ },
177
+ routes: [
178
+ GoRoute(path: '/', builder: (_, __) => const HomeScreen()),
179
+ GoRoute(path: '/auth/login', builder: (_, __) => const LoginScreen()),
180
+ GoRoute(path: '/todos', builder: (_, __) => const TodoListScreen()),
181
+ ],
182
+ );
183
+ });
184
+ ```
185
+
186
+ ---
187
+
188
+ ## Entity (freezed)
189
+
190
+ ```dart
191
+ import 'package:freezed_annotation/freezed_annotation.dart';
192
+
193
+ part 'todo.freezed.dart';
194
+ part 'todo.g.dart';
195
+
196
+ @freezed
197
+ class Todo with _$Todo {
198
+ const factory Todo({
199
+ required String id,
200
+ required String title,
201
+ @Default(false) bool completed,
202
+ required DateTime createdAt,
203
+ }) = _Todo;
204
+
205
+ factory Todo.fromJson(Map<String, dynamic> json) => _$TodoFromJson(json);
206
+ }
207
+ ```
208
+
209
+ ---
210
+
211
+ ## Widget Test
212
+
213
+ ```dart
214
+ import 'package:flutter_test/flutter_test.dart';
215
+ import 'package:flutter_riverpod/flutter_riverpod.dart';
216
+
217
+ void main() {
218
+ testWidgets('TodoListScreen shows loading then data', (tester) async {
219
+ await tester.pumpWidget(
220
+ ProviderScope(
221
+ overrides: [
222
+ todoListProvider.overrideWith(() => MockTodoList()),
223
+ ],
224
+ child: const MaterialApp(home: TodoListScreen()),
225
+ ),
226
+ );
227
+
228
+ expect(find.byType(CircularProgressIndicator), findsOneWidget);
229
+
230
+ await tester.pumpAndSettle();
231
+
232
+ expect(find.text('Test Todo'), findsOneWidget);
233
+ });
234
+ }
235
+ ```
@@ -0,0 +1,45 @@
1
+ # Mobile Agent - Tech Stack Reference
2
+
3
+ ## Flutter (Recommended)
4
+ - **Framework**: Flutter 3.19+
5
+ - **Language**: Dart 3.3+
6
+ - **State**: Riverpod 2.4+, Bloc, Provider
7
+ - **Navigation**: GoRouter 13+
8
+ - **API Client**: Dio
9
+ - **Local Storage**: Drift, Hive
10
+ - **Testing**: flutter_test, mockito
11
+
12
+ ## React Native (Alternative)
13
+ - **Framework**: React Native 0.73+
14
+ - **Language**: TypeScript
15
+ - **State**: Redux Toolkit, Zustand
16
+ - **Navigation**: React Navigation 6+
17
+ - **Testing**: Jest, React Native Testing Library
18
+
19
+ ## Project Structure (Flutter)
20
+
21
+ ```
22
+ lib/
23
+ main.dart
24
+ core/ # Theme, router, utils
25
+ features/
26
+ [feature]/
27
+ data/ # Models, repositories
28
+ domain/ # Entities, use cases
29
+ presentation/ # Screens, widgets, providers
30
+ shared/ # Shared widgets
31
+ ```
32
+
33
+ ## Architecture Pattern
34
+
35
+ Clean Architecture with Riverpod:
36
+ 1. Entity (Domain) - Pure business objects
37
+ 2. Repository Interface (Domain) - Abstract data access
38
+ 3. Repository Implementation (Data) - Dio, database
39
+ 4. Providers (Presentation) - State management
40
+ 5. Screens/Widgets (Presentation) - UI
41
+
42
+ ## Platform Guidelines
43
+ - Material Design 3 for Android
44
+ - iOS Human Interface Guidelines for iOS
45
+ - Use `Platform.isIOS` for platform-specific code
@@ -0,0 +1,99 @@
1
+ ---
2
+ name: orchestrator
3
+ description: Automated multi-agent orchestrator that spawns CLI subagents in parallel, coordinates via MCP Memory, and monitors progress
4
+ ---
5
+
6
+ # Orchestrator - Automated Multi-Agent Coordinator
7
+
8
+ ## When to use
9
+ - Complex feature requires multiple specialized agents working in parallel
10
+ - User wants automated execution without manually spawning agents
11
+ - Full-stack implementation spanning backend, frontend, mobile, and QA
12
+ - User says "자동으로 실행해줘", "병렬로 돌려줘", or similar automation requests
13
+
14
+ ## When NOT to use
15
+ - Simple single-domain task -> use the specific agent directly
16
+ - User wants step-by-step manual control -> use workflow-guide
17
+ - Quick bug fixes or minor changes
18
+
19
+ ## Important
20
+ This skill orchestrates CLI subagents via `gemini -p "..." --approval-mode=yolo`. It uses MCP Memory tools as a shared state bus. Each subagent runs as an independent process.
21
+
22
+ ## Configuration
23
+
24
+ | Setting | Default | Description |
25
+ |---------|---------|-------------|
26
+ | MAX_PARALLEL | 3 | Max concurrent subagents |
27
+ | MAX_RETRIES | 2 | Retry attempts per failed task |
28
+ | POLL_INTERVAL | 30s | Status check interval |
29
+ | MAX_TURNS (impl) | 20 | Turn limit for backend/frontend/mobile |
30
+ | MAX_TURNS (review) | 15 | Turn limit for qa/debug |
31
+ | MAX_TURNS (plan) | 10 | Turn limit for pm |
32
+
33
+ ## Memory Configuration
34
+
35
+ Memory provider and tool names are configurable via `mcp.json`:
36
+ ```json
37
+ {
38
+ "memoryConfig": {
39
+ "provider": "serena",
40
+ "basePath": ".serena/memories",
41
+ "tools": {
42
+ "read": "read_memory",
43
+ "write": "write_memory",
44
+ "edit": "edit_memory"
45
+ }
46
+ }
47
+ }
48
+ ```
49
+
50
+ ## Workflow Phases
51
+
52
+ **PHASE 1 - Plan**: Analyze request -> decompose tasks -> generate session ID
53
+ **PHASE 2 - Setup**: Use memory write tool to create `orchestrator-session.md` + `task-board.md`
54
+ **PHASE 3 - Execute**: Spawn agents by priority tier (never exceed MAX_PARALLEL)
55
+ **PHASE 4 - Monitor**: Poll every POLL_INTERVAL; handle completed/failed/crashed agents
56
+ **PHASE 4.5 - Verify**: Run `../_shared/verify.sh {agent-type} {workspace}` per completed agent
57
+ **PHASE 5 - Collect**: Read all `result-{agent}.md`, compile summary, cleanup progress files
58
+
59
+ See `resources/subagent-prompt-template.md` for prompt construction.
60
+ See `resources/memory-schema.md` for memory file formats.
61
+
62
+ ## Memory File Ownership
63
+
64
+ | File | Owner | Others |
65
+ |------|-------|--------|
66
+ | `orchestrator-session.md` | orchestrator | read-only |
67
+ | `task-board.md` | orchestrator | read-only |
68
+ | `progress-{agent}.md` | that agent | orchestrator reads |
69
+ | `result-{agent}.md` | that agent | orchestrator reads |
70
+
71
+ ## Verification Gate (PHASE 4.5)
72
+ After each agent completes, run automated verification before accepting the result:
73
+ ```bash
74
+ bash .agent/skills/_shared/verify.sh {agent-type} {workspace}
75
+ ```
76
+ - **PASS (exit 0)**: Accept result, advance to next task
77
+ - **FAIL (exit 1)**: Treat as failure → enter Retry Logic with verify output as error context
78
+ - This is mandatory. Never skip verification even if the agent reports success.
79
+
80
+ ## Retry Logic
81
+ - 1st retry: Wait 30s, re-spawn with error context (include verify.sh output)
82
+ - 2nd retry: Wait 60s, add "Try a different approach"
83
+ - Final failure: Report to user, ask whether to continue or abort
84
+
85
+ ## References
86
+ - Prompt template: `resources/subagent-prompt-template.md`
87
+ - Memory schema: `resources/memory-schema.md`
88
+ - Config: `config/cli-config.yaml`
89
+ - Scripts: `scripts/spawn-agent.sh`, `scripts/parallel-run.sh`
90
+ - Task templates: `templates/`
91
+ - Skill routing: `../_shared/skill-routing.md`
92
+ - Verification: `../_shared/verify.sh`
93
+ - API contracts: `../_shared/api-contracts/`
94
+ - Context loading: `../_shared/context-loading.md`
95
+ - Difficulty guide: `../_shared/difficulty-guide.md`
96
+ - Reasoning templates: `../_shared/reasoning-templates.md`
97
+ - Clarification protocol: `../_shared/clarification-protocol.md`
98
+ - Context budget: `../_shared/context-budget.md`
99
+ - Lessons learned: `../_shared/lessons-learned.md`