mindsystem-cc 3.13.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.
@@ -1,182 +1,95 @@
1
1
  ---
2
2
  name: ms-mock-generator
3
- description: Generates framework-specific mock code for UAT testing. Spawned by verify-work when batch needs mocks.
3
+ description: Generates inline mock edits in batch for UAT testing. Spawned by verify-work when 5+ mocks needed.
4
4
  model: sonnet
5
5
  tools: Read, Write, Edit, Bash, Grep, Glob
6
6
  color: cyan
7
7
  ---
8
8
 
9
9
  <role>
10
- You are a Mindsystem mock generator. You create framework-appropriate mock code for manual UI verification during UAT.
10
+ You are a Mindsystem batch mock generator. You edit service/repository methods inline to hardcode return values for manual UAT testing.
11
11
 
12
- You are spawned by `/ms:verify-work` when a test batch requires mock state (error states, premium user, empty responses, loading states, etc.).
12
+ Spawned by `/ms:verify-work` when a batch requires 5+ mocks too many for main context to handle efficiently.
13
13
 
14
- Your job: Detect the framework, generate mock override files, add minimal production hooks if needed, and provide clear toggle instructions.
14
+ Your job: Read each service method, edit it to return hardcoded values before the real implementation, and report what was changed.
15
15
  </role>
16
16
 
17
17
  <context_you_receive>
18
- Your prompt will include:
18
+ Your prompt includes:
19
19
 
20
- - **Mock type needed**: The kind of state to mock (e.g., "error_state", "premium_user", "empty_response")
21
- - **Tests requiring this mock**: List of tests with their expected behaviors
20
+ - **Tests requiring mocks**: List with mock_type and expected behavior for each
22
21
  - **Phase info**: Current phase being tested
22
+ - **Mocked files so far**: Files already edited in previous batches (avoid conflicts)
23
23
  </context_you_receive>
24
24
 
25
- <framework_detection>
26
- **1. Check PROJECT.md first**
27
- ```bash
28
- cat .planning/PROJECT.md 2>/dev/null | head -50
29
- ```
25
+ <references>
26
+ @~/.claude/mindsystem/references/mock-patterns.md
27
+ </references>
30
28
 
31
- Look for project type/stack description.
32
-
33
- **2. Verify with config files**
34
- ```bash
35
- # Flutter/Dart
36
- ls pubspec.yaml 2>/dev/null
29
+ <process>
37
30
 
38
- # React/Next.js
39
- ls package.json 2>/dev/null && grep -E '"react"|"next"' package.json
40
-
41
- # React Native
42
- ls package.json 2>/dev/null && grep '"react-native"' package.json
43
-
44
- # Vue
45
- ls package.json 2>/dev/null && grep '"vue"' package.json
46
- ```
31
+ **1. Identify service methods**
47
32
 
48
- **3. Determine framework**
49
- - Flutter: `pubspec.yaml` exists
50
- - React/Next.js: `package.json` with react/next dependency
51
- - React Native: `package.json` with react-native dependency
52
- - Vue: `package.json` with vue dependency
53
- - Other: Generate generic pattern with clear adaptation notes
54
- </framework_detection>
33
+ For each test, identify the service/repository method that provides the data being tested. Use Grep to find fetch calls, API methods, or data access points related to the test's expected behavior.
55
34
 
56
- <mock_pattern>
57
- **Philosophy:** Mocks are temporary scaffolding. They should:
58
- - Be contained in as few files as possible (ideally 1 override file)
59
- - Have minimal hooks in production code (single if-check)
60
- - Be easy to completely remove (delete file + remove hooks)
35
+ **2. Read and edit each method**
61
36
 
62
- **Pattern: Override File + Minimal Hooks**
63
-
64
- 1. **Create override file** - Single file with all mock flags and data
65
- 2. **Add minimal hooks** - If-check at service/repository layer
66
- 3. **Provide toggle instructions** - How to enable/disable each state
67
-
68
- **Override file location conventions:**
69
- - Flutter: `lib/test_overrides.dart`
70
- - React/Next.js: `src/testOverrides.ts` or `lib/testOverrides.ts`
71
- - React Native: `src/testOverrides.ts`
72
- - Vue: `src/testOverrides.ts`
73
- </mock_pattern>
74
-
75
- <generation_process>
76
- **1. Analyze tests to determine mock requirements**
77
-
78
- For each test, identify:
79
- - What state needs to be simulated
80
- - What service/API call needs to be intercepted
81
- - What data should be returned
82
-
83
- **2. Create override file**
37
+ For each method, add a hardcoded return/throw BEFORE the real implementation:
84
38
 
