@bdayadev/flutter-ultra-mcp 1.3.1 → 1.4.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.
@@ -1,21 +1,131 @@
1
1
  ---
2
- name: devtools
3
- description: Wiring up the Flutter DevTools panel for this plugin so the user can see live MCP activity inside their IDE. Use when the user wants to inspect the plugin's recent tool calls, attached sessions, or activity timeline.
4
- disable-model-invocation: true
2
+ name: flutter-devtools
3
+ description: Wiring up and using the flutter-ultra DevTools panel to inspect live MCP activity, attached sessions, and agent tool calls from inside the IDE. Use when the user wants to see the plugin's activity timeline, pause/resume agent flows from the panel, or stream screenshots to the DevTools view.
5
4
  ---
6
5
 
7
- # DevTools (stub)
6
+ # flutter-devtools — Wire Up the DevTools Panel
8
7
 
9
- **Status:** scaffold stub. Implementation owner: wave-3 skills worker (see plan §8.6, §12).
8
+ ## When to use
10
9
 
11
- User-triggered only installing a dev dependency and editing pubspec is opinionated.
10
+ Use this skill when the user wants to:
11
+
12
+ - See live MCP tool call activity inside Flutter DevTools while the agent is running.
13
+ - Pause or resume an automated agent flow from a panel button (human-in-the-loop).
14
+ - Stream screenshots or session events to the DevTools view during a tour or drive flow.
15
+ - Verify that the DevTools extension is correctly wired to the running MCP server.
16
+
17
+ ## Prerequisites
18
+
19
+ - The flutter-ultra-mcp plugin is already set up in the project (run `/flutter-setup` first if not).
20
+ - Flutter DevTools is open in the IDE (VS Code: `Dart: Open DevTools` from the command palette; Android Studio: via the Flutter Inspector toolbar).
21
+ - The DevTools extension tab labeled **flutter-ultra** must be visible. If it is not, the `ultra_flutter_devtools` package may not be in `dev_dependencies` — step 1 covers this.
12
22
 
13
23
  ## Workflow
14
24
 
