@smartsoft001-mobilems/claude-plugins 2.58.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 (52) hide show
  1. package/.claude-plugin/marketplace.json +14 -0
  2. package/package.json +13 -0
  3. package/plugins/flow/.claude-plugin/plugin.json +5 -0
  4. package/plugins/flow/agents/angular-component-scaffolder.md +174 -0
  5. package/plugins/flow/agents/angular-directive-builder.md +152 -0
  6. package/plugins/flow/agents/angular-guard-builder.md +242 -0
  7. package/plugins/flow/agents/angular-jest-test-writer.md +473 -0
  8. package/plugins/flow/agents/angular-pipe-builder.md +168 -0
  9. package/plugins/flow/agents/angular-resolver-builder.md +285 -0
  10. package/plugins/flow/agents/angular-service-builder.md +160 -0
  11. package/plugins/flow/agents/angular-signal-state-builder.md +338 -0
  12. package/plugins/flow/agents/angular-test-diagnostician.md +278 -0
  13. package/plugins/flow/agents/angular-testbed-configurator.md +314 -0
  14. package/plugins/flow/agents/arch-scaffolder.md +277 -0
  15. package/plugins/flow/agents/shared-build-verifier.md +159 -0
  16. package/plugins/flow/agents/shared-config-updater.md +309 -0
  17. package/plugins/flow/agents/shared-coverage-enforcer.md +183 -0
  18. package/plugins/flow/agents/shared-error-handler.md +216 -0
  19. package/plugins/flow/agents/shared-file-creator.md +343 -0
  20. package/plugins/flow/agents/shared-impl-orchestrator.md +309 -0
  21. package/plugins/flow/agents/shared-impl-reporter.md +338 -0
  22. package/plugins/flow/agents/shared-linear-subtask-iterator.md +336 -0
  23. package/plugins/flow/agents/shared-logic-implementer.md +242 -0
  24. package/plugins/flow/agents/shared-maia-api.md +25 -0
  25. package/plugins/flow/agents/shared-performance-validator.md +167 -0
  26. package/plugins/flow/agents/shared-project-standardizer.md +204 -0
  27. package/plugins/flow/agents/shared-security-scanner.md +185 -0
  28. package/plugins/flow/agents/shared-style-enforcer.md +229 -0
  29. package/plugins/flow/agents/shared-tdd-developer.md +349 -0
  30. package/plugins/flow/agents/shared-test-fixer.md +185 -0
  31. package/plugins/flow/agents/shared-test-runner.md +190 -0
  32. package/plugins/flow/agents/shared-ui-classifier.md +229 -0
  33. package/plugins/flow/agents/shared-verification-orchestrator.md +193 -0
  34. package/plugins/flow/agents/shared-verification-runner.md +139 -0
  35. package/plugins/flow/agents/ui-a11y-validator.md +304 -0
  36. package/plugins/flow/agents/ui-screenshot-reporter.md +328 -0
  37. package/plugins/flow/agents/ui-web-designer.md +213 -0
  38. package/plugins/flow/commands/commit.md +131 -0
  39. package/plugins/flow/commands/impl.md +625 -0
  40. package/plugins/flow/commands/plan.md +598 -0
  41. package/plugins/flow/commands/push.md +584 -0
  42. package/plugins/flow/skills/a11y-audit/SKILL.md +214 -0
  43. package/plugins/flow/skills/angular-patterns/SKILL.md +191 -0
  44. package/plugins/flow/skills/browser-capture/SKILL.md +238 -0
  45. package/plugins/flow/skills/debug-helper/SKILL.md +375 -0
  46. package/plugins/flow/skills/maia-files-delete/SKILL.md +60 -0
  47. package/plugins/flow/skills/maia-files-upload/SKILL.md +58 -0
  48. package/plugins/flow/skills/nx-conventions/SKILL.md +327 -0
  49. package/plugins/flow/skills/test-unit/SKILL.md +456 -0
  50. package/src/index.d.ts +6 -0
  51. package/src/index.js +10 -0
  52. package/src/index.js.map +1 -0
