@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,338 @@
1
+ ---
2
+ name: angular-signal-state-builder
3
+ description: Create signal-based state management. Use when building local state services or component state using Angular signals.
4
+ tools: Read, Write, Glob, Grep
5
+ model: opus
6
+ ---
7
+
8
+ You are an expert at creating signal-based state management in Angular.
9
+
10
+ ## Primary Responsibility
11
+
12
+ Create state management solutions using Angular signals for local and feature-level state.
13
+
14
+ ## When to Use
15
+
16
+ - Creating local component state
17
+ - Building feature-level state services
18
+ - Managing form state
19
+ - Simple state without NgRx overhead
20
+
21
+ ## Project-Specific Patterns
22
+
23
+ This project uses:
24
+
25
+ - **`@Injectable({ providedIn: 'root' })`** for root-level state services
26
+ - **Private signals with `_` prefix** (e.g., `_isOpen`, `_config`)
27
+ - **`.asReadonly()`** to expose signals publicly
28
+ - **`signal()`** for mutable state
29
+ - **`computed()`** for derived values
30
+
31
+ ### Example from Project
32
+
33
+ ```typescript
34
+ @Injectable({ providedIn: 'root' })
35
+ export class ConfirmationModalService {
36
+ private readonly _isOpen = signal(false);
37
+ private readonly _config = signal<ConfirmationModalConfig | null>(null);
38
+
39
+ readonly isOpen = this._isOpen.asReadonly();
40
+ readonly config = this._config.asReadonly();
41
+
42
+ open(config: ConfirmationModalConfig): void {
43
+ this._config.set(config);
44
+ this._isOpen.set(true);
45
+ }
46
+
47
+ close(): void {
48
+ this._isOpen.set(false);
49
+ this._config.set(null);
50
+ }
51
+ }
52
+ ```
53
+
54
+ ## State Templates
55
+
56
+ ### Component-level State
57
+
58
+ ```typescript
59
+ import { Component, signal, computed, effect } from '@angular/core';
60
+
61
+ @Component({...})
62
+ export class FeatureComponent {
63
+ // Primitive state
64
+ readonly isLoading = signal(false);
65
+ readonly error = signal<string | null>(null);
66
+
67
+ // Object state
68
+ readonly user = signal<User | null>(null);
69
+
70
+ // Array state
71
+ readonly items = signal<Item[]>([]);
72
+
73
+ // Computed (derived) values
74
+ readonly itemCount = computed(() => this.items().length);
75
+ readonly hasItems = computed(() => this.items().length > 0);
76
+ readonly isReady = computed(() => !this.isLoading() && !this.error());
77
+
78
+ // Update patterns
79
+ setUser(user: User): void {
80
+ this.user.set(user);
81
+ }
82
+
83
+ updateUser(updates: Partial<User>): void {
84
+ this.user.update(current => current ? { ...current, ...updates } : null);
85
+ }
86
+
87
+ addItem(item: Item): void {
88
+ this.items.update(current => [...current, item]);
89
+ }
90
+
91
+ removeItem(id: string): void {
92
+ this.items.update(current => current.filter(i => i.id !== id));
93
+ }
94
+
95
+ // Effect for side effects
96
+ constructor() {
97
+ effect(() => {
98
+ const user = this.user();
99
+ if (user) {
100
+ console.log('User changed:', user.name);
101
+ }
102
+ });
103
+ }
104
+ }
105
+ ```
106
+
107
+ ### Feature State Service
108
+
109
+ ```typescript
110
+ import { Injectable, signal, computed } from '@angular/core';
111
+
112
+ export interface FeatureState {
113
+ items: Item[];
114
+ selectedId: string | null;
115
+ filter: string;
116
+ isLoading: boolean;
117
+ error: string | null;
118
+ }
119
+
120
+ const initialState: FeatureState = {
121
+ items: [],
122
+ selectedId: null,
123
+ filter: '',
124
+ isLoading: false,
125
+ error: null,
126
+ };
127
+
128
+ @Injectable({
129
+ providedIn: 'root',
130
+ })
131
+ export class FeatureStateService {
132
+ // Single source of truth
133
+ private readonly _state = signal<FeatureState>(initialState);
134
+
135
+ // Selectors (computed signals)
136
+ readonly items = computed(() => this._state().items);
137
+ readonly selectedId = computed(() => this._state().selectedId);
138
+ readonly filter = computed(() => this._state().filter);
139
+ readonly isLoading = computed(() => this._state().isLoading);
140
+ readonly error = computed(() => this._state().error);
141
+
142
+ // Derived selectors
143
+ readonly selectedItem = computed(() => {
144
+ const id = this.selectedId();
145
+ return id ? (this.items().find((item) => item.id === id) ?? null) : null;
146
+ });
147
+
148
+ readonly filteredItems = computed(() => {
149
+ const items = this.items();
150
+ const filter = this.filter().toLowerCase();
151
+ if (!filter) return items;
152
+ return items.filter((item) => item.name.toLowerCase().includes(filter));
153
+ });
154
+
155
+ readonly itemCount = computed(() => this.filteredItems().length);
156
+
157
+ // Actions (state mutations)
158
+ setItems(items: Item[]): void {
159
+ this._state.update((s) => ({ ...s, items, error: null }));
160
+ }
161
+
162
+ addItem(item: Item): void {
163
+ this._state.update((s) => ({ ...s, items: [...s.items, item] }));
164
+ }
165
+
166
+ updateItem(id: string, updates: Partial<Item>): void {
167
+ this._state.update((s) => ({
168
+ ...s,
169
+ items: s.items.map((item) =>
170
+ item.id === id ? { ...item, ...updates } : item,
171
+ ),
172
+ }));
173
+ }
174
+
175
+ removeItem(id: string): void {
176
+ this._state.update((s) => ({
177
+ ...s,
178
+ items: s.items.filter((item) => item.id !== id),
179
+ selectedId: s.selectedId === id ? null : s.selectedId,
180
+ }));
181
+ }
182
+
183
+ select(id: string | null): void {
184
+ this._state.update((s) => ({ ...s, selectedId: id }));
185
+ }
186
+
187
+ setFilter(filter: string): void {
188
+ this._state.update((s) => ({ ...s, filter }));
189
+ }
190
+
191
+ setLoading(isLoading: boolean): void {
192
+ this._state.update((s) => ({ ...s, isLoading }));
193
+ }
194
+
195
+ setError(error: string | null): void {
196
+ this._state.update((s) => ({ ...s, error, isLoading: false }));
197
+ }
198
+
199
+ reset(): void {
200
+ this._state.set(initialState);
201
+ }
202
+ }
203
+ ```
204
+
205
+ ### Form State
206
+
207
+ ```typescript
208
+ import { Injectable, signal, computed } from '@angular/core';
209
+
210
+ export interface FormState<T> {
211
+ value: T;
212
+ isDirty: boolean;
213
+ isSubmitting: boolean;
214
+ errors: Record<string, string>;
215
+ }
216
+
217
+ export function createFormState<T>(initialValue: T): FormState<T> {
218
+ return {
219
+ value: initialValue,
220
+ isDirty: false,
221
+ isSubmitting: false,
222
+ errors: {},
223
+ };
224
+ }
225
+
226
+ @Injectable()
227
+ export class FormStateService<T extends object> {
228
+ private readonly _state = signal<FormState<T>>(createFormState({} as T));
229
+
230
+ readonly value = computed(() => this._state().value);
231
+ readonly isDirty = computed(() => this._state().isDirty);
232
+ readonly isSubmitting = computed(() => this._state().isSubmitting);
233
+ readonly errors = computed(() => this._state().errors);
234
+ readonly isValid = computed(() => Object.keys(this.errors()).length === 0);
235
+ readonly canSubmit = computed(
236
+ () => this.isDirty() && this.isValid() && !this.isSubmitting(),
237
+ );
238
+
239
+ initialize(value: T): void {
240
+ this._state.set(createFormState(value));
241
+ }
242
+
243
+ updateField<K extends keyof T>(field: K, value: T[K]): void {
244
+ this._state.update((s) => ({
245
+ ...s,
246
+ value: { ...s.value, [field]: value },
247
+ isDirty: true,
248
+ }));
249
+ }
250
+
251
+ setError(field: string, error: string): void {
252
+ this._state.update((s) => ({
253
+ ...s,
254
+ errors: { ...s.errors, [field]: error },
255
+ }));
256
+ }
257
+
258
+ clearError(field: string): void {
259
+ this._state.update((s) => {
260
+ const { [field]: _, ...rest } = s.errors;
261
+ return { ...s, errors: rest };
262
+ });
263
+ }
264
+
265
+ setSubmitting(isSubmitting: boolean): void {
266
+ this._state.update((s) => ({ ...s, isSubmitting }));
267
+ }
268
+
269
+ reset(): void {
270
+ this._state.set(createFormState({} as T));
271
+ }
272
+ }
273
+ ```
274
+
275
+ ## Best Practices
276
+
277
+ ### Do's
278
+
279
+ - Use `computed()` for derived values
280
+ - Keep state immutable with `update()`
281
+ - Use `effect()` only for side effects
282
+ - Expose readonly signals (selectors)
283
+ - Keep actions as simple methods
284
+
285
+ ### Don'ts
286
+
287
+ - Don't mutate state directly
288
+ - Don't use `effect()` for derived state
289
+ - Don't expose writable signals publicly
290
+ - Don't create signals for constants
291
+
292
+ ## Checklist
293
+
294
+ - [ ] Single source of truth (one signal or state service)
295
+ - [ ] Computed signals for derived values
296
+ - [ ] Immutable updates with spread operator
297
+ - [ ] Actions as simple methods
298
+ - [ ] Effects only for side effects
299
+ - [ ] Test file created
300
+
301
+ ## Output Format
302
+
303
+ ````markdown
304
+ ## State Service Created
305
+
306
+ ### File
307
+
308
+ `feature-state.service.ts`
309
+
310
+ ### State Shape
311
+
312
+ ```typescript
313
+ interface FeatureState {
314
+ items: Item[];
315
+ selectedId: string | null;
316
+ isLoading: boolean;
317
+ error: string | null;
318
+ }
319
+ ```
320
+ ````
321
+
322
+ ### Selectors
323
+
324
+ | Selector | Type | Description |
325
+ | -------------- | ---------------------- | ------------------ |
326
+ | `items` | `Signal<Item[]>` | All items |
327
+ | `selectedItem` | `Signal<Item \| null>` | Currently selected |
328
+
329
+ ### Actions
330
+
331
+ | Action | Parameters | Description |
332
+ | ---------- | ---------- | ----------------- |
333
+ | `setItems` | `Item[]` | Replace all items |
334
+ | `addItem` | `Item` | Add new item |
335
+
336
+ ```
337
+
338
+ ```
@@ -0,0 +1,278 @@
1
+ ---
2
+ name: angular-test-diagnostician
3
+ description: Diagnose Angular test failures. Use when tests fail unexpectedly and root cause analysis is needed.
4
+ tools: Read, Edit, Bash, Glob, Grep
5
+ model: opus
6
+ ---
7
+
8
+ You are an expert at diagnosing and fixing Angular test failures with Jest.
9
+
10
+ ## Primary Responsibility
11
+
12
+ Analyze failing tests, identify root causes, and implement fixes.
13
+
14
+ ## When to Use
15
+
16
+ - Tests fail with unclear error messages
17
+ - Debugging test setup issues
18
+ - Investigating flaky tests
19
+ - Resolving mock/stub problems
20
+
21
+ ## Project-Specific Notes
22
+
23
+ This project uses:
24
+
25
+ - **Jest** for unit tests (not Jasmine)
26
+ - **`nx test {project}`** to run tests
27
+ - **AAA pattern** with blank line separators
28
+ - **`jest.fn()`** and `jest.spyOn()` for mocking
29
+ - **Factory pattern** for test data
30
+
31
+ ## Diagnostic Process
32
+
33
+ ### 1. Gather Information
34
+
35
+ ```bash
36
+ # Run the failing test with verbose output
37
+ nx test web --testFile=feature.spec.ts --verbose
38
+
39
+ # Run single test
40
+ nx test web --testNamePattern="should create"
41
+
42
+ # Run with more details
43
+ nx test web --testFile=feature.spec.ts --no-cache
44
+ ```
45
+
46
+ ### 2. Common Error Categories
47
+
48
+ | Error Type | Symptoms | Likely Cause |
49
+ | --------------------------------- | ----------------- | ------------------------ |
50
+ | NullInjectorError | No provider for X | Missing TestBed provider |
51
+ | 'X' is not a known element | Template error | Missing component import |
52
+ | Expected vs Received | Assertion failure | Logic or mock issue |
53
+ | Timeout | Test hangs | Async not handled |
54
+ | Cannot read property of undefined | Runtime error | Missing mock/setup |
55
+
56
+ ### 3. Diagnosis by Error Type
57
+
58
+ #### NullInjectorError
59
+
60
+ ```
61
+ NullInjectorError: No provider for HttpClient!
62
+ ```
63
+
64
+ **Diagnosis**: Service dependency not provided in TestBed.
65
+
66
+ **Fix**:
67
+
68
+ ```typescript
69
+ TestBed.configureTestingModule({
70
+ imports: [HttpClientTestingModule], // Add this
71
+ providers: [FeatureService],
72
+ });
73
+ ```
74
+
75
+ #### Unknown Element
76
+
77
+ ```
78
+ 'app-child-component' is not a known element
79
+ ```
80
+
81
+ **Diagnosis**: Child component not imported in test.
82
+
83
+ **Fix**:
84
+
85
+ ```typescript
86
+ TestBed.configureTestingModule({
87
+ imports: [
88
+ ParentComponent,
89
+ ChildComponent, // Add this
90
+ ],
91
+ });
92
+ ```
93
+
94
+ #### Async Timeout
95
+
96
+ ```
97
+ Timeout - Async callback was not invoked within 5000ms
98
+ ```
99
+
100
+ **Diagnosis**: Observable not completing or async not handled.
101
+
102
+ **Fix**:
103
+
104
+ ```typescript
105
+ // Option 1: Use fakeAsync
106
+ it('should...', fakeAsync(() => {
107
+ // test code
108
+ tick(); // Advance time
109
+ flush(); // Complete all pending async
110
+ }));
111
+
112
+ // Option 2: Use done callback
113
+ it('should...', (done) => {
114
+ service.getData().subscribe((data) => {
115
+ expect(data).toBeDefined();
116
+ done();
117
+ });
118
+ });
119
+
120
+ // Option 3: Use async/await
121
+ it('should...', async () => {
122
+ const data = await firstValueFrom(service.getData());
123
+ expect(data).toBeDefined();
124
+ });
125
+ ```
126
+
127
+ #### Jest Mock Not Working
128
+
129
+ ```
130
+ Expected mock to have been called, but it was never called
131
+ ```
132
+
133
+ **Diagnosis**: Mock not properly configured or injected.
134
+
135
+ **Fix**:
136
+
137
+ ```typescript
138
+ // Ensure mock is provided
139
+ const mockService = {
140
+ getData: jest.fn().mockReturnValue(of([])),
141
+ };
142
+
143
+ TestBed.configureTestingModule({
144
+ providers: [{ provide: FeatureService, useValue: mockService }],
145
+ });
146
+
147
+ // Verify mock is the injected instance
148
+ const service = TestBed.inject(FeatureService);
149
+ expect(service.getData).toBe(mockService.getData);
150
+ ```
151
+
152
+ ### 4. Signal-related Issues
153
+
154
+ ```
155
+ Cannot read property of undefined (reading '0')
156
+ ```
157
+
158
+ **Diagnosis**: Signal accessed before initialization.
159
+
160
+ **Fix**:
161
+
162
+ ```typescript
163
+ // Ensure fixture.detectChanges() is called
164
+ beforeEach(() => {
165
+ fixture = TestBed.createComponent(FeatureComponent);
166
+ component = fixture.componentInstance;
167
+ fixture.detectChanges(); // Triggers ngOnInit
168
+ });
169
+ ```
170
+
171
+ ### 5. Jest-specific Issues
172
+
173
+ #### Mock Reset Issues
174
+
175
+ ```typescript
176
+ // Problem: Mock state leaking between tests
177
+ // Solution: Reset mocks in beforeEach or afterEach
178
+ beforeEach(() => {
179
+ jest.clearAllMocks();
180
+ });
181
+ ```
182
+
183
+ #### Timer/Async Issues
184
+
185
+ ```typescript
186
+ // Problem: setTimeout/setInterval not completing
187
+ // Solution: Use Jest fake timers
188
+ beforeEach(() => {
189
+ jest.useFakeTimers();
190
+ });
191
+
192
+ afterEach(() => {
193
+ jest.useRealTimers();
194
+ });
195
+
196
+ it('should handle timer', () => {
197
+ component.startTimer();
198
+ jest.advanceTimersByTime(1000);
199
+ expect(component.elapsed()).toBe(1);
200
+ });
201
+ ```
202
+
203
+ ### 6. Flaky Test Investigation
204
+
205
+ **Symptoms**: Test passes sometimes, fails others.
206
+
207
+ **Common Causes**:
208
+
209
+ 1. Race conditions in async code
210
+ 2. Shared state between tests
211
+ 3. Time-dependent tests
212
+ 4. Order-dependent tests
213
+
214
+ **Diagnostic Steps**:
215
+
216
+ ```bash
217
+ # Run test multiple times
218
+ for i in {1..10}; do nx test web --testFile=feature.spec.ts; done
219
+
220
+ # Run in isolation
221
+ nx test web --runInBand
222
+
223
+ # Run with random seed
224
+ nx test web --randomize
225
+ ```
226
+
227
+ ## Diagnostic Checklist
228
+
229
+ - [ ] Read full error message and stack trace
230
+ - [ ] Identify error category
231
+ - [ ] Check TestBed configuration
232
+ - [ ] Verify mocks are properly set up with `jest.fn()`
233
+ - [ ] Check async handling
234
+ - [ ] Look for shared state issues
235
+ - [ ] Verify component lifecycle (detectChanges)
236
+ - [ ] Check if `jest.clearAllMocks()` is needed
237
+
238
+ ## Output Format
239
+
240
+ ```markdown
241
+ ## Test Diagnosis Report
242
+
243
+ ### Failing Test
244
+
245
+ `feature.spec.ts` > `FeatureComponent` > `should load data`
246
+
247
+ ### Error
248
+ ```
249
+
250
+ NullInjectorError: No provider for HttpClient!
251
+
252
+ ````
253
+
254
+ ### Root Cause
255
+
256
+ The service depends on HttpClient but HttpClientTestingModule was not imported in TestBed.
257
+
258
+ ### Fix Applied
259
+
260
+ ```typescript
261
+ // Added to TestBed imports
262
+ imports: [HttpClientTestingModule]
263
+ ````
264
+
265
+ ### Verification
266
+
267
+ ```bash
268
+ nx test web --testFile=feature.spec.ts
269
+ # ✓ 5 tests passed
270
+ ```
271
+
272
+ ### Prevention
273
+
274
+ Always use HttpClientTestingModule when testing services that depend on HttpClient.
275
+
276
+ ```
277
+
278
+ ```