mindsystem-cc 3.12.0 → 3.13.1

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 (33) hide show
  1. package/agents/ms-consolidator.md +4 -4
  2. package/agents/ms-executor.md +19 -351
  3. package/agents/ms-flutter-code-quality.md +7 -6
  4. package/agents/ms-mock-generator.md +51 -138
  5. package/agents/ms-plan-checker.md +170 -175
  6. package/agents/ms-plan-writer.md +120 -115
  7. package/agents/ms-verifier.md +22 -18
  8. package/commands/ms/check-phase.md +3 -3
  9. package/commands/ms/execute-phase.md +8 -6
  10. package/commands/ms/plan-phase.md +4 -3
  11. package/commands/ms/verify-work.md +7 -7
  12. package/mindsystem/references/goal-backward.md +10 -25
  13. package/mindsystem/references/mock-patterns.md +149 -240
  14. package/mindsystem/references/plan-format.md +326 -247
  15. package/mindsystem/references/scope-estimation.md +29 -24
  16. package/mindsystem/references/tdd-execution.md +70 -0
  17. package/mindsystem/references/tdd.md +53 -194
  18. package/mindsystem/templates/UAT.md +16 -16
  19. package/mindsystem/templates/phase-prompt.md +51 -367
  20. package/mindsystem/templates/roadmap.md +1 -1
  21. package/mindsystem/templates/verification-report.md +2 -2
  22. package/mindsystem/workflows/adhoc.md +16 -21
  23. package/mindsystem/workflows/execute-phase.md +71 -49
  24. package/mindsystem/workflows/execute-plan.md +183 -1054
  25. package/mindsystem/workflows/plan-phase.md +47 -38
  26. package/mindsystem/workflows/verify-phase.md +16 -20
  27. package/mindsystem/workflows/verify-work.md +54 -67
  28. package/package.json +1 -1
  29. package/scripts/update-state.sh +59 -0
  30. package/scripts/validate-execution-order.sh +102 -0
  31. package/skills/flutter-code-quality/SKILL.md +4 -3
  32. package/mindsystem/templates/summary.md +0 -293
  33. package/mindsystem/workflows/generate-mocks.md +0 -261
@@ -1,21 +1,7 @@
1
1
  <overview>
2
- Mock patterns for manual UAT testing. Mocks are temporary scaffolding to reach testable UI states. They exist only as uncommitted changes never in commit history.
2
+ Mock patterns for manual UAT testing. Mocks are temporary inline edits to service methods — hardcoded return values that let you reach testable UI states. They exist only as uncommitted changes, never in commit history.
3
3
  </overview>
4
4
 
5
- <philosophy>
6
- **Mocks enable testing states you can't easily reach.**
7
-
8
- Without mocks, testing "error message display" requires actually triggering server errors. Testing "premium user badge" requires a premium account. Testing "empty list placeholder" requires deleting all data.
9
-
10
- **With mocks:** Set a flag, hot reload, test the UI state.
11
-
12
- **Core principles:**
13
- 1. **Temporary** — Mocks are stashed/discarded, never committed
14
- 2. **Minimal** — One override file, minimal production hooks
15
- 3. **Explicit** — Clear flags, clear toggle instructions
16
- 4. **Removable** — Delete file + remove imports = clean
17
- </philosophy>
18
-
19
5
  <classification_framework>
20
6
 
21
7
  **Two-question framework for mock classification:**
@@ -57,19 +43,161 @@ Domain terms don't map reliably to mock types. "View recipe list" needs external
57
43
 
58
44
  </classification_framework>
59
45
 