15
- - Detect `ultra_flutter_devtools` in `dev_dependencies`; add via `mcp__flutter-ultra-build__pub_add` if missing.
16
- - Start the panel WebSocket via `mcp__flutter-ultra-devtools__start_panel_server`.
17
- - Print the DevTools URL with the `flutter-ultra` tab anchor.
25
+ ### 1. Ensure `ultra_flutter_devtools` is in dev_dependencies
26
+
27
+ - Call `mcp__plugin_flutter_flutter-ultra-build__project_info` to read existing dependencies.
28
+ - If `ultra_flutter_devtools` is NOT listed under `dev_dependencies`:
29
+ - Call `mcp__plugin_flutter_flutter-ultra-build__pub_add` with `package: ultra_flutter_devtools`, `dev: true`.
30
+ - Call `mcp__plugin_flutter_flutter-ultra-build__pub_get` to resolve.
31
+ - If `pub_add` fails (package not on pub.dev — it is bundled with the MCP plugin):
32
+ - Call `mcp__plugin_flutter_flutter-ultra-build__pubspec_overrides_set` with the bundled package path.
33
+ - Add `ultra_flutter_devtools: any` manually under `dev_dependencies` in `pubspec.yaml`.
34
+ - Call `mcp__plugin_flutter_flutter-ultra-build__pub_get`.
35
+
36
+ ### 2. Start the panel WebSocket server
37
+
38
+ - Call `mcp__plugin_flutter_flutter-ultra-devtools__start_panel_server` with `port: 9170` (default).
39
+ - Returns: `{ url: "ws://127.0.0.1:9170", port: 9170, status: "listening" }`.
40
+ - If the port is already in use, retry with `port: 9171` (or any free port above 9170).
41
+ - Note the returned `url` — this is what the DevTools extension iframe connects to.
42
+
43
+ ### 3. Connect the DevTools extension
44
+
45
+ - Open Flutter DevTools in the IDE and navigate to the **flutter-ultra** tab.
46
+ - The extension panel auto-connects to `ws://127.0.0.1:9170` when the tab loads (default port).
47
+ - Verify connection by calling `mcp__plugin_flutter_flutter-ultra-devtools__panel_status`:
48
+ - Expect: `{ running: true, viewers: 1, url: "ws://127.0.0.1:9170" }`.
49
+ - If `viewers: 0` after 10 seconds, the extension has not connected — see edge cases below.
50
+
51
+ ### 4. Push a test event to confirm the pipeline
52
+
53
+ - Call `mcp__plugin_flutter_flutter-ultra-devtools__push_event` with:
54
+ - `type: "custom"`
55
+ - `server: "flutter-ultra-devtools"`
56
+ - `payload: { message: "flutter-ultra panel connected" }`
57
+ - If `delivered: 1` is returned, the panel is receiving events. The user should see the notification in the DevTools flutter-ultra tab.
58
+
59
+ ### 5. Stream activity during automated flows (optional)
60
+
61
+ During long operations (tour, drive, patrol test runs), push events to keep the panel updated:
62
+
63
+ - After each screenshot: call `push_event` with `type: "screenshot"` and `payload: { path: "<screenshot-path>", route: "<current-route>" }`.
64
+ - After each tool call completes: call `push_event` with `type: "tool_result"` and `payload: { tool: "<tool-name>", status: "ok" }`.
65
+ - On error: call `push_event` with `type: "error"` and `payload: { message: "<error>" }`.
66
+
67
+ This is especially useful when running `/flutter-tour` or `/flutter-drive` so the user can follow progress without reading the raw agent output.
68
+
69
+ ### 6. Wait for human-in-the-loop panel commands (optional)
70
+
71
+ To pause an automated flow and wait for the panel user to click a button:
72
+
73
+ - Call `mcp__plugin_flutter_flutter-ultra-devtools__panel_command` with:
74
+ - `timeoutMs: 300000` (5 minutes — adjust to the expected review window)
75
+ - `prompt: "Review the current state and click Resume when ready."`
76
+ - The tool blocks until the panel user sends a command or the timeout expires.
77
+ - Returns: `{ type: "resume" | "pause" | <custom>, payload: {...}, viewerId: "...", timestamp: "..." }`.
78
+ - Use `type === "pause"` to abort the current flow; `type === "resume"` to continue.
79
+
80
+ ### 7. Stop the server when done
81
+
82
+ - Call `mcp__plugin_flutter_flutter-ultra-devtools__stop_panel_server` when the session ends.
83
+ - This disconnects all panel viewers and frees the port.
84
+ - Safe to call even if no viewers are connected.
85
+
86
+ ## Handling edge cases
87
+
88
+ - **`viewers: 0` after tab load**: the DevTools extension connects to port 9170 by default. If `start_panel_server` used a different port, the extension won't find it. Either restart with port 9170, or check if the extension allows a custom port in its settings panel.
89
+ - **Port already in use**: `start_panel_server` will throw. Call `panel_status` first — if `running: true` and the port matches, the server is already up from a previous session; skip to step 3.
90
+ - **`pub_add ultra_flutter_devtools` fails**: the package is bundled inside the MCP plugin distribution. Ask the user for the plugin root path and use `pubspec_overrides_set` to point to `<plugin-root>/packages/flutter-ultra-devtools/dart/`.
91
+ - **DevTools tab not visible**: the `ultra_flutter_devtools` package must be imported somewhere in the app (it self-registers its DevTools extension on import). Add `import 'package:ultra_flutter_devtools/ultra_flutter_devtools.dart';` to the entry point or a debug-only file.
92
+ - **`panel_command` times out**: the panel user did not interact within `timeoutMs`. Treat the timeout as a "continue" signal and proceed with the automated flow. Notify the user in your response that the timeout elapsed.
93
+ - **Multiple IDEs / DevTools windows**: each opened DevTools flutter-ultra tab creates a separate viewer. `push_event` broadcasts to all of them. `panel_command` dequeues from the first one that sends a response — subsequent responses from other viewers are discarded.
94
+
95
+ ## Output format
96
+
97
+ After completing setup, report:
98
+
99
+ 1. **Panel URL**: the WebSocket URL the extension connects to.
100
+ 2. **Viewer count**: how many DevTools windows are connected.
101
+ 3. **Test event delivered**: yes/no.
102
+ 4. **Next steps**: suggest running `/flutter-tour` or `/flutter-drive` with the panel open to see live event streaming.
103
+
104
+ ## Example
105
+
106
+ ```
107
+ User: "Wire up the DevTools panel so I can see what the agent is doing."
108
+
109
+ 1. project_info → ultra_flutter_devtools not in dev_dependencies
110
+ 2. pub_add ultra_flutter_devtools dev:true → added
111
+ 3. pub_get → resolved
112
+ 4. start_panel_server port:9170 → url: ws://127.0.0.1:9170
113
+ 5. [User opens DevTools → flutter-ultra tab]
114
+ 6. panel_status → { running: true, viewers: 1 }
115
+ 7. push_event type:custom payload:{ message: "flutter-ultra panel connected" }
116
+ → delivered: 1
117
+ 8. Panel confirmed working.
118
+
119
+ Panel URL: ws://127.0.0.1:9170 — 1 viewer connected.
120
+ Test event delivered: yes.
121
+ Next: run /flutter-tour with the panel open to see screenshots streaming live.
122
+ ```
18
123
 
19
124
  ## See also
20
125
 
21
- - Plan §8.6, §6.2
126
+ - Sibling skill: `flutter-tour` — route screenshot tour; push screenshot events during the tour
127
+ - Sibling skill: `flutter-drive` — multi-step flows; use `panel_command` for human review gates
128
+ - `mcp__plugin_flutter_flutter-ultra-devtools__start_panel_server` — start the WS server
129
+ - `mcp__plugin_flutter_flutter-ultra-devtools__panel_status` — check viewer count
130
+ - `mcp__plugin_flutter_flutter-ultra-devtools__push_event` — stream events to the panel
131
+ - `mcp__plugin_flutter_flutter-ultra-devtools__panel_command` — wait for human-in-the-loop input
@@ -1,20 +1,143 @@
1
1
  ---
2
- name: drive
2
+ name: flutter-drive
3
3
  description: Driving multi-step user flows in a running Flutter app via gestures and assertions. Use when reproducing a bug across several screens, validating an onboarding flow, or running an ad-hoc end-to-end scenario without writing a patrol test.