85
39
  ```
86
- # Pattern structure (adapt to framework):
87
-
88
- # Flags
89
- forcePremiumUser = false
90
- forceErrorState = false
91
- forceEmptyResponse = false
92
- forceLoadingState = false
40
+ // MOCK: {description} revert after UAT
41
+ {hardcoded return value or throw}
93
42
 
94
- # Mock data (when flags are true)
95
- mockErrorMessage = "Simulated error for testing"
96
- mockPremiumUserData = { ... }
97
-
98
- # Reset function
99
- resetAllOverrides() { ... }
43
+ // Real implementation below...
100
44
  ```
101
45
 
102
- **3. Identify hook points**
46
+ **Patterns by mock_type:**
103
47
 
104
- Find the service/repository methods that need to check override flags.
105
- Add minimal hooks:
48
+ | mock_type | Edit pattern |
49
+ |-----------|-------------|
50
+ | `error_state` | `throw Exception('{error message}');` before real call |
51
+ | `empty_response` | `return [];` or `return null;` before real call |
52
+ | `premium_user` | `return {hardcoded user object with premium fields};` |
53
+ | `external_data` | `return {hardcoded data matching expected schema};` |
54
+ | `loading_state` | `await {5s delay};` before real call |
55
+ | `transient_state` | Delay or never-resolve — read `mock-patterns.md` transient_state_patterns |
56
+ | `offline` | `throw {network error};` before real call |
106
57
 
107
- ```
108
- # Pseudocode pattern:
109
- function getUserData() {
110
- if (testOverrides.forcePremiumUser) {
111
- return testOverrides.mockPremiumUserData
112
- }
113
- // ... real implementation
114
- }
115
- ```
58
+ **3. For transient_state mocks:** Read `mock-patterns.md` for delay injection and never-resolve strategies. Choose based on whether the test is verifying the transition or the loading UI appearance.
59
+
60
+ **4. Track all changes**
116
61
 
117
- **4. Generate toggle instructions**
62
+ Maintain a list of every file edited and what was changed.
118
63
 
119
- Clear steps for user:
120
- 1. Which file to edit
121
- 2. Which flag to set
122
- 3. How to apply (hot reload, restart, etc.)
123
- 4. How to verify mock is active
124
- </generation_process>
64
+ </process>
125
65
 
126
66
  <return_format>
127
67
  ```markdown
128
- ## MOCKS GENERATED
129
-
130
- **Framework detected:** {Flutter | React | etc.}
131
- **Mock type:** {the mock_type requested}
132
-
133
- ### Files Created
134
-
135
- **{path/to/override_file}**
136
- - Purpose: Central mock control
137
- - Flags: {list of flags added}
68
+ ## Mocks Applied
138
69
 
139
- ### Files Modified
70
+ ### Files Edited
140
71
 
141
- **{path/to/service_file}** (lines {N}-{M})
142
- - Added: Import for test overrides
143
- - Added: Override check in {method_name}
72
+ | File | Method | Mock Type | Change |
73
+ |------|--------|-----------|--------|
74
+ | `{path}` | `{methodName}` | {type} | {brief description} |
144
75
 
145
- ### Toggle Instructions
76
+ ### Cleanup
146
77
 
147
- **To enable {mock_state_1}:**
148
- 1. Open `{override_file}`
149
- 2. Set `{flag_name} = true`
150
- 3. {Hot reload / Restart app}
151
- 4. Verify: {what user should see to confirm mock is active}
152
-
153
- **To enable {mock_state_2}:**
154
- ...
155
-
156
- ### Reset
157
-
158
- To disable all mocks:
159
- 1. Set all flags to `false` in `{override_file}`
160
- 2. {Hot reload / Restart}
78
+ To revert all mocks:
79
+ ```bash
80
+ git checkout -- {space-separated list of files}
81
+ ```
161
82
 
162
- Or delete `{override_file}` entirely (hooks will use defaults).
83
+ ### Mocked Files List
84
+ {JSON array of file paths for UAT.md frontmatter}
163
85
  ```
164
86
  </return_format>
165
87
 
166
88
  <constraints>
167
- - Keep override file as simple as possible
168
- - Minimize production code modifications
169
- - Don't create complex mock infrastructure
170
- - Don't modify test files (this is for manual UAT, not automated tests)
171
- - Include clear comments marking test-only code
172
- - Generated files should be .gitignore-able if needed
89
+ - Edit existing methods only do not create new files
90
+ - Add mock code BEFORE the real implementation (early return pattern)
91
+ - Mark every edit with `// MOCK: {description} — revert after UAT`
92
+ - Do not modify test files this is for manual UAT, not automated tests
93
+ - Do not create override files or toggle flags — inline hardcoding only
94
+ - Keep mock data minimal but realistic enough for UI rendering
173
95
  </constraints>
174
-
175
- <success_criteria>
176
- - [ ] Framework correctly detected
177
- - [ ] Override file created with appropriate flags
178
- - [ ] Minimal hooks added to production code (if needed)
179
- - [ ] Clear toggle instructions for each mock state
180
- - [ ] Reset instructions provided
181
- - [ ] All files written to disk (not just returned as content)
182
- </success_criteria>
@@ -43,9 +43,9 @@ Phase: $ARGUMENTS (optional)
43
43
  4. **Extract testable deliverables** from summaries