46
+ <mock_types>
47
+
48
+ | Mock Type | Enables Testing | Inline Pattern |
49
+ |-----------|-----------------|----------------|
50
+ | `error_state` | Error messages, retry UI, fallback displays | Throw exception before real implementation |
51
+ | `premium_user` | Premium badges, gated features, upgrade prompts | Return mock user object with premium fields |
52
+ | `empty_response` | Empty states, placeholder UI, "no results" | Return empty list/null before real implementation |
53
+ | `loading_state` | Loading spinners, skeleton screens | Add delay before real implementation |
54
+ | `offline` | Offline UI, cached data, sync indicators | Throw network error before real implementation |
55
+ | `transient_state` | Brief async states (loading skeletons, transitions) | Delay or never-resolve strategies (see below) |
56
+ | `external_data` | Features depending on API data that may not exist locally | Return hardcoded data objects |
57
+
58
+ </mock_types>
59
+
60
+ <inline_mock_patterns>
61
+
62
+ **Inline mocks edit service methods directly.** Add hardcoded return values BEFORE the real implementation. Mark with `// MOCK:` comment for cleanup tracking.
63
+
64
+ **Pattern:** Early return with mock comment
65
+ ```
66
+ // MOCK: {description} — revert after UAT
67
+ {hardcoded return/throw}
68
+
69
+ // Real implementation below...
70
+ ```
71
+
72
+ **By mock_type:**
73
+
74
+ **error_state** — Throw before real call:
75
+ ```dart
76
+ // Before:
77
+ Future<User> login(String email, String password) async {
78
+ final response = await _api.post('/auth/login', data: {'email': email, 'password': password});
79
+ return User.fromJson(response.data);
80
+ }
81
+
82
+ // After:
83
+ Future<User> login(String email, String password) async {
84
+ // MOCK: force login error — revert after UAT
85
+ throw Exception('Invalid credentials');
86
+
87
+ final response = await _api.post('/auth/login', data: {'email': email, 'password': password});
88
+ return User.fromJson(response.data);
89
+ }
90
+ ```
91
+
92
+ **empty_response** — Return empty collection:
93
+ ```dart
94
+ // Before:
95
+ Future<List<Recipe>> getRecipes() async {
96
+ final response = await _api.get('/recipes');
97
+ return response.data.map((j) => Recipe.fromJson(j)).toList();
98
+ }
99
+
100
+ // After:
101
+ Future<List<Recipe>> getRecipes() async {
102
+ // MOCK: force empty list — revert after UAT
103
+ return [];
104
+
105
+ final response = await _api.get('/recipes');
106
+ return response.data.map((j) => Recipe.fromJson(j)).toList();
107
+ }
108
+ ```
109
+
110
+ **premium_user / external_data** — Return hardcoded object:
111
+ ```dart
112
+ // Before:
113
+ Future<User> getCurrentUser() async {
114
+ final response = await _api.get('/user/me');
115
+ return User.fromJson(response.data);
116
+ }
117
+
118
+ // After:
119
+ Future<User> getCurrentUser() async {
120
+ // MOCK: force premium user — revert after UAT
121
+ return User(id: 'mock-001', name: 'Test User', isPremium: true, tier: 'gold');
122
+
123
+ final response = await _api.get('/user/me');
124
+ return User.fromJson(response.data);
125
+ }
126
+ ```
127
+
128
+ **TypeScript equivalents follow identical pattern** — early return/throw with `// MOCK:` comment before the real implementation.
129
+
130
+ </inline_mock_patterns>
131
+
132
+ <transient_state_patterns>
133
+
134
+ **Transient states are UI states that appear briefly during async operations.** Loading skeletons, shimmer effects, transition animations — they resolve too fast to observe and test manually.
135
+
136
+ **Two strategies:**
137
+
138
+ **1. Extended delay (default):**
139
+
140
+ Add a configurable delay before the real data returns. The transient state stays visible long enough to test.
141
+
142
+ ```dart
143
+ // MOCK: extend loading state for testing — revert after UAT
144
+ await Future.delayed(const Duration(seconds: 5));
145
+
146
+ // Real implementation continues...
147
+ final response = await _api.get('/recipes');
148
+ return response.data.map((j) => Recipe.fromJson(j)).toList();
149
+ ```
150
+
151
+ ```typescript
152
+ // MOCK: extend loading state for testing — revert after UAT
153
+ await new Promise(resolve => setTimeout(resolve, 5000));
154
+
155
+ // Real implementation continues...
156
+ const response = await fetch('/api/recipes');
157
+ return response.json();
158
+ ```
159
+
160
+ **When to use:** Testing that the loading UI (skeleton, spinner) displays correctly while waiting.
161
+
162
+ **2. Never-resolve:**
163
+
164
+ The async call never completes. The transient state stays permanently visible.
165
+
166
+ ```dart
167
+ // MOCK: freeze loading state — revert after UAT
168
+ await Completer<void>().future; // Never completes
169
+
170
+ // Real implementation continues...
171
+ ```
172
+
173
+ ```typescript
174
+ // MOCK: freeze loading state — revert after UAT
175
+ await new Promise(() => {}); // Never resolves
176
+
177
+ // Real implementation continues...
178
+ ```
179
+
180
+ **When to use:** Testing that the loading UI itself is correct (layout, styling, animation) without it disappearing.
181
+
182
+ **Choosing between strategies:**
183
+ - Testing the transition (loading → loaded): Use extended delay (5s default)
184
+ - Testing the loading UI appearance: Use never-resolve
185
+
186
+ </transient_state_patterns>
187
+
60
188
  <git_stash_lifecycle>
61
189
 
62
190
  **Why stash?**
63
191
 
64
- Fixes must be clean commits (no mock code). But after fixing, we need mocks back to re-test. Git stash enables this:
192
+ Fixes must be clean commits (no mock code). But after fixing, mocks need to be restored to re-test. Git stash enables this:
65
193
 