4
4
  ---
5
5
 
6
- # Drive (stub)
6
+ # flutter-drive — Multi-Step User Flow Automation
7
7
 
8
- **Status:** scaffold stub. Implementation owner: wave-3 skills worker (see plan §8.2, §12).
8
+ ## When to use
9
+
10
+ Use this skill when the user wants to walk through a specific interactive flow — login sequences, checkout funnels, onboarding wizards, form submissions — and wants the agent to drive the app step by step, verifying state and capturing screenshots between major steps. This is ad-hoc flow automation; for repeatable E2E test suites use the `flutter-test` skill instead.
11
+
12
+ ## Prerequisites
13
+
14
+ - A Flutter app is running in debug mode with the `ultra_flutter` binding initialized (or the app can be launched via `mcp__plugin_flutter_flutter-ultra-runtime__launch_app`).
15
+ - The user has described the flow to execute (e.g. "log in as user@example.com, navigate to invoices, open the first one").
16
+ - For web OAuth flows: a browser context must be available via `mcp__plugin_flutter_flutter-ultra-browser__launch_browser`.
9
17
 
10
18
  ## Workflow
11
19
 
12
- - Enumerate interactive elements via `mcp__flutter-ultra-gesture__interactive_elements`.
13
- - Tap or enter text using key-based finders.
14
- - Verify intermediate state via `mcp__flutter-ultra-runtime__get_widget_tree`.
15
- - For OAuth/popups: delegate to `mcp__flutter-ultra-browser__*` (web) or `mcp__flutter-ultra-native-mobile__*` (mobile).
20
+ ### 1. Attach to the running session
21
+
22
+ - Call `mcp__plugin_flutter_flutter-ultra-runtime__discover_sessions` — pick the session matching the target app.
23
+ - Call `mcp__plugin_flutter_flutter-ultra-runtime__attach` with `sessionId`.
24
+ - Take an initial screenshot with `mcp__plugin_flutter_flutter-ultra-runtime__screenshot` to confirm starting state.
25
+
26
+ ### 2. Plan the flow steps
27
+
28
+ Break the user's request into discrete, verifiable steps:
29
+
30
+ ```
31
+ Step 1: Navigate to /login
32
+ Step 2: Enter email "user@example.com" in field key='email-field'
33
+ Step 3: Enter password in field key='password-field'
34
+ Step 4: Tap button key='sign-in-button'
35
+ Step 5: Verify dashboard loaded (widget key='dashboard-root' present)
36
+ Step 6: Screenshot
37
+ ```
38
+
39
+ Announce the plan before executing if it involves more than 3 steps.
40
+
41
+ ### 3. For each step — inspect → act → verify → screenshot
42
+
43
+ **Inspect the current UI:**
44
+
45
+ - Call `mcp__plugin_flutter_flutter-ultra-runtime__find_widget` with `key` or `text` to confirm the target element exists before acting.
46
+ - If `find_widget` returns nothing, call `mcp__plugin_flutter_flutter-ultra-runtime__get_widget_tree` to understand the current widget hierarchy and adjust the finder.
47
+
48
+ **Perform the action** (choose appropriate tool):
49
+
50
+ - **Tap by key**: `mcp__plugin_flutter_flutter-ultra-runtime__evaluate` with `find.byKey(ValueKey('btn')).first.tap()` via the gesture VM extension, or use marionette's `mcp__marionette__tap` if connected.
51
+ - **Enter text**: `mcp__plugin_flutter_flutter-ultra-runtime__evaluate` to set controller value, or `mcp__marionette__enter_text` for native keyboard input.
52
+ - **Scroll**: `mcp__marionette__scroll_to` with the target key.
53
+ - **Navigate programmatically**: `mcp__plugin_flutter_flutter-ultra-runtime__evaluate` with `context.go('/route')`.
54
+
55
+ **Verify the result:**
56
+
57
+ - Call `mcp__plugin_flutter_flutter-ultra-runtime__find_widget` for an expected element on the next screen.
58
+ - Or call `mcp__plugin_flutter_flutter-ultra-runtime__evaluate` to read state: `MyBloc.of(context).state.runtimeType.toString()`.
59
+ - If verification fails: call `mcp__plugin_flutter_flutter-ultra-runtime__get_runtime_errors` and `mcp__plugin_flutter_flutter-ultra-runtime__get_logs` before reporting failure.
60
+
61
+ **Screenshot after major transitions** (not every micro-step):
62
+
63
+ - `mcp__plugin_flutter_flutter-ultra-runtime__screenshot` → save to `.omc/research/drive-<date>/<step-N>-<label>.png`.
64
+
65
+ ### 4. Web OAuth / external popups (web target)
66
+
67
+ When a flow involves an external OAuth consent screen:
68
+
69
+ 1. Call `mcp__plugin_flutter_flutter-ultra-browser__intercept_redirect` to capture the redirect URL.
70
+ 2. Call `mcp__plugin_flutter_flutter-ultra-browser__navigate` to drive the external auth page.
71
+ 3. Call `mcp__plugin_flutter_flutter-ultra-browser__fill` for username/password fields.
72
+ 4. Call `mcp__plugin_flutter_flutter-ultra-browser__click` on the submit button.
73
+ 5. Call `mcp__plugin_flutter_flutter-ultra-browser__wait_for_url` matching the app's redirect URI.
74
+ 6. Re-attach to the Flutter runtime after the redirect completes.
75
+
76
+ ### 5. Native mobile system dialogs (mobile target)
77
+
78
+ When the flow triggers OS-level permission dialogs or system sheets:
79
+
80
+ - Call `mcp__plugin_flutter_flutter-ultra-native-mobile__wait_for_native_element` to detect the dialog.
81
+ - Call `mcp__plugin_flutter_flutter-ultra-native-mobile__native_permission_grant` or `native_permission_deny`.
82
+ - Call `mcp__plugin_flutter_flutter-ultra-native-mobile__native_tap` for other system buttons.
83
+
84
+ ### 6. Report the flow result
85
+
86
+ After all steps complete, produce:
87
+
88
+ - A numbered summary of steps taken, each with pass/fail status and the screenshot path if captured.
89
+ - Any errors encountered (with stack traces from `get_runtime_errors`).
90
+ - Final state description (current route, visible widget).
91
+
92
+ ## Handling edge cases
93
+
94
+ - **Element not found**: call `get_widget_tree` from the root to find where the element actually is; the app may still be loading or may have navigated differently than expected. Wait up to 3 seconds in 500 ms increments by calling `evaluate` with `SchedulerBinding.instance.endOfFrame`.
95
+ - **App is on wrong route**: call `evaluate` with `GoRouter.of(context).routerDelegate.currentConfiguration.fullPath` to read current route, then navigate to the expected starting point.
96
+ - **Text field requires focus first**: tap the field before entering text; use `find_widget` to confirm it has focus via `hasFocus` property.
97
+ - **Async operations in progress**: check for loading indicators via `find_widget` with type `CircularProgressIndicator`; wait and retry.
98
+ - **Hot-reload after code change**: call `mcp__plugin_flutter_flutter-ultra-runtime__hot_reload` after any code edit, then re-verify the widget tree before continuing.
99
+
100
+ ## Key tool reference
101
+
102
+ | Action | Tool |
103
+ | ----------------------------- | ----------------------------------------------------------------------------------------------------- |
104
+ | Find element by key/text | `mcp__plugin_flutter_flutter-ultra-runtime__find_widget` |
105
+ | Inspect widget hierarchy | `mcp__plugin_flutter_flutter-ultra-runtime__get_widget_tree` |
106
+ | Run arbitrary Dart in-app | `mcp__plugin_flutter_flutter-ultra-runtime__evaluate` |
107
+ | Tap / enter text (marionette) | `mcp__marionette__tap`, `mcp__marionette__enter_text` |
108
+ | Scroll to element | `mcp__marionette__scroll_to` |
109
+ | Read runtime errors | `mcp__plugin_flutter_flutter-ultra-runtime__get_runtime_errors` |
110
+ | Read app logs | `mcp__plugin_flutter_flutter-ultra-runtime__get_logs` |
111
+ | Screenshot | `mcp__plugin_flutter_flutter-ultra-runtime__screenshot` |
112
+ | Web fill / click | `mcp__plugin_flutter_flutter-ultra-browser__fill`, `mcp__plugin_flutter_flutter-ultra-browser__click` |
113
+ | Wait for URL (OAuth) | `mcp__plugin_flutter_flutter-ultra-browser__wait_for_url` |
114
+ | Native permission grant | `mcp__plugin_flutter_flutter-ultra-native-mobile__native_permission_grant` |
115
+
116
+ ## Example
117
+
118
+ ```
119
+ User: "Drive the login flow for user@invora.app with password hunter2, then open the first invoice."
120
+
121
+ 1. discover_sessions → attach(sessionId: "flutter-1")
122
+ 2. screenshot → step-0-start.png (confirm login screen)
123
+ 3. find_widget(key: "email-field") → found
124
+ 4. evaluate: set email controller value to "user@invora.app"
125
+ 5. find_widget(key: "password-field") → found
126
+ 6. evaluate: set password controller value to "hunter2"
127
+ 7. find_widget(key: "sign-in-button") → found; marionette tap(key: "sign-in-button")
128
+ 8. evaluate: await SchedulerBinding.instance.endOfFrame (wait for navigation)
129
+ 9. find_widget(key: "dashboard-root") → found (login succeeded)
130
+ 10. screenshot → step-1-dashboard.png
131
+ 11. evaluate: context.go('/invoices')
132
+ 12. find_widget(text: "Invoice #1") → found; marionette tap(text: "Invoice #1")
133
+ 13. find_widget(key: "invoice-detail-root") → found
134
+ 14. screenshot → step-2-invoice-detail.png
135
+
136
+ Summary: 3 major steps completed, all passed. Final route: /invoices/1.
137
+ ```
16
138
 