44
44
  5. **Classify tests by mock requirements** — Use SUMMARY.md mock_hints when available; classify inline with keyword heuristics when absent. Confirm data availability with user before batching.
45
45
  6. **Group into batches** — By mock type, max 4 per batch, no-mock tests first
46
- - If any tests require mocks: Read `~/.claude/mindsystem/references/mock-patterns.md` and `~/.claude/mindsystem/workflows/generate-mocks.md` for mock generation guidance
46
+ - If any tests require transient_state mocks: Read `~/.claude/mindsystem/references/mock-patterns.md` for delay strategies
47
47
  7. **For each batch:**
48
- - If mock needed: Generate mocks, present toggle instructions, wait for confirmation
48
+ - If mock needed: Apply inline mocks (1-4 direct edits, 5+ via ms-mock-generator subagent), tell user to hot reload
49
49
  - Present tests via AskUserQuestion (Pass / Can't test / Skip / Other)
50
50
  - Process results, update UAT.md
51
51
  - **For each issue found:**
@@ -54,10 +54,10 @@ Phase: $ARGUMENTS (optional)
54
54
  - If complex: Spawn ms-verify-fixer subagent
55
55
  - 2 retries on failed re-test, then offer options
56
56
  8. **On batch transition:**
57
- - If new mock_type: Discard old mocks, generate new ones
57
+ - If new mock_type: Revert old mocks (`git checkout -- <mocked_files>`), apply new ones
58
58
  - If same mock_type: Keep mocks active
59
59
  9. **On completion:**
60
- - Discard all mocks (git stash drop)
60
+ - Revert all mocks (`git checkout -- <mocked_files>`)
61
61
  - Generate UAT fixes patch
62
62
  - Restore user's pre-existing work (if stashed)
63
63
  - Commit UAT.md, present summary
@@ -77,7 +77,7 @@ Phase: $ARGUMENTS (optional)
77
77
  - Don't run automated tests — this is manual user validation
78
78
  - Don't skip investigation — always try 2-3 tool calls before escalating
79
79
  - Don't fix complex issues inline — spawn fixer subagent for multi-file or architectural changes
80
- - Don't commit mock code — always stash before fixing
80
+ - Don't commit mock code — stash mocked files before fixing, restore after
81
81
  - Don't re-present skipped tests — assumptions stand
82
82
  </anti_patterns>
83
83
 
@@ -85,14 +85,14 @@ Phase: $ARGUMENTS (optional)
85
85
  - [ ] Dirty tree handled at start (stash/commit/abort)
86
86
  - [ ] Tests extracted from SUMMARY.md and classified
87
87
  - [ ] Tests batched by mock requirements
88
- - [ ] Mocks generated when needed with clear toggle instructions
88
+ - [ ] Mocks applied inline when needed (1-4 direct, 5+ via subagent)
89
89
  - [ ] Tests presented in batches of 4 using AskUserQuestion
90
90
  - [ ] Issues investigated with lightweight check first
91
91
  - [ ] Simple issues fixed inline with proper commit message
92
92
  - [ ] Complex issues escalated to fixer subagent
93
93
  - [ ] Failed re-tests get 2 retries then options
94
94
  - [ ] Stash conflicts auto-resolved to fix version
95
- - [ ] Mocks discarded on completion
95
+ - [ ] Mocks reverted on completion (git checkout)
96
96
  - [ ] UAT fixes patch generated
97
97
  - [ ] User's pre-existing work restored
98
98
  - [ ] UAT.md committed with final summary
@@ -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>
@@ -14,7 +14,7 @@ source: [list of SUMMARY.md files tested]
14
14
  started: [ISO timestamp]
15
15
  updated: [ISO timestamp]
16
16
  current_batch: [N]
17
- mock_stash: [stash name or null]
17
+ mocked_files: []
18
18
  pre_work_stash: [stash name or null]
19
19
  ---
20
20
 
@@ -138,7 +138,7 @@ mock_type: empty_response
138
138
  - `started`: IMMUTABLE - set on creation
139
139
  - `updated`: OVERWRITE - update on every change
140
140
  - `current_batch`: OVERWRITE - current batch number
141
- - `mock_stash`: OVERWRITE - name of stashed mocks or null
141
+ - `mocked_files`: OVERWRITE - list of files with inline mocks, or empty array
142
142
  - `pre_work_stash`: OVERWRITE - user's pre-existing work stash or null
143
143
 
144
144
  **Progress:**
@@ -196,23 +196,22 @@ mock_type: empty_response
196
196
  <mock_lifecycle>
197
197
 
198
198
  **When batch needs mocks:**
199
- 1. Generate mock files (uncommitted)
200
- 2. User enables mocks
201
- 3. Testing proceeds
199
+ 1. Edit service methods inline (hardcoded return values)
200
+ 2. Record files in `mocked_files` frontmatter
201
+ 3. User hot reloads, testing proceeds
202
202
 
203
203
  **When fix needed:**
204
- 1. `git stash push -m "mocks-batch-N"`
205
- 2. Update `mock_stash` in frontmatter
206
- 3. Fix applied, committed
207
- 4. `git stash pop` to restore mocks
208
- 5. Clear `mock_stash` if no conflicts
204
+ 1. `git stash push -m "mocks-batch-N" -- <mocked_files>`
205
+ 2. Fix applied, committed
206
+ 3. `git stash pop` to restore mocks
207
+ 4. If conflict: take fix version, remove file from `mocked_files`
209
208
 
210
209
  **On batch transition (different mock_type):**
211
- 1. Discard old mocks: `git stash drop`
212
- 2. Generate new mocks for new batch
210
+ 1. Revert old mocks: `git checkout -- <mocked_files>`
211
+ 2. Clear `mocked_files`, apply new inline mocks
213
212
 
214
213
  **On session complete:**
215
- 1. Discard all mocks: `git stash drop`
214
+ 1. Revert all mocks: `git checkout -- <mocked_files>`
216
215
  2. Restore pre_work_stash if exists
217
216
 
218
217
  </mock_lifecycle>
@@ -225,8 +224,9 @@ On `/ms:verify-work` with existing UAT.md:
225
224
  - "complete" → offer to re-run or view results
226
225
  - "testing" or "fixing" → resume
227
226
 
228
- 2. Check `mock_stash`:
229
- - If exists, offer to restore or discard
227
+ 2. Check `mocked_files`:
228
+ - If non-empty, verify mocks still present via `git diff --name-only`
229
+ - If mocks lost, regenerate for current batch
230
230
 
231
231
  3. Check `current_batch`:
232
232
  - Resume from that batch
@@ -262,7 +262,7 @@ source: 04-01-SUMMARY.md, 04-02-SUMMARY.md
262
262
  started: 2025-01-15T10:30:00Z
263
263
  updated: 2025-01-15T11:15:00Z
264
264
  current_batch: 2
265
- mock_stash: mocks-batch-2
265
+ mocked_files: [src/services/auth_service.dart, src/services/api_service.dart]
266
266
  pre_work_stash: null
267
267
  ---
268
268
 
@@ -5,7 +5,7 @@ Complete verify-and-fix session: by session end, everything verified, issues fix
5
5
  </purpose>
6
6
 
7
7
  <execution_context>
8
- <!-- mock-patterns.md and generate-mocks.md loaded on demand when mocks are needed (see classify_tests step) -->
8
+ <!-- mock-patterns.md loaded on demand for transient_state mocks (see generate_mocks step) -->
9
9
  </execution_context>
10
10
 
11
11
  <template>
@@ -232,7 +232,7 @@ tests:
232
232
  <step name="create_batches">
233
233
  **Group tests into batches:**
234
234
 
235
- **If any tests have mock_required=true:** Read `~/.claude/mindsystem/references/mock-patterns.md` and `~/.claude/mindsystem/workflows/generate-mocks.md` now for mock generation guidance.
235
+ **If any tests have mock_required=true AND batch includes `transient_state` mocks:** Read `~/.claude/mindsystem/references/mock-patterns.md` for delay/never-resolve strategies.
236
236
 
237
237
  **Rules:**
238
238
  1. Group by mock_type (tests needing same mock state go together)
@@ -311,7 +311,7 @@ source: [list of SUMMARY.md files]
311
311
  started: [ISO timestamp]
312
312
  updated: [ISO timestamp]
313
313
  current_batch: 1
314
- mock_stash: null
314
+ mocked_files: []
315
315
  pre_work_stash: [from dirty tree handling, or null]
316
316
  ---
317
317
 
@@ -378,11 +378,11 @@ Read current batch from UAT.md.
378
378
  **1. Handle mock generation (if needed):**
379
379
 
380
380
  If `mock_type` is not null AND different from previous batch:
381
- - Discard old mocks if any (use stash name from `mock_stash` in UAT.md frontmatter):
381
+ - Revert old mocks if any (from `mocked_files` in UAT.md frontmatter):
382
382
  ```bash
383
- MOCK_STASH=$(git stash list | grep "mocks-batch" | head -1 | cut -d: -f1)
384
- [ -n "$MOCK_STASH" ] && git stash drop "$MOCK_STASH"
383
+ git checkout -- <mocked_files>
385
384
  ```
385
+ - Clear `mocked_files` in frontmatter
386
386
  - Go to `generate_mocks`
387
387
 
388
388
  If `mock_type` is null or same as previous:
@@ -394,72 +394,61 @@ Go to `present_tests`
394
394
  </step>
395
395
 
396
396
  <step name="generate_mocks">
397
- **Generate mocks for current batch:**
397
+ **Generate mocks for current batch using inline approach:**
398
398
 
399
- Present mock generation options:
400
- ```
401
- ## Batch [N]: [Name]
399
+ Count mock-requiring tests in this batch.
402
400
 
403
- **Mock required:** [mock_type description]
401
+ **Decision logic:**
404
402
 
405
- This batch tests states that require mock data. Options:
403
+ | Count | Approach |
404
+ |-------|----------|
405
+ | 1-4 | Inline: edit service methods directly in main context |
406
+ | 5+ | Subagent: spawn ms-mock-generator for batch editing |
406
407
 
407
- 1. Generate mocks (Recommended) — I'll create the override files
408
- 2. I'll set up mocks manually — Skip generation, you handle it
409
- 3. Skip this batch — Log all tests as assumptions
410
- ```
408
+ **Inline approach (1-4 mocks):**
411
409
 
412
- **If "Generate mocks":**
410
+ For each test in the batch:
411
+ 1. Identify the service/repository method that provides the data
412
+ 2. Read the method
413
+ 3. Edit to hardcode desired return value BEFORE the real implementation:
414
+ ```
415
+ // MOCK: {description} — revert after UAT
416
+ {hardcoded return/throw}
417
+ ```
418
+ 4. For transient_state mocks: Read `~/.claude/mindsystem/references/mock-patterns.md` for delay/never-resolve strategies
419
+
420
+ **Subagent approach (5+ mocks):**
413
421
 
414
- Spawn mock generator:
415
422
  ```
416
423
  Task(
417
424
  prompt="""
418
- Generate mocks for manual UAT testing.
425
+ Generate inline mocks for manual UAT testing.
419
426
 
420
- Project: {from PROJECT.md}
421
427
  Phase: {phase_name}
422
- Mock type: {mock_type}
423
428
 
424
- Tests requiring this mock:
425
- {test list with expected behaviors}
429
+ Tests requiring mocks:
430
+ {test list with mock_type and expected behaviors}
426
431
 
427
- Follow patterns from @~/.claude/mindsystem/workflows/generate-mocks.md
432
+ Mocked files from previous batches (avoid conflicts):
433
+ {mocked_files from UAT.md frontmatter}
428
434
  """,
429
435
  subagent_type="ms-mock-generator",
430
436
  description="Generate {mock_type} mocks"
431
437
  )
432
438
  ```
433
439
 
434
- After mock generator returns:
440
+ **After mocks applied (both approaches):**
435
441
 
436
- 1. Update UAT.md: `mock_stash: null` (mocks are uncommitted, not stashed yet)
437
- 2. Present toggle instructions from mock generator
438
- 3. Ask user to confirm mocks are active:
442
+ 1. Record mocked files in UAT.md frontmatter: `mocked_files: [file1.dart, file2.dart, ...]`
443
+ 2. Tell user: "Mocks applied. Hot reload to test."
444
+ 3. Proceed directly to `present_tests` no user confirmation needed
439
445
 
440
- ```
441
- questions:
442
- - question: "I've created the mock files. Have you enabled the mocks and verified they're working?"
443
- header: "Mocks ready"
444
- options:
445
- - label: "Yes, mocks are active"
446
- description: "I've toggled the flags and hot reloaded"
447
- - label: "Having trouble"
448
- description: "Something isn't working with the mocks"
449
- multiSelect: false
450
- ```
451
-
452
- **If "I'll set up manually":**
453
- - Present what mock state is needed
454
- - Wait for user to confirm ready
446
+ **Skip option:**
455
447
 
456
- **If "Skip this batch":**
457
- - Prompt for reason: "Why are you skipping this batch?"
458
- - Mark all tests in batch as `skipped` with user's reason
448
+ If user has previously indicated they want to skip mock batches, or if mock generation fails:
449
+ - Mark all tests in batch as `skipped`
459
450
  - Append to Assumptions section
460
451
  - Proceed to next batch
461
-
462
- Proceed to `present_tests`.
463
452
  </step>
464
453
 
465
454
  <step name="present_tests">
@@ -574,9 +563,9 @@ For each question:
574
563
 
575
564
  **1. Stash mocks (if active):**
576
565
  ```bash
577
- git stash push -m "mocks-batch-{N}"
566
+ git stash push -m "mocks-batch-{N}" -- <mocked_files>
578
567
  ```
579
- Update UAT.md: `mock_stash: "mocks-batch-{N}"`
568
+ Use `mocked_files` list from UAT.md frontmatter.
580
569
 
581
570
  **2. Make the fix:**
582
571
  - Edit the file(s)
@@ -605,11 +594,11 @@ git stash pop
605
594
 
606
595
  **Handle stash conflict:**
607
596
  ```bash
608
- # If conflict, take fix version
597
+ # Conflict means fix touched a mocked file — take the fix version
609
598
  git checkout --theirs <conflicted-file>
610
599
  git add <conflicted-file>
611
600
  ```
612
- Log that mock was discarded for that file.
601
+ Remove conflicted file from `mocked_files` list in UAT.md (mock no longer needed for that file).
613
602
 
614
603
  **6. Request re-test:**
615
604
  ```
@@ -626,7 +615,7 @@ Go to `handle_retest`.
626
615
 
627
616
  **1. Stash mocks (if active):**
628
617
  ```bash
629
- git stash push -m "mocks-batch-{N}"
618
+ git stash push -m "mocks-batch-{N}" -- <mocked_files>
630
619
  ```
631
620
 
632
621
  **2. Spawn ms-verify-fixer:**
@@ -738,13 +727,12 @@ questions:
738
727
 
739
728
  Read full UAT file.
740
729
 
741
- Check `mock_stash` — if exists, offer to restore:
742
- ```
743
- Found stashed mocks: {mock_stash}
744
-
745
- 1. Restore mocks — Continue where we left off
746
- 2. Discard mocks — Start batch fresh
730
+ Check `mocked_files` — if non-empty, verify mocks are still present:
731
+ ```bash
732
+ git diff --name-only
747
733
  ```
734
+ If mocked files have uncommitted changes, mocks are still active — continue.
735
+ If mocked files are clean, mocks were lost — regenerate for current batch.
748
736
 
749
737
  Find current position:
750
738
  - current_batch
@@ -796,12 +784,11 @@ issues: {count}
796
784
  <step name="complete_session">
797
785
  **Complete UAT session:**
798
786
 
799
- **1. Discard mocks:**
787
+ **1. Revert mocks:**
800
788
  ```bash
801
- # Find and drop the specific mock stash (not just the top one)
802
- MOCK_STASH=$(git stash list | grep "mocks-batch" | head -1 | cut -d: -f1)
803
- [ -n "$MOCK_STASH" ] && git stash drop "$MOCK_STASH"
789
+ git checkout -- <mocked_files>
804
790
  ```
791
+ Use `mocked_files` list from UAT.md frontmatter. Clear the list after reverting.
805
792
 
806
793
  **2. Generate UAT fixes patch (if fixes were made):**
807
794
  ```bash
@@ -818,7 +805,7 @@ PRE_WORK_STASH=$(git stash list | grep "pre-verify-work" | head -1 | cut -d: -f1
818
805
 
819
806
  **4. Update UAT.md:**
820
807
  - status: complete
821
- - Clear current_batch, mock_stash
808
+ - Clear current_batch, mocked_files
822
809
  - Final Progress counts
823
810
 
824
811
  **5. Commit UAT.md:**
@@ -863,7 +850,7 @@ Check if more phases remain in ROADMAP.md:
863
850
  |---------|------|------|
864
851
  | Frontmatter.status | OVERWRITE | Phase transitions |
865
852
  | Frontmatter.current_batch | OVERWRITE | Batch transitions |
866
- | Frontmatter.mock_stash | OVERWRITE | Stash operations |
853
+ | Frontmatter.mocked_files | OVERWRITE | Mock generation/cleanup |
867
854
  | Frontmatter.updated | OVERWRITE | Every write |
868
855
  | Progress | OVERWRITE | After each test result |
869
856
  | Current Batch | OVERWRITE | Batch transitions |
@@ -895,7 +882,7 @@ Default: **major** (safe default)
895
882
  - [ ] Dirty tree handled at start
896
883
  - [ ] Tests classified by mock requirements
897
884
  - [ ] Batches created respecting dependencies and mock types
898
- - [ ] Mocks generated when needed with toggle instructions
885
+ - [ ] Mocks applied inline when needed (1-4 direct, 5+ via subagent)
899
886
  - [ ] Tests presented in batches of 4
900
887
  - [ ] Issues investigated with lightweight check (2-3 calls)
901
888
  - [ ] Simple issues fixed inline with proper commit
@@ -903,7 +890,7 @@ Default: **major** (safe default)
903
890
  - [ ] Re-test retries (2 max, tracked via retry_count) before offering options
904
891
  - [ ] Blocked tests re-presented after blocking issues resolved
905
892
  - [ ] Stash conflicts auto-resolved to fix version
906
- - [ ] Mocks discarded on completion
893
+ - [ ] Mocks reverted on completion (git checkout)
907
894
  - [ ] UAT fixes patch generated
908
895
  - [ ] User's pre-existing work restored
909
896
  - [ ] UAT.md committed with final summary
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mindsystem-cc",
3
- "version": "3.13.0",
3
+ "version": "3.13.1",
4
4
  "description": "A meta-prompting, context engineering and spec-driven development system for Claude Code by TÂCHES.",
5
5
  "bin": {
6
6
  "mindsystem-cc": "bin/install.js"
@@ -1,261 +0,0 @@
1
- <purpose>
2
- Generate framework-specific mock code for manual UAT testing. Creates override files with toggle flags and minimal production hooks.
3
-
4
- Called by verify-work workflow when a test batch requires mock state.
5
- </purpose>
6
-
7
- <philosophy>
8
- **Mocks are temporary scaffolding.**
9
-
10
- They exist only as uncommitted changes during testing. They enable reaching UI states that require specific backend conditions (premium user, error states, empty lists, loading states).
11
-
12
- **Principles:**
13
- - Minimal footprint: One override file + minimal hooks
14
- - Easy removal: Delete file, remove imports, done
15
- - Framework-appropriate: Match project conventions
16
- - User-controlled: Clear toggle instructions
17
- </philosophy>
18
-
19
- <framework_detection>
20
-
21
- **Step 1: Read PROJECT.md**
22
- ```bash
23
- cat .planning/PROJECT.md 2>/dev/null | head -50
24
- ```
25
-
26
- **Step 2: Verify with config files**
27
-
28
- | Check | Indicates |
29
- |-------|-----------|
30
- | `pubspec.yaml` exists | Flutter |
31
- | `package.json` has `"react"` or `"next"` | React/Next.js |
32
- | `package.json` has `"react-native"` | React Native |
33
- | `package.json` has `"vue"` | Vue |
34
-
35
- **Step 3: Determine file locations**
36
-
37
- | Framework | Override File | Import Pattern |
38
- |-----------|---------------|----------------|
39
- | Flutter | `lib/test_overrides.dart` | `import 'package:{app}/test_overrides.dart';` |
40
- | React/Next.js | `src/testOverrides.ts` | `import { testOverrides } from '@/testOverrides';` |
41
- | React Native | `src/testOverrides.ts` | `import { testOverrides } from '../testOverrides';` |
42
- | Vue | `src/testOverrides.ts` | `import { testOverrides } from '@/testOverrides';` |
43
-
44
- </framework_detection>
45
-
46
- <override_file_pattern>
47
-
48
- **Structure:**
49
-
50
- ```
51
- // Test Overrides - DELETE THIS FILE BEFORE COMMITTING
52
- // Used for manual UAT testing only
53
-
54
- // === STATE FLAGS ===
55
- // Set to true to enable mock state
56
-
57
- {flag declarations based on mock_type}
58
-
59
- // === MOCK DATA ===
60
- // Returned when flags are true
61
-
62
- {mock data structures}
63
-
64
- // === RESET ===
65
- // Call to disable all overrides
66
-
67
- {reset function}
68
- ```
69
-
70
- **Flag naming convention:**
71
- - `force{State}` for boolean flags (e.g., `forcePremiumUser`, `forceErrorState`)
72
- - `mock{DataType}` for mock data (e.g., `mockUserData`, `mockErrorMessage`)
73
-
74
- </override_file_pattern>
75
-
76
- <production_hook_pattern>
77
-
78
- **Minimal hooks at service/repository layer:**
79
-
80
- ```
81
- // Check override BEFORE real implementation
82
- if (testOverrides.force{State}) {
83
- return testOverrides.mock{Data};
84
- }
85
-
86
- // Real implementation continues here...
87
- ```
88
-
89
- **Placement:**
90
- - In services/repositories, not UI components
91
- - At the data fetch point, not the render point
92
- - Single if-check, no complex branching
93
-
94
- **Marking:**
95
- ```
96
- // TEST OVERRIDE - Remove before commit
97
- if (testOverrides.forceError) {
98
- throw testOverrides.mockError;
99
- }
100
- ```
101
-
102
- </production_hook_pattern>
103
-
104
- <mock_types>
105
-
106
- Common mock types and what they enable:
107
-
108
- | Mock Type | Enables Testing | Typical Flags |
109
- |-----------|-----------------|---------------|
110
- | `error_state` | Error messages, retry UI, fallback displays | `forceError`, `mockErrorMessage` |
111
- | `premium_user` | Premium badges, gated features, upgrade prompts | `forcePremium`, `mockPremiumData` |
112
- | `empty_response` | Empty states, placeholder UI, "no results" | `forceEmpty` |
113
- | `loading_state` | Loading spinners, skeleton screens | `forceLoading`, `mockLoadingDelay` |
114
- | `offline` | Offline UI, cached data, sync indicators | `forceOffline` |
115
- | `transient_state` | Brief async states (loading skeletons, transitions) | `forceTransient`, `mockTransientDelay` |
116
- | `external_data` | Features depending on API data that may not exist locally | `forceMockData`, `mockDataSet` |
117
-
118
- </mock_types>
119
-
120
- <transient_state_patterns>
121
-
122
- **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.
123
-
124
- **Two mock strategies:**
125
-
126
- **1. Extended delay strategy (default):**
127
-
128
- Add a configurable delay before the real data returns. The transient state stays visible long enough to test.
129
-
130
- ```dart
131
- // Flutter — Completer-based delay
132
- Future<List<Recipe>> getRecipes() async {
133
- // TEST OVERRIDE - Extend loading state for testing
134
- if (TestOverrides.forceTransientState) {
135
- await Future.delayed(TestOverrides.mockTransientDelay); // default 5s
136
- }
137
- // Real implementation continues...
138
- final response = await _api.get('/recipes');
139
- return response.data.map((j) => Recipe.fromJson(j)).toList();
140
- }
141
- ```
142
-
143
- ```typescript
144
- // React/Next.js — Promise delay
145
- async function getRecipes(): Promise<Recipe[]> {
146
- // TEST OVERRIDE - Extend loading state for testing
147
- if (testOverrides.forceTransientState) {
148
- await new Promise(resolve => setTimeout(resolve, testOverrides.mockTransientDelayMs));
149
- }
150
- // Real implementation continues...
151
- const response = await fetch('/api/recipes');
152
- return response.json();
153
- }
154
- ```
155
-
156
- **When to use:** Testing that the loading UI (skeleton, spinner) displays correctly while waiting.
157
-
158
- **2. Never-resolve strategy:**
159
-
160
- The async call never completes. The transient state stays permanently visible.
161
-
162
- ```dart
163
- // Flutter — Completer that never completes
164
- Future<List<Recipe>> getRecipes() async {
165
- // TEST OVERRIDE - Never resolve, keep loading state visible
166
- if (TestOverrides.forceTransientState && TestOverrides.mockTransientDelay == Duration.zero) {
167
- await Completer<void>().future; // Never completes
168
- }
169
- // Real implementation continues...
170
- }
171
- ```
172
-
173
- ```typescript
174
- // JS — Promise that never resolves
175
- async function getRecipes(): Promise<Recipe[]> {
176
- // TEST OVERRIDE - Never resolve, keep loading state visible
177
- if (testOverrides.forceTransientState && testOverrides.mockTransientDelayMs === 0) {
178
- await new Promise(() => {}); // Never resolves
179
- }
180
- // Real implementation continues...
181
- }
182
- ```
183
-
184
- **When to use:** Testing that the loading UI itself is correct (layout, styling, animation) without it disappearing.
185
-
186
- **Choosing between strategies:**
187
- - Testing the transition (loading → loaded): Use extended delay (5s default)
188
- - Testing the loading UI appearance: Use never-resolve (set delay to 0)
189
-
190
- </transient_state_patterns>
191
-
192
- <toggle_instructions_template>
193
-
194
- **Format for each mock state:**
195
-
196
- ```markdown
197
- **To enable {state_name}:**
198
- 1. Open `{override_file_path}`
199
- 2. Set `{flag_name} = true`
200
- 3. {Hot reload command or restart instruction}
201
- 4. Verify: {What user should see to confirm mock is active}
202
-
203
- **To disable:**
204
- 1. Set `{flag_name} = false`
205
- 2. {Hot reload / restart}
206
- ```
207
-
208
- **Framework-specific apply instructions:**
209
-
210
- | Framework | Apply Changes |
211
- |-----------|---------------|
212
- | Flutter | Hot reload (r in terminal) or hot restart (R) |
213
- | React/Next.js (dev) | Auto hot reload on save |
214
- | React Native | Shake device → Reload, or `r` in Metro |
215
- | Vue (dev) | Auto hot reload on save |
216
-
217
- </toggle_instructions_template>
218
-
219
- <spawn_mock_generator>
220
-
221
- When verify-work needs mocks:
222
-
223
- ```
224
- Task(
225
- prompt="""
226
- You are generating test mocks for manual UI verification.
227
-
228
- ## Context
229
-
230
- Project type: {detected_framework}
231
- Phase: {phase_name}
232
- Mock type needed: {mock_type}
233
-
234
- ## Tests requiring this mock
235
-
236
- {test_list_with_expected_behavior}
237
-
238
- ## Requirements
239
-
240
- 1. Create override file at standard location for this framework
241
- 2. Add minimal hooks to relevant services (if needed)
242
- 3. Provide clear toggle instructions
243
- 4. Write all files to disk
244
-
245
- Follow the patterns from @~/.claude/mindsystem/workflows/generate-mocks.md
246
- """,
247
- subagent_type="ms-mock-generator",
248
- description="Generate {mock_type} mocks"
249
- )
250
- ```
251
-
252
- </spawn_mock_generator>
253
-
254
- <success_criteria>
255
- - [ ] Framework correctly detected
256
- - [ ] Override file created at standard location
257
- - [ ] Minimal hooks added (only if needed)
258
- - [ ] Toggle instructions clear and complete
259
- - [ ] Files written to disk (uncommitted)
260
- - [ ] Easy to remove (clear cleanup path)
261
- </success_criteria>