66
194
  ```
67
195
  ┌─────────────────────────────────────────────────────────────┐
68
196
  │ Phase 1: Setup │
69
197
  ├─────────────────────────────────────────────────────────────┤
70
198
  │ 1. git stash push -m "pre-verify-work" (if dirty) │
71
- │ 2. Mock Generator creates mock code (uncommitted)
72
- │ 3. User confirms mocks look correct
199
+ │ 2. Inline mocks applied to service methods (uncommitted)
200
+ │ 3. Mocked files tracked in UAT.md: mocked_files: [...]
73
201
  └─────────────────────────────────────────────────────────────┘
74
202
 
75
203
 
@@ -78,7 +206,7 @@ Fixes must be clean commits (no mock code). But after fixing, we need mocks back
78
206
  ├─────────────────────────────────────────────────────────────┤
79
207
  │ 4. User tests on device with mocks active │
80
208
  │ 5. User reports issue │
81
- │ 6. git stash push -m "mocks-batch-N" Stash mocks
209
+ │ 6. git stash push -m "mocks-batch-N" -- <mocked_files>
82
210
  │ 7. Fixer investigates and commits fix ← Clean commit │
83
211
  │ 8. git stash pop ← Restore mocks │
84
212
  │ 9. User re-tests specific item │
@@ -89,7 +217,7 @@ Fixes must be clean commits (no mock code). But after fixing, we need mocks back
89
217
  ┌─────────────────────────────────────────────────────────────┐
90
218
  │ Phase 3: Cleanup │
91
219
  ├─────────────────────────────────────────────────────────────┤
92
- │ 11. git stash drop Discard mocks
220
+ │ 11. git checkout -- <mocked_files> Revert mocks
93
221
  │ 12. Generate UAT fixes patch │
94
222
  │ 13. git stash pop (if pre-existing) ← Restore user work │
95
223
  └─────────────────────────────────────────────────────────────┘
@@ -97,7 +225,7 @@ Fixes must be clean commits (no mock code). But after fixing, we need mocks back
97
225
 
98
226
  **Stash naming convention:**
99
227
  - `pre-verify-work` — User's original uncommitted work
100
- - `mocks-batch-N` — Current mock state for batch N
228
+ - `mocks-batch-N` — Current mock state for batch N (stashed only during fix application)
101
229
 
102
230
  </git_stash_lifecycle>
103
231
 
@@ -121,222 +249,3 @@ git add <conflicted-file>
121
249
  **This is rare.** Mocks typically live in data layer, fixes often in UI layer.
122
250
 
123
251
  </conflict_resolution>
124
-
125
- <flutter_example>
126
-
127
- **Override file: `lib/test_overrides.dart`**
128
-
129
- ```dart
130
- // Test Overrides - DELETE THIS FILE BEFORE COMMITTING
131
- // Used for manual UAT testing only
132
-
133
- class TestOverrides {
134
- // === STATE FLAGS ===
135
- static bool forcePremiumUser = false;
136
- static bool forceErrorState = false;
137
- static bool forceEmptyResponse = false;
138
- static bool forceLoadingState = false;
139
- static bool forceTransientState = false;
140
-
141
- // === MOCK DATA ===
142
- static String mockErrorMessage = 'Simulated error for testing';
143
- static Duration mockLoadingDelay = const Duration(seconds: 3);
144
- static Duration mockTransientDelay = const Duration(seconds: 5);
145
-
146
- static Map<String, dynamic> mockPremiumUser = {
147
- 'id': 'test-user-001',
148
- 'name': 'Test Premium User',
149
- 'isPremium': true,
150
- 'subscriptionTier': 'gold',
151
- };
152
-
153
- // === RESET ===
154
- static void reset() {
155
- forcePremiumUser = false;
156
- forceErrorState = false;
157
- forceEmptyResponse = false;
158
- forceLoadingState = false;
159
- forceTransientState = false;
160
- }
161
- }
162
- ```
163
-
164
- **Production hook: `lib/services/user_service.dart`**
165
-
166
- ```dart
167
- import '../test_overrides.dart';
168
-
169
- class UserService {
170
- Future<User> getCurrentUser() async {
171
- // TEST OVERRIDE - Remove before commit
172
- if (TestOverrides.forcePremiumUser) {
173
- return User.fromJson(TestOverrides.mockPremiumUser);
174
- }
175
-
176
- // Real implementation
177
- final response = await _api.get('/user/me');
178
- return User.fromJson(response.data);
179
- }
180
-
181
- Future<List<Item>> getItems() async {
182
- // TEST OVERRIDE - Remove before commit
183
- if (TestOverrides.forceEmptyResponse) {
184
- return [];
185
- }
186
- if (TestOverrides.forceErrorState) {
187
- throw Exception(TestOverrides.mockErrorMessage);
188
- }
189
- // TEST OVERRIDE - Extend transient state (loading skeleton stays visible)
190
- if (TestOverrides.forceTransientState) {
191
- await Future.delayed(TestOverrides.mockTransientDelay);
192
- }
193
-
194
- // Real implementation
195
- final response = await _api.get('/items');
196
- return (response.data as List).map((j) => Item.fromJson(j)).toList();
197
- }
198
- }
199
- ```
200
-
201
- **Toggle instructions:**
202
-
203
- ```
204
- To enable Premium User state:
205
- 1. Open lib/test_overrides.dart
206
- 2. Set TestOverrides.forcePremiumUser = true
207
- 3. Hot reload (r in terminal)
208
- 4. Verify: User profile shows "Premium" badge
209
-
210
- To enable Error State:
211
- 1. Open lib/test_overrides.dart
212
- 2. Set TestOverrides.forceErrorState = true
213
- 3. Hot reload (r in terminal)
214
- 4. Verify: Error message appears on relevant screens
215
- ```
216
-
217
- </flutter_example>
218
-
219
- <react_example>
220
-
221
- **Override file: `src/testOverrides.ts`**
222
-
223
- ```typescript
224
- // Test Overrides - DELETE THIS FILE BEFORE COMMITTING
225
- // Used for manual UAT testing only
226
-
227
- export const testOverrides = {
228
- // === STATE FLAGS ===
229
- forcePremiumUser: false,
230
- forceErrorState: false,
231
- forceEmptyResponse: false,
232
- forceLoadingState: false,
233
-
234
- // === MOCK DATA ===
235
- mockErrorMessage: 'Simulated error for testing',
236
- mockLoadingDelayMs: 3000,
237
-
238
- mockPremiumUser: {
239
- id: 'test-user-001',
240
- name: 'Test Premium User',
241
- isPremium: true,
242
- subscriptionTier: 'gold',
243
- },
244
-
245
- // === RESET ===
246
- reset() {
247
- this.forcePremiumUser = false;
248
- this.forceErrorState = false;
249
- this.forceEmptyResponse = false;
250
- this.forceLoadingState = false;
251
- },
252
- };
253
- ```
254
-
255
- **Production hook: `src/services/userService.ts`**
256
-
257
- ```typescript
258
- import { testOverrides } from '../testOverrides';
259
-
260
- export async function getCurrentUser(): Promise<User> {
261
- // TEST OVERRIDE - Remove before commit
262
- if (testOverrides.forcePremiumUser) {
263
- return testOverrides.mockPremiumUser as User;
264
- }
265
-
266
- // Real implementation
267
- const response = await fetch('/api/user/me');
268
- return response.json();
269
- }
270
-
271
- export async function getItems(): Promise<Item[]> {
272
- // TEST OVERRIDE - Remove before commit
273
- if (testOverrides.forceEmptyResponse) {
274
- return [];
275
- }
276
- if (testOverrides.forceErrorState) {
277
- throw new Error(testOverrides.mockErrorMessage);
278
- }
279
-
280
- // Real implementation
281
- const response = await fetch('/api/items');
282
- return response.json();
283
- }
284
- ```
285
-
286
- **Toggle instructions:**
287
-
288
- ```
289
- To enable Premium User state:
290
- 1. Open src/testOverrides.ts
291
- 2. Set forcePremiumUser: true
292
- 3. Save file (auto hot reload in dev mode)
293
- 4. Verify: User profile shows "Premium" badge
294
-
295
- To enable Error State:
296
- 1. Open src/testOverrides.ts
297
- 2. Set forceErrorState: true
298
- 3. Save file (auto hot reload)
299
- 4. Verify: Error message appears on relevant screens
300
- ```
301
-
302
- </react_example>
303
-
304
- <best_practices>
305
-
306
- **Do:**
307
- - Keep all flags in one file
308
- - Use descriptive flag names (`forcePremiumUser` not `flag1`)
309
- - Add comments marking test-only code
310
- - Provide reset function
311
- - Document toggle instructions clearly
312
-
313
- **Don't:**
314
- - Create complex mock infrastructure
315
- - Add mocks in UI components (use service layer)
316
- - Commit mock code (ever)
317
- - Create multiple override files
318
- - Add conditional compilation / build flags
319
-
320
- **Signs you're over-engineering:**
321
- - More than one override file
322
- - Mock code in more than 3 production files
323
- - Complex mock data generators
324
- - Mocking at multiple layers simultaneously
325
-
326
- </best_practices>
327
-
328
- <cleanup>
329
-
330
- **After UAT complete:**
331
-
332
- 1. `git stash drop` — Removes mock stash permanently
333
- 2. Delete override file if still present
334
- 3. Remove any imports/hooks still in production code
335
-
336
- **Verification:**
337
- ```bash
338
- git status # Should show no mock-related files
339
- grep -r "testOverrides" src/ # Should find nothing (or only the override file itself)
340
- ```
341
-
342
- </cleanup>