17
139
  ## See also
18
140
 
19
- - Plan §8.2
20
- - Sibling skill: `test` for orchestrated patrol runs
141
+ - Sibling skill: `flutter-tour` for passive route screenshot sweeps (no interaction)
142
+ - Sibling skill: `flutter-test` for orchestrated patrol E2E test runs
143
+ - `mcp__marionette__*` — native gesture and text tools via VM service extensions
@@ -1,21 +1,167 @@
1
1
  ---
2
- name: scaffold
2
+ name: flutter-scaffold
3
3
  description: Scaffolding new Flutter projects or features following the conventions detected in the existing codebase. Use when starting a fresh app, adding a feature module, or generating boilerplate that should match an existing project's structure.
4
4
  disable-model-invocation: true
5
5
  ---
6
6
 
7
- # Scaffold (stub)
7
+ # flutter-scaffold — Project and Feature Scaffolding
8
8
 
9
- **Status:** scaffold stub. Implementation owner: wave-3 skills worker (see plan §8.4, §12).
9
+ ## When to use
10
10
 
11
- This skill is opinionated and destructive (creates files), so it is **not** auto-invocable. The user must trigger it explicitly with `/flutter:scaffold`.
11
+ User must explicitly trigger this skill with `/flutter:scaffold`. It is not auto-invoked because it creates files. Use when the user asks to create a new Flutter project, add a feature module, scaffold a new screen, set up state management, or add boilerplate that must match the project's existing conventions.
12
12
 