@@ -0,0 +1,214 @@
1
+ ---
2
+ name: a11y-audit
3
+ description: Run accessibility audits on web pages. Ensures dev server is running, navigates to pages, captures accessibility snapshots, and runs axe-core tests.
4
+ allowed-tools:
5
+ - Bash
6
+ - Read
7
+ - Glob
8
+ - mcp__playwright__browser_navigate
9
+ - mcp__playwright__browser_snapshot
10
+ - mcp__playwright__browser_evaluate
11
+ - mcp__playwright__browser_close
12
+ ---
13
+
14
+ # Accessibility Audit Skill
15
+
16
+ Run accessibility audits on web pages using Playwright and axe-core. Automatically ensures the development server is running before auditing.
17
+
18
+ ## Capabilities
19
+
20
+ 1. **Server Management**: Check if dev server is running, start if needed
21
+ 2. **Page Navigation**: Navigate to specified URLs using Playwright
22
+ 3. **Accessibility Snapshot**: Capture accessibility tree for analysis
23
+ 4. **Axe-core Testing**: Run automated accessibility tests
24
+
25
+ ## Server Management
26
+
27
+ ### Read Port Configuration
28
+
29
+ ```bash
30
+ # Default port location
31
+ grep -o '"port":[^,}]*' apps/web/project.json | head -1
32
+ # Default: 4210
33
+ ```
34
+
35
+ ### Check if Server is Running
36
+
37
+ ```bash
38
+ lsof -i :4210 -t
39
+ ```
40
+
41
+ - If returns PID → server is running
42
+ - If returns nothing → server needs to be started
43
+
44
+ ### Start Server if Needed
45
+
46
+ ```bash
47
+ # Start in background
48
+ npm start &
49
+
50
+ # Wait for server to be ready
51
+ for i in {1..15}; do
52
+ curl -s http://localhost:4210 > /dev/null && break
53
+ sleep 2
54
+ done
55
+ ```
56
+
57
+ ## Audit Process
58
+
59
+ ### 1. Ensure Server is Running
60
+
61
+ Before any audit:
62
+
63
+ 1. Read port from `apps/web/project.json` (default: 4210)
64
+ 2. Check if port is occupied: `lsof -i :PORT -t`
65
+ 3. If not running: `npm start &` and wait ~15 seconds
66
+
67
+ ### 2. Navigate to Page
68
+
69
+ Use `mcp__playwright__browser_navigate` to open the target URL.
70
+
71
+ ```
72
+ URL format: http://localhost:{port}/{path}
73
+ ```
74
+
75
+ ### 3. Capture Accessibility Snapshot
76
+
77
+ Use `mcp__playwright__browser_snapshot` to get the accessibility tree.
78
+
79
+ This provides:
80
+
81
+ - Element roles and names
82
+ - ARIA attributes
83
+ - Focus states
84
+ - Interactive element information
85
+
86
+ ### 4. Run Axe-core Audit
87
+
88
+ Use `mcp__playwright__browser_evaluate` to inject and run axe-core:
89
+
90
+ ```javascript
91
+ // Example evaluation code
92
+ async () => {
93
+ // Load axe-core from CDN
94
+ const script = document.createElement('script');
95
+ script.src =
96
+ 'https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.8.2/axe.min.js';
97
+ document.head.appendChild(script);
98
+
99
+ await new Promise((resolve) => (script.onload = resolve));
100
+
101
+ // Run audit
102
+ const results = await axe.run();
103
+ return {
104
+ violations: results.violations,
105
+ passes: results.passes.length,
106
+ incomplete: results.incomplete,
107
+ };
108
+ };
109
+ ```
110
+
111
+ ## Usage Examples
112
+
113
+ ### Full Page Audit
114
+
115
+ ```
116
+ Input: { path: "/articles" }
117
+
118
+ Process:
119
+ 1. Check server running on port 4210
120
+ 2. Start if needed, wait for ready
121
+ 3. Navigate to http://localhost:4210/articles
122
+ 4. Capture accessibility snapshot
123
+ 5. Run axe-core audit
124
+ 6. Return violations and recommendations
125
+
126
+ Output:
127
+ {
128
+ "url": "http://localhost:4210/articles",
129
+ "snapshot": { ... accessibility tree ... },
130
+ "violations": [
131
+ {
132
+ "id": "image-alt",
133
+ "impact": "critical",
134
+ "description": "Images must have alternate text",
135
+ "nodes": [...]
136
+ }
137
+ ],
138
+ "passes": 45,
139
+ "incomplete": 2
140
+ }
141
+ ```
142
+
143
+ ### Quick Check
144
+
145
+ ```
146
+ Input: { path: "/", snapshotOnly: true }
147
+
148
+ Output:
149
+ {
150
+ "url": "http://localhost:4210/",
151
+ "snapshot": { ... accessibility tree ... }
152
+ }
153
+ ```
154
+
155
+ ## Report Format
156
+
157
+ When generating reports, use this structure:
158
+
159
+ ```markdown
160
+ ## Accessibility Audit Report
161
+
162
+ **Page**: [URL]
163
+ **Date**: [Date]
164
+ **Standard**: WCAG 2.1 Level AA
165
+
166
+ ### Critical Issues (Must Fix)
167
+
168
+ | Issue | Elements | WCAG | Fix |
169
+ | ----------- | -------- | ----- | ------------------------ |
170
+ | Missing alt | 3 images | 1.1.1 | Add descriptive alt text |
171
+
172
+ ### Serious Issues (Should Fix)
173
+
174
+ | Issue | Elements | WCAG | Fix |
175
+ | ------------ | ---------- | ----- | ---------------- |
176
+ | Low contrast | 2 elements | 1.4.3 | Use darker color |
177
+
178
+ ### Passed Checks
179
+
180
+ - [x] Page has lang attribute
181
+ - [x] Headings in correct order
182
+ - [x] Form inputs have labels
183
+
184
+ ### Summary
185
+
186
+ - Violations: X critical, Y serious, Z minor
187
+ - Passed: N checks
188
+ ```
189
+
190
+ ## Error Handling
191
+
192
+ ### Server Won't Start
193
+
194
+ If server fails to start after 30 seconds:
195
+
196
+ 1. Check for port conflicts
197
+ 2. Check npm logs for errors
198
+ 3. Report error and skip audit
199
+
200
+ ### Axe-core Load Fails
201
+
202
+ If axe-core fails to load:
203
+
204
+ 1. Check network connectivity
205
+ 2. Try alternative CDN
206
+ 3. Fall back to snapshot-only audit
207
+
208
+ ### Navigation Fails
209
+
210
+ If page doesn't load:
211
+
212
+ 1. Verify URL is correct
213
+ 2. Check for JavaScript errors
214
+ 3. Report partial results
@@ -0,0 +1,191 @@
1
+ ---
2
+ name: angular-patterns
3
+ description: Angular 20 modern patterns including signals, standalone components, and new control flow syntax
4
+ ---
5
+
6
+ # Angular 20 Modern Patterns
7
+
8
+ This skill provides guidance on Angular 20 best practices for this project.
9
+
10
+ ## 1. Control Flow Syntax (`@if`, `@for`, `@switch`)
11
+
12
+ - Prefer `@if` over `*ngIf` and `@switch` over `ngSwitch`
13
+ - Prefer `@for` over `*ngFor`; always provide an explicit `track` expression
14
+ - Do not mix old and new syntax in the same file
15
+
16
+ ### Examples
17
+
18
+ ```html
19
+ @if (isLoading()) {
20
+ <app-spinner />
21
+ } @else if (error()) {
22
+ <app-error [message]="error()?.message" />
23
+ } @else {
24
+ <ul>
25
+ @for (item of items(); track item.id) {
26
+ <li>{{ item.name }}</li>
27
+ } @empty {
28
+ <li>No data</li>
29
+ }
30
+ </ul>
31
+ }
32
+ ```
33
+
34
+ ```html
35
+ @switch (status()) { @case ('pending') {
36
+ <span class="smart-text-yellow-500">Pending</span>
37
+ } @case ('active') {
38
+ <span class="smart-text-green-500">Active</span>
39
+ } @default {
40
+ <span class="smart-text-gray-500">Unknown</span>
41
+ } }
42
+ ```
43
+
44
+ ## 2. Signals
45
+
46
+ ### When to Use
47
+
48
+ | Pattern | Use Case |
49
+ | ------------ | ---------------------------------------------------- |
50
+ | `signal()` | Local, mutable component state |
51
+ | `computed()` | Pure derivations from other signals |
52
+ | `effect()` | Side-effects (logging, syncing, service interaction) |
53
+ | `toSignal()` | Convert Observable to Signal |
54
+
55
+ ### Signal Examples
56
+
57
+ ```typescript
58
+ // Local state
59
+ readonly items = signal<Item[]>([]);
60
+ readonly isLoading = signal(false);
61
+
62
+ // Computed derivation
63
+ readonly filtered = computed(() => {
64
+ const f = this.filter().toLowerCase();
65
+ return this.items().filter(i => i.name.toLowerCase().includes(f));
66
+ });
67
+
68
+ // Effect for side-effects only
69
+ private readonly syncEffect = effect(() => {
70
+ const items = this.items();
71
+ this.analyticsService.track('items-loaded', { count: items.length });
72
+ });
73
+ ```
74
+
75
+ ### RxJS Bridging
76
+
77
+ ```typescript
78
+ // Observable → Signal
79
+ private readonly data$ = this.http.get<Data[]>('/api/data');
80
+ readonly data = toSignal(this.data$, { initialValue: [] });
81
+
82
+ // Signal → Observable (only when needed)
83
+ readonly filter$ = toObservable(this.filter);
84
+ ```
85
+
86
+ ### Naming Conventions
87
+
88
+ - No `Signal`/`Sig` suffix—use semantic names (`items`, `isLoading`)
89
+ - Use descriptive names: `selectedItem`, `filteredResults`, `hasError`
90
+
91
+ ## 3. Dependency Injection via `inject()`
92
+
93
+ ```typescript
94
+ @Component({...})
95
+ export class MyComponent {
96
+ // Standard pattern
97
+ private readonly http = inject(HttpClient);
98
+ private readonly router = inject(Router);
99
+ private readonly myService = inject(MyService);
100
+
101
+ // Optional dependency
102
+ private readonly optionalService = inject(OptionalService, { optional: true });
103
+ }
104
+ ```
105
+
106
+ ### Rules
107
+
108
+ - Place `inject()` calls near the top of the class
109
+ - Never call `inject()` inside loops or event handlers
110
+ - Assign to `readonly` properties
111
+
112
+ ## 4. Input/Output APIs: `input()`, `output()`, `model()`
113
+
114
+ ### New API Patterns
115
+
116
+ ```typescript
117
+ @Component({...})
118
+ export class FormFieldComponent {
119
+ // Required input
120
+ readonly label = input.required<string>();
121
+
122
+ // Optional input with default
123
+ readonly disabled = input(false);
124
+
125
+ // Input with transform
126
+ readonly count = input<number, string>(0, {
127
+ transform: (v) => parseInt(v, 10)
128
+ });
129
+
130
+ // Output event
131
+ readonly changed = output<string>();
132
+
133
+ // Two-way binding (use sparingly)
134
+ readonly value = model<string>('');
135
+ }
136
+ ```
137
+
138
+ ### Usage in Templates
139
+
140
+ ```html
141
+ <!-- Parent template -->
142
+ <app-form-field
143
+ label="Name"
144
+ [disabled]="isDisabled()"
145
+ [(value)]="name"
146
+ (changed)="onChanged($event)"
147
+ />
148
+ ```
149
+
150
+ ## 5. Standalone Components
151
+
152
+ All new components should be standalone:
153
+
154
+ ```typescript
155
+ @Component({
156
+ selector: 'app-feature',
157
+ standalone: true,
158
+ imports: [CommonModule, RouterModule, SharedModule],
159
+ template: `...`,
160
+ styles: `...`,
161
+ })
162
+ export class FeatureComponent {
163
+ // ...
164
+ }
165
+ ```
166
+
167
+ ## 6. Performance Guidelines
168
+
169
+ - Every `@for` must have a stable `track` expression (prefer `item.id` over index)
170
+ - Extract complex conditions into `computed()` signals
171
+ - Avoid allocating new arrays/objects in template expressions
172
+ - Use `OnPush` change detection when appropriate
173
+
174
+ ## 7. Migration Order (Legacy Code)
175
+
176
+ When touching legacy code, migrate in this order:
177
+
178
+ 1. `*ngIf` → `@if`
179
+ 2. `*ngFor` → `@for` (add `track`)
180
+ 3. Constructor DI → `inject()`
181
+ 4. `@Input/@Output` → `input()/output()/model()`
182
+ 5. Simple state Observables → signals
183
+
184
+ ## 8. PR Checklist
185
+
186
+ - [ ] No mixing of `*ngIf/*ngFor` with `@if/@for` in same logical block
187
+ - [ ] Every `@for` has a `track` expression
188
+ - [ ] No unnecessary `subscribe()` calls (use `toSignal`)
189
+ - [ ] DI uses `inject()` (no new constructor-based DI)
190
+ - [ ] Inputs/Outputs use `input()/output()/model()` in new code
191
+ - [ ] No heavy inline computations in templates
@@ -0,0 +1,238 @@
1
+ ---
2
+ name: browser-capture
3
+ description: Manage browser sessions and capture screenshots. Ensures dev server is running, navigates to pages, captures responsive screenshots, and uploads them to temporary storage.
4
+ allowed-tools:
5
+ - Bash
6
+ - Read
7
+ - Glob
8
+ - mcp__playwright__browser_navigate
9
+ - mcp__playwright__browser_snapshot
10
+ - mcp__playwright__browser_take_screenshot
11
+ - mcp__playwright__browser_resize
12
+ - mcp__playwright__browser_close
13
+ ---
14
+
15
+ # Browser Capture Skill
16
+
17
+ Manage browser sessions for capturing screenshots of web pages. Automatically ensures the development server is running before capturing.
18
+
19
+ ## Capabilities
20
+
21
+ 1. **Server Management**: Check if dev server is running, start if needed
22
+ 2. **Page Navigation**: Navigate to specified URLs using Playwright
23
+ 3. **Screenshot Capture**: Take screenshots at multiple viewport sizes
24
+ 4. **Upload Screenshots**: Upload captured images to maia-api for use in reports
25
+
26
+ ## Server Management
27
+
28
+ ### Read Port Configuration
29
+
30
+ ```bash
31
+ # Default port location
32
+ grep -o '"port":[^,}]*' apps/web/project.json | head -1
33
+ # Default: 4210
34
+ ```
35
+
36
+ ### Check if Server is Running
37
+
38
+ ```bash
39
+ lsof -i :4210 -t
40
+ ```
41
+
42
+ - If returns PID → server is running
43
+ - If returns nothing → server needs to be started
44
+
45
+ ### Start Server if Needed
46
+
47
+ ```bash
48
+ # Start in background
49
+ npm start &
50
+
51
+ # Wait for server to be ready (check every 2 seconds, max 30 seconds)
52
+ for i in {1..15}; do
53
+ curl -s http://localhost:4210 > /dev/null && break
54
+ sleep 2
55
+ done
56
+ ```
57
+
58
+ ## Screenshot Capture Process
59
+
60
+ ### 1. Ensure Server is Running
61
+
62
+ Before any screenshot capture:
63
+
64
+ 1. Read port from `apps/web/project.json` (default: 4210)
65
+ 2. Check if port is occupied: `lsof -i :PORT -t`
66
+ 3. If not running: `npm start &` and wait ~15 seconds
67
+
68
+ ### 2. Navigate to Page
69
+
70
+ Use `mcp__playwright__browser_navigate` to open the target URL.
71
+
72
+ ```
73
+ URL format: http://localhost:{port}/{path}
74
+ ```
75
+
76
+ ### 3. Capture at Multiple Viewports
77
+
78
+ Standard viewport sizes:
79
+
80
+ | Name | Width | Height |
81
+ | ------- | ----- | ------ |
82
+ | Desktop | 1920 | 1080 |
83
+ | Tablet | 768 | 1024 |
84
+ | Mobile | 375 | 667 |
85
+
86
+ Process for each viewport:
87
+
88
+ 1. `mcp__playwright__browser_resize` → set dimensions
89
+ 2. `mcp__playwright__browser_take_screenshot` → save to temp file
90
+
91
+ ### 4. Upload Screenshots
92
+
93
+ After capturing, delegate upload to `maia-api` agent:
94
+
95
+ ```
96
+ Input: /tmp/screenshot-desktop.png
97
+ Output: { id: "abc123", url: "https://maia-ai-api.smartsoft.biz.pl/files/abc123" }
98
+ ```
99
+
100
+ ## Usage Examples
101
+
102
+ ### Capture Single Page
103
+
104
+ ```
105
+ Input: { path: "/articles", viewports: ["desktop", "mobile"] }
106
+
107
+ Process:
108
+ 1. Check server running on port 4210
109
+ 2. Start if needed, wait for ready
110
+ 3. Navigate to http://localhost:4210/articles
111
+ 4. Resize to 1920x1080, screenshot → /tmp/articles-desktop.png
112
+ 5. Resize to 375x667, screenshot → /tmp/articles-mobile.png
113
+ 6. Upload both via maia-api agent
114
+ 7. Return URLs
115
+
116
+ Output:
117
+ {
118
+ "desktop": "https://maia-ai-api.smartsoft.biz.pl/files/abc123",
119
+ "mobile": "https://maia-ai-api.smartsoft.biz.pl/files/def456"
120
+ }
121
+ ```
122
+
123
+ ### Capture Before/After
124
+
125
+ ```
126
+ Input: {
127
+ path: "/profile",
128
+ phase: "before" | "after",
129
+ viewports: ["desktop", "mobile"]
130
+ }
131
+
132
+ Output:
133
+ {
134
+ "phase": "before",
135
+ "desktop": { "id": "abc123", "url": "https://..." },
136
+ "mobile": { "id": "def456", "url": "https://..." }
137
+ }
138
+ ```
139
+
140
+ ## Viewport Presets
141
+
142
+ | Preset | Dimensions | Use Case |
143
+ | ---------- | ---------- | ------------------------ |
144
+ | `desktop` | 1920x1080 | Full desktop view |
145
+ | `laptop` | 1366x768 | Common laptop resolution |
146
+ | `tablet` | 768x1024 | iPad portrait |
147
+ | `mobile` | 375x667 | iPhone SE/8 |
148
+ | `mobile-l` | 414x896 | iPhone XR/11 |
149
+
150
+ ## Server Ready Check
151
+
152
+ ```bash
153
+ # Check if server responds
154
+ check_server() {
155
+ local port=$1
156
+ local max_attempts=$2
157
+ local attempt=1
158
+
159
+ while [ $attempt -le $max_attempts ]; do
160
+ if curl -s "http://localhost:$port" > /dev/null 2>&1; then
161
+ echo "Server ready"
162
+ return 0
163
+ fi
164
+ echo "Waiting for server... ($attempt/$max_attempts)"
165
+ sleep 2
166
+ ((attempt++))
167
+ done
168
+
169
+ echo "Server not ready after $max_attempts attempts"
170
+ return 1
171
+ }
172
+
173
+ check_server 4210 15
174
+ ```
175
+
176
+ ## Output Format
177
+
178
+ When capturing screenshots, return structured data:
179
+
180
+ ```json
181
+ {
182
+ "serverStarted": true,
183
+ "port": 4210,
184
+ "screenshots": [
185
+ {
186
+ "viewport": "desktop",
187
+ "dimensions": "1920x1080",
188
+ "localPath": "/tmp/screenshot-desktop.png",
189
+ "uploadedId": "abc123",
190
+ "uploadedUrl": "https://maia-ai-api.smartsoft.biz.pl/files/abc123"
191
+ },
192
+ {
193
+ "viewport": "mobile",
194
+ "dimensions": "375x667",
195
+ "localPath": "/tmp/screenshot-mobile.png",
196
+ "uploadedId": "def456",
197
+ "uploadedUrl": "https://maia-ai-api.smartsoft.biz.pl/files/def456"
198
+ }
199
+ ]
200
+ }
201
+ ```
202
+
203
+ ## Cleanup
204
+
205
+ After screenshots are used (embedded in Linear comments), cleanup local temp files:
206
+
207
+ ```bash
208
+ rm /tmp/screenshot-*.png
209
+ ```
210
+
211
+ For API cleanup, delegate to `maia-api` agent with collected IDs.
212
+
213
+ ## Error Handling
214
+
215
+ ### Server Won't Start
216
+
217
+ If server fails to start after 30 seconds:
218
+
219
+ 1. Check for port conflicts: `lsof -i :4210`
220
+ 2. Check npm logs for errors
221
+ 3. Report error and skip screenshot capture
222
+
223
+ ### Screenshot Fails
224
+
225
+ If Playwright screenshot fails:
226
+
227
+ 1. Verify navigation succeeded
228
+ 2. Check for JavaScript errors: `mcp__playwright__browser_console_messages`
229
+ 3. Try alternative viewport
230
+ 4. Report partial success
231
+
232
+ ### Upload Fails
233
+
234
+ If maia-api upload fails:
235
+
236
+ 1. Verify file exists and has content
237
+ 2. Retry upload once
238
+ 3. Report error with local file path as fallback