13
- ## Workflow
13
+ ## Prerequisites
14
14
 
15
- - Project mode: `flutter create` via shell with detected channel + org.
16
- - Feature mode: read the existing structure via `mcp__flutter-ultra-build__project_info`, then create files that match.
15
+ - For **project mode**: a target directory must be specified or agreed upon. Flutter SDK must be on PATH.
16
+ - For **feature mode**: a Flutter project must already exist and be identifiable by `list_projects`.
17
+ - The user must confirm the scaffolding plan before any files are written.
18
+
19
+ ## Mode detection
20
+
21
+ Determine which mode to use from the user's request:
22
+
23
+ | User asks | Mode |
24
+ | --------------------------------------------------------- | ------------------------------------ |
25
+ | "create a new Flutter app", "new project" | Project mode |
26
+ | "add a feature", "new screen", "scaffold [X] page/module" | Feature mode |
27
+ | "set up BLoC / Riverpod / Provider" | State management mode |
28
+ | "add a new route / page" | Screen mode (subset of feature mode) |
29
+
30
+ ---
31
+
32
+ ## Project mode — new Flutter app
33
+
34
+ 1. Confirm with the user: project name, org (reverse domain), target directory, and Flutter channel (stable/beta).
35
+ 2. Run via shell (Bash tool):
36
+ ```bash
37
+ flutter create --org com.example --project-name my_app ./my_app
38
+ ```
39
+ 3. Call `mcp__plugin_flutter_flutter-ultra-build__pub_get` on the new project to fetch dependencies.
40
+ 4. Call `mcp__plugin_flutter_flutter-ultra-build__analyze` to confirm a clean baseline.
41
+ 5. Ask the user if they want state management, routing, or localization scaffolded next — then proceed to the relevant feature mode sections below.
42
+
43
+ ---
44
+
45
+ ## Feature mode — detect existing conventions first
46
+
47
+ Before creating any files, call `mcp__plugin_flutter_flutter-ultra-build__project_info` on the target project to read:
48
+
49
+ - Project root and `lib/` structure
50
+ - Existing dependencies (from `pubspec.yaml`)
51
+
52
+ Then detect the project's conventions by reading `pubspec.yaml` dependencies:
53
+
54
+ | Detected dep | State management pattern |
55
+ | ------------------------------- | ------------------------- |
56
+ | `flutter_bloc` / `bloc` | BLoC pattern |
57
+ | `riverpod` / `flutter_riverpod` | Riverpod |
58
+ | `provider` | Provider |
59
+ | None of the above | Ask the user which to use |
60
+
61
+ | Detected dep | Routing pattern |
62
+ | ------------ | ------------------------ |
63
+ | `go_router` | GoRouter |
64
+ | `auto_route` | AutoRoute |
65
+ | None | Navigator 1.0 (push/pop) |
66
+
67
+ Announce detected conventions to the user before scaffolding.
68
+
69
+ ---
70
+
71
+ ## Screen scaffolding (new route/page)
72
+
73
+ For each new screen, create the following files following the detected pattern:
74
+
75
+ ### File structure (BLoC + GoRouter example for `InvoiceList`):
76
+
77
+ ```
78
+ lib/
79
+ features/
80
+ invoice_list/
81
+ bloc/
82
+ invoice_list_bloc.dart # BLoC class
83
+ invoice_list_event.dart # events sealed class
84
+ invoice_list_state.dart # states sealed class
85
+ view/
86
+ invoice_list_page.dart # BlocProvider wrapper
87
+ invoice_list_view.dart # stateless widget body
88
+ invoice_list.dart # barrel export
89
+ test/
90
+ features/
91
+ invoice_list/
92
+ bloc/
93
+ invoice_list_bloc_test.dart
94
+ ```
95
+
96
+ For **Riverpod**: replace `bloc/` with `provider/` containing a `StateNotifier` or `AsyncNotifier`.
97
+ For **Provider**: replace `bloc/` with `provider/` containing a `ChangeNotifier`.
98
+
99
+ ### Route registration (GoRouter):
100
+
101
+ Add the new route to the router config file (detect by searching for `GoRouter(` in `lib/`):
102
+
103
+ ```dart
104
+ GoRoute(
105
+ path: '/invoice-list',
106
+ name: 'invoiceList',
107
+ builder: (context, state) => const InvoiceListPage(),
108
+ ),
109
+ ```
110
+
111
+ ### After creating files:
112
+
113
+ 1. Call `mcp__plugin_flutter_flutter-ultra-build__format` on the new files to normalize formatting.
114
+ 2. Call `mcp__plugin_flutter_flutter-ultra-build__analyze` — fix any errors before reporting done.
115
+ 3. Do **not** call `pub_get` unless new packages were added.
116
+
117
+ ---
118
+
119
+ ## State management setup (first-time)
120
+
121
+ When the project has no state management and the user wants to add one:
122
+
123
+ **BLoC:**
124
+
125
+ 1. Call `mcp__plugin_flutter_flutter-ultra-build__pub_add` with `flutter_bloc bloc equatable`.
126
+ 2. Call `mcp__plugin_flutter_flutter-ultra-build__pub_get`.
127
+ 3. Scaffold the first BLoC as described in the screen section above.
128
+
129
+ **Riverpod:**
130
+
131
+ 1. Call `mcp__plugin_flutter_flutter-ultra-build__pub_add` with `flutter_riverpod riverpod_annotation` and dev deps `riverpod_generator build_runner`.
132
+ 2. Call `mcp__plugin_flutter_flutter-ultra-build__pub_get`.
133
+ 3. Wrap `main.dart`'s `runApp` with `ProviderScope`.
134
+ 4. Call `mcp__plugin_flutter_flutter-ultra-build__start_build_runner_build` → `poll_build_runner_job` → `get_build_runner_result` to generate initial code.
135
+
136
+ **Provider:**
137
+
138
+ 1. Call `mcp__plugin_flutter_flutter-ultra-build__pub_add` with `provider`.
139
+ 2. Call `mcp__plugin_flutter_flutter-ultra-build__pub_get`.
140
+
141
+ ---
142
+
143
+ ## Localization scaffolding
144
+
145
+ When the user asks to add l10n:
146
+
147
+ 1. Call `mcp__plugin_flutter_flutter-ultra-build__pub_add` with `flutter_localizations` (SDK package).
148
+ 2. Create `lib/l10n/app_en.arb` with a minimal key set.
149
+ 3. Add `generate: true` to `pubspec.yaml` under `flutter:`.
150
+ 4. Call `mcp__plugin_flutter_flutter-ultra-build__flutter_gen_l10n` to generate the `AppLocalizations` class.
151
+ 5. Add `localizationsDelegates` and `supportedLocales` to the `MaterialApp`.
152
+
153
+ ---
154
+
155
+ ## Confirmation and safety rules
156
+
157
+ - **Always announce the file list** that will be created before writing. Wait for user confirmation if the list is more than 3 files.
158
+ - **Never overwrite existing files** without explicit user confirmation.
159
+ - **Match the existing naming convention**: if existing files use `snake_case` feature directories, continue that pattern; if they use `camelCase`, match it.
160
+ - After scaffolding, run `analyze` and surface any errors — do not report done if there are errors.
17
161
 
18
162
  ## See also
19
163
 
20
- - Plan §8.4
21
- - Sibling skill: `setup` for plugging the plugin into an existing codebase
164
+ - Sibling skill: `flutter-test` for writing tests after scaffolding
165
+ - Sibling skill: `flutter-debug` for inspecting live state in scaffolded features
166
+ - `mcp__plugin_flutter_flutter-ultra-build__project_info` — reads project structure and dependencies
167
+ - `mcp__plugin_flutter_flutter-ultra-build__analyze` — validates scaffolded code compiles clean
@@ -1,26 +1,150 @@
1
1
  ---
2
- name: setup
3
- description: Bootstrapping flutter-ultra-mcp into an existing Flutter codebase end-to-end. Use when the user wants the plugin enabled for the first time on a project, or when re-running after a clean install. Idempotent.
4
- disable-model-invocation: true
2
+ name: flutter-setup
3
+ description: One-command setup of the flutter-ultra-mcp plugin in an existing Flutter codebase. Use when the user wants to enable flutter-ultra for the first time, or when re-running after a clean install. Idempotent — safe to run again if a previous attempt was partial.
5
4
  ---
6
5
 
7
- # Setup (stub)
6
+ # flutter-setup — One-Command Plugin Setup
8
7
 
9
- **Status:** scaffold stub. Implementation owner: wave-3 skills worker (see plan §8.7, §12).
8
+ ## When to use
10
9
 
11
- User-triggered only patches pubspec, entry points, and `.vscode/launch.json`.
10
+ Use this skill when the user wants to wire up the flutter-ultra-mcp plugin into a Flutter project for the first time, or when verifying that a previously attempted setup is complete and working. The expected end state is: `UltraFlutterBinding` initialized in the app entry point, `ultra_flutter` in `dev_dependencies`, patrol fork overridden in `pubspec_overrides.yaml`, and a smoke launch confirming the VM Service attaches correctly.
12
11
 
13
- ## Workflow (target)
12
+ ## Prerequisites
14
13
 
15
- 1. Detect project layout via `mcp__flutter-ultra-build__project_info` (entry points, existing bindings, Sentry usage, patrol).
16
- 2. Add `ultra_flutter` to `dev_dependencies`; if Sentry detected, show the direct `// ignore: implementation_imports` binding pattern.
17
- 3. Patch entry point(s) with AST-aware edits to mix in `UltraFlutterBinding` under `kDebugMode`.
18
- 4. Optional: add a launch.json profile pre-applying dart-defines for session discovery.
19
- 5. Detect existing patrol setup and offer the `run_patrol_web` wrapper.
20
- 6. Generate per-project `.flutter-ultra.config.yaml`.
21
- 7. Run a smoke launch + screenshot + detach.
22
- 8. Emit `SETUP-REPORT.md` at project root.
14
+ - Flutter SDK installed and on PATH (`flutter --version` must succeed).
15
+ - Node.js 18 installed (required for the MCP servers).
16
+ - The target project has a `pubspec.yaml` (i.e., it is a Flutter app, not a pure Dart package).
17
+ - The user is working from the project root (or has provided an absolute path to it).
18
+
19
+ ## Workflow
20
+
21
+ ### 1. Verify the environment
22
+
23
+ - Call `mcp__plugin_flutter_flutter-ultra-build__flutter_doctor` with the project root.
24
+ - If any `[✗]` entries appear for Flutter SDK, connected devices, or Dart, stop and surface the doctor output to the user. Do not continue until the environment is healthy.
25
+ - Call `mcp__plugin_flutter_flutter-ultra-build__project_info` with the project root.
26
+ - Note: `entryPoints` (usually `lib/main.dart` or `lib/bootstrap.dart`), `hasSentry` (affects binding pattern), `hasPatrol` (determines whether to configure the patrol fork override).
27
+
28
+ ### 2. Add `ultra_flutter` to dev_dependencies
29
+
30
+ - Call `mcp__plugin_flutter_flutter-ultra-build__pub_add` with:
31
+ - `package`: `ultra_flutter`
32
+ - `dev`: `true`
33
+ - If `pub_add` fails because `ultra_flutter` is not on pub.dev (it is a local plugin bundled with the MCP server), use `pubspec_overrides_set` to point to the bundled path instead:
34
+ - Call `mcp__plugin_flutter_flutter-ultra-build__pubspec_overrides_set` with `package: ultra_flutter` and `path` set to the absolute path of the bundled package (ask the user or read from plugin config if available).
35
+ - Then add the dependency manually by editing `pubspec.yaml`: add `ultra_flutter: any` under `dev_dependencies`.
36
+ - Call `mcp__plugin_flutter_flutter-ultra-build__pub_get` to resolve.
37
+
38
+ ### 3. Patch the app entry point
39
+
40
+ Read the primary entry point file identified in step 1. Apply the following pattern:
41
+
42
+ **Without Sentry** — wrap the existing `runApp` call:
43
+
44
+ ```dart
45
+ import 'package:flutter/foundation.dart';
46
+ import 'package:ultra_flutter/ultra_flutter.dart';
47
+
48
+ void main() {
49
+ if (kDebugMode) {
50
+ UltraFlutterBinding.ensureInitialized();
51
+ }
52
+ runApp(const MyApp());
53
+ }
54
+ ```
55
+
56
+ **With Sentry** (when `hasSentry: true`) — Sentry installs its own binding; use the direct mixin pattern:
57
+
58
+ ```dart
59
+ import 'package:flutter/foundation.dart';
60
+ import 'package:ultra_flutter/ultra_flutter.dart';
61
+
62
+ // In your custom binding class:
63
+ class AppBinding extends WidgetsFlutterBinding with UltraFlutterBindingMixin {
64
+ static AppBinding ensureInitialized() =>
65
+ WidgetsFlutterBinding.ensureInitialized() as AppBinding;
66
+ }
67
+
68
+ void main() {
69
+ AppBinding.ensureInitialized();
70
+ // ... Sentry.init wrapping runApp as before
71
+ }
72
+ ```
73
+
74
+ Edit the file with the appropriate pattern. Only add the import and the `ensureInitialized` call — do not reorganize the existing code.
75
+
76
+ ### 4. Configure the patrol fork override (if patrol detected)
77
+
78
+ When `project_info` reported `hasPatrol: true`:
79
+
80
+ - Call `mcp__plugin_flutter_flutter-ultra-build__pubspec_overrides_list` to check if a `patrol` override already exists.
81
+ - If not present, call `mcp__plugin_flutter_flutter-ultra-build__pubspec_overrides_set` with:
82
+ - `package`: `patrol`
83
+ - `path`: the vendored patrol fork path bundled with flutter-ultra-mcp (located at `<plugin-root>/packages/flutter-ultra-patrol/vendor/patrol` — ask the user for `<plugin-root>` if not available in context).
84
+ - Call `mcp__plugin_flutter_flutter-ultra-build__pub_get` to resolve the override.
85
+
86
+ ### 5. Run static analysis to verify the setup
87
+
88
+ - Call `mcp__plugin_flutter_flutter-ultra-build__pub_get` (ensure lock file is current after all edits).
89
+ - Call `mcp__plugin_flutter_flutter-ultra-build__analyze` with the project root.
90
+ - If any errors reference `ultra_flutter` or `UltraFlutterBinding`, the import or mixin was not applied correctly — re-read the entry point and fix.
91
+ - Warnings about `// ignore: implementation_imports` on the Sentry path are expected; surface them to the user as informational only.
92
+
93
+ ### 6. Smoke test: launch, attach, screenshot
94
+
95
+ - Call `mcp__plugin_flutter_flutter-ultra-runtime__launch_app` with the project root and target device (default: `chrome` for web projects, `linux`/`macos`/`windows` for desktop, first connected device for mobile).
96
+ - Poll `mcp__plugin_flutter_flutter-ultra-runtime__poll_launch_app` until status is `ready` or `error`.
97
+ - If `error`, surface the launch log to the user and stop.
98
+ - Call `mcp__plugin_flutter_flutter-ultra-runtime__attach` with the returned `sessionId`.
99
+ - Call `mcp__plugin_flutter_flutter-ultra-runtime__screenshot` — save to `.omc/research/setup-smoke-<YYYY-MM-DD>.png`.
100
+ - Call `mcp__plugin_flutter_flutter-ultra-runtime__detach`.
101
+ - Call `mcp__plugin_flutter_flutter-ultra-runtime__stop_app` with the `sessionId`.
102
+
103
+ If screenshot succeeds and the image is not blank, the setup is confirmed working.
104
+
105
+ ## Handling edge cases
106
+
107
+ - **`UltraFlutterBinding.ensureInitialized()` already present**: `project_info` reports `hasUltraBinding: true`. Skip step 3 but still run steps 5–6 to confirm working state.
108
+ - **Multiple entry points** (e.g. `main_dev.dart`, `main_prod.dart`): patch all of them with the same binding initialization. Confirm with the user if the list is longer than 3 files before editing.
109
+ - **Monorepo / workspace**: `pubspec_overrides.yaml` must exist in each app package that needs ultra. Run steps 2–6 for each app package separately.
110
+ - **pub_get fails after overrides**: common cause is a mismatched `patrol` version in `pubspec.yaml` vs. the fork. Call `mcp__plugin_flutter_flutter-ultra-build__pub_outdated` to inspect version constraints, then relax the constraint in `pubspec.yaml` to `any` for the overridden package.
111
+ - **analyze reports `ultra_flutter` not found**: the `pubspec_overrides.yaml` path is wrong. Call `mcp__plugin_flutter_flutter-ultra-build__pubspec_overrides_list` to verify the resolved path, then correct it.
112
+ - **launch_app times out**: the app may require dart-defines (e.g. OIDC client IDs). Call `mcp__plugin_flutter_flutter-ultra-build__list_dart_defines` to discover required defines, then relaunch with them.
113
+
114
+ ## Output format
115
+
116
+ After the workflow completes, produce:
117
+
118
+ 1. **Status**: `setup complete` or `setup failed at step N`.
119
+ 2. **Changes made**: bullet list of files edited (entry points, `pubspec.yaml`, `pubspec_overrides.yaml`).
120
+ 3. **Smoke test result**: path to the saved screenshot, or the error message if launch failed.
121
+ 4. **Next steps**: suggest running `/flutter-tour` to capture a visual baseline, or `/flutter-debug` if the smoke test revealed a runtime error.
122
+
123
+ ## Example
124
+
125
+ ```
126
+ User: "Set up flutter-ultra on the Invora Flutter app."
127
+
128
+ 1. flutter_doctor → all checks pass
129
+ 2. project_info → entryPoints: ["lib/bootstrap.dart"], hasSentry: true, hasPatrol: true
130
+ 3. pub_add ultra_flutter dev:true → added to pubspec.yaml
131
+ 4. Edit lib/bootstrap.dart — add UltraFlutterBindingMixin to AppBinding class
132
+ 5. pubspec_overrides_set patrol → path: /home/user/.claude/plugins/flutter-ultra-mcp/vendor/patrol
133
+ 6. pub_get → resolved
134
+ 7. analyze → 0 errors, 1 warning (ignore: implementation_imports — expected)
135
+ 8. launch_app device:chrome → sessionId: "flutter-1"
136
+ 9. attach(sessionId: "flutter-1")
137
+ 10. screenshot → .omc/research/setup-smoke-2026-05-19.png (dashboard visible)
138
+ 11. detach + stop_app
139
+
140
+ Setup complete. 3 files changed. Smoke screenshot saved.
141
+ Next: run /flutter-tour to capture a full visual baseline.
142
+ ```
23
143
 
24
144
  ## See also
25
145
 
26
- - Plan §8.7
146
+ - Sibling skill: `flutter-tour` — visual screenshot tour after setup
147
+ - Sibling skill: `flutter-debug` — triage if the smoke launch reveals a runtime error
148
+ - `mcp__plugin_flutter_flutter-ultra-build__project_info` — entry point and feature detection
149
+ - `mcp__plugin_flutter_flutter-ultra-runtime__launch_app` — launch app for smoke test
150
+ - `mcp__plugin_flutter_flutter-ultra-build__pubspec_overrides_set` — configure patrol fork override