claude-flow-novice 1.5.10 → 1.5.12
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.
- package/.claude-flow-novice/dist/src/cli/commands/index.js +1049 -1087
- package/.claude-flow-novice/dist/src/cli/commands/index.js.map +1 -1
- package/.claude-flow-novice/dist/src/cli/simple-commands/init/templates/CLAUDE.md +301 -26
- package/.claude-flow-novice/dist/src/cli/simple-commands/init/templates/enhanced-templates.js +3 -40
- package/CLAUDE.md +289 -1877
- package/package.json +1 -1
- package/src/cli/simple-commands/init/templates/CLAUDE.md +240 -26
- package/src/cli/simple-commands/init/templates/enhanced-templates.js +3 -40
- package/.claude-flow-novice/dist/src/cli/simple-commands/init/CLAUDE.md +0 -188
package/CLAUDE.md
CHANGED
|
@@ -1,78 +1,62 @@
|
|
|
1
|
-
# Claude
|
|
1
|
+
# Claude Flow Novice - AI Agent Orchestration
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Core Orchestration Patterns
|
|
4
|
+
|
|
5
|
+
## 🚨 CRITICAL: MANDATORY AGENT-BASED EXECUTION
|
|
6
|
+
|
|
7
|
+
**YOU MUST USE AGENTS FOR ALL NON-TRIVIAL WORK - NO EXCEPTIONS**
|
|
4
8
|
|
|
5
9
|
**ABSOLUTE RULES**:
|
|
6
|
-
1.
|
|
7
|
-
2. **
|
|
8
|
-
3. ALWAYS
|
|
9
|
-
4. **
|
|
10
|
+
1. **ALWAYS USE AGENTS** - Tasks requiring >3 steps MUST use agent coordination
|
|
11
|
+
2. **ALWAYS INITIALIZE SWARM** - ANY multi-agent task requires swarm_init FIRST
|
|
12
|
+
3. **ALWAYS RUN POST-EDIT HOOKS** - After EVERY file edit without exception
|
|
13
|
+
4. **ALWAYS BATCH OPERATIONS** - 1 MESSAGE = ALL RELATED OPERATIONS
|
|
14
|
+
5. **NEVER WORK SOLO** - Spawn multiple agents in parallel for ALL significant tasks
|
|
15
|
+
6. **NEVER SAVE TO ROOT** - Organize files in appropriate subdirectories
|
|
16
|
+
7. **USE CLAUDE CODE'S TASK TOOL** - For spawning agents concurrently, not just MCP
|
|
17
|
+
|
|
18
|
+
### 🚫 WHEN YOU MUST USE AGENTS (MANDATORY)
|
|
19
|
+
|
|
20
|
+
**TRIGGER CONDITIONS - If ANY apply, you MUST spawn agents:**
|
|
21
|
+
- Task requires >3 distinct steps
|
|
22
|
+
- Multiple files need to be created or modified
|
|
23
|
+
- Need research + implementation + testing
|
|
24
|
+
- Architecture or design decisions required
|
|
25
|
+
- Code review or quality validation needed
|
|
26
|
+
- Security, performance, or compliance concerns
|
|
27
|
+
- Integration across multiple systems/components
|
|
28
|
+
- Documentation generation needed
|
|
29
|
+
- Refactoring or optimization work
|
|
30
|
+
- ANY feature development (even "simple" ones)
|
|
31
|
+
|
|
32
|
+
### Agent Requirements by Task Complexity
|
|
33
|
+
|
|
34
|
+
| Task Size | Steps | Agent Count | Example Team Composition |
|
|
35
|
+
|-----------|-------|-------------|--------------------------|
|
|
36
|
+
| **Simple** | 3-5 | 2-3 agents | coder + tester + reviewer |
|
|
37
|
+
| **Medium** | 6-10 | 4-6 agents | + researcher + architect + security-specialist |
|
|
38
|
+
| **Complex** | 11-20 | 8-12 agents | Full specialist team with domain experts |
|
|
39
|
+
| **Enterprise** | 20+ | 15-20 agents | + devops + api-docs + perf-analyzer + coordinators |
|
|
10
40
|
|
|
11
41
|
### ⚡ GOLDEN RULE: "1 MESSAGE = ALL RELATED OPERATIONS"
|
|
12
42
|
|
|
13
43
|
**MANDATORY PATTERNS:**
|
|
44
|
+
- **Agent Spawning**: ALWAYS spawn ALL required agents in ONE message using Task tool
|
|
14
45
|
- **TodoWrite**: ALWAYS batch ALL todos in ONE call (5-10+ todos minimum)
|
|
15
46
|
- **Task tool (Claude Code)**: ALWAYS spawn ALL agents in ONE message with full instructions
|
|
16
47
|
- **File operations**: ALWAYS batch ALL reads/writes/edits in ONE message
|
|
17
48
|
- **Bash commands**: ALWAYS batch ALL terminal operations in ONE message
|
|
18
49
|
- **Memory operations**: ALWAYS batch ALL memory store/retrieve in ONE message
|
|
19
50
|
|
|
20
|
-
###
|
|
21
|
-
|
|
22
|
-
**Claude Code's Task tool is the PRIMARY way to spawn agents:**
|
|
23
|
-
```javascript
|
|
24
|
-
// ✅ CORRECT: Use Claude Code's Task tool for parallel agent execution
|
|
25
|
-
[Single Message]:
|
|
26
|
-
Task("Research agent", "Analyze requirements and patterns...", "researcher")
|
|
27
|
-
Task("Coder agent", "Implement core features...", "coder")
|
|
28
|
-
Task("Tester agent", "Create comprehensive tests...", "tester")
|
|
29
|
-
Task("Reviewer agent", "Review code quality...", "reviewer")
|
|
30
|
-
Task("Architect agent", "Design system architecture...", "system-architect")
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Project Overview
|
|
34
|
-
|
|
35
|
-
**Project Type**: react-typescript
|
|
36
|
-
**Primary Language**: javascript
|
|
37
|
-
**Primary Framework**: react
|
|
38
|
-
**Package Manager**: npm
|
|
39
|
-
**Build Tools**: none
|
|
40
|
-
|
|
41
|
-
**Detected Languages**: javascript, typescript, rust, python
|
|
42
|
-
**Detected Frameworks**: react, express, vue, django, flask, nextjs, angular, spring, fastapi
|
|
43
|
-
**Project Directories**: src
|
|
44
|
-
|
|
45
|
-
*Auto-generated on 2025-09-30*
|
|
46
|
-
|
|
47
|
-
## 📁 File Organization Rules
|
|
48
|
-
|
|
49
|
-
**NEVER save to root folder. Use these directories:**
|
|
50
|
-
- `/src` - Source code files
|
|
51
|
-
- `/tests` - Test files
|
|
52
|
-
- `/docs` - Documentation and markdown files
|
|
53
|
-
- `/config` - Configuration files
|
|
54
|
-
- `/scripts` - Utility scripts
|
|
55
|
-
- `/examples` - Example code
|
|
56
|
-
|
|
57
|
-
## 🚀 Available Agent Types
|
|
58
|
-
|
|
59
|
-
### Core Development
|
|
60
|
-
`coder`, `reviewer`, `tester`, `planner`, `researcher`
|
|
61
|
-
|
|
62
|
-
### Backend Development
|
|
63
|
-
`backend-dev`, `api-docs`, `system-architect`, `code-analyzer`
|
|
64
|
-
|
|
65
|
-
### Frontend Development
|
|
66
|
-
`mobile-dev` (React Native), specialized frontend agents
|
|
67
|
-
|
|
68
|
-
### Testing & Validation
|
|
69
|
-
`tdd-london-swarm`, `production-validator`
|
|
51
|
+
### ⚠️ PROHIBITED SOLO WORK
|
|
70
52
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
53
|
+
**YOU ARE FORBIDDEN FROM:**
|
|
54
|
+
- ❌ Working alone on multi-step tasks
|
|
55
|
+
- ❌ Implementing features without agent coordination
|
|
56
|
+
- ❌ Skipping agent spawning because "it's simple"
|
|
57
|
+
- ❌ Writing code without a tester agent
|
|
58
|
+
- ❌ Making architectural decisions without an architect agent
|
|
59
|
+
- ❌ Deploying without security review from security-specialist agent
|
|
76
60
|
|
|
77
61
|
## 🎯 Claude Code vs MCP Tools
|
|
78
62
|
|
|
@@ -82,1909 +66,337 @@
|
|
|
82
66
|
- Code generation and programming
|
|
83
67
|
- Bash commands and system operations
|
|
84
68
|
- Implementation work
|
|
69
|
+
- Project navigation and analysis
|
|
70
|
+
- TodoWrite and task management
|
|
71
|
+
- Git operations
|
|
72
|
+
- Package management
|
|
73
|
+
- Testing and debugging
|
|
85
74
|
|
|
86
75
|
### MCP Tools ONLY COORDINATE:
|
|
87
76
|
- Swarm initialization (topology setup)
|
|
88
77
|
- Agent type definitions (coordination patterns)
|
|
89
78
|
- Task orchestration (high-level planning)
|
|
90
79
|
- Memory management
|
|
80
|
+
- Neural features
|
|
91
81
|
- Performance tracking
|
|
82
|
+
- GitHub integration
|
|
92
83
|
|
|
93
84
|
**KEY**: MCP coordinates the strategy, Claude Code's Task tool executes with real agents.
|
|
94
85
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
### Every Agent Spawned via Task Tool MUST:
|
|
86
|
+
### Agent Coordination Framework
|
|
98
87
|
|
|
99
|
-
|
|
88
|
+
#### Pre-Task Hooks (Setup & Validation)
|
|
100
89
|
```bash
|
|
101
|
-
|
|
102
|
-
npx claude-flow
|
|
103
|
-
```
|
|
90
|
+
# Validate safety and prepare resources
|
|
91
|
+
npx claude-flow-novice hooks pre-command --command "[command]" --validate-safety true --prepare-resources true
|
|
104
92
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
npx claude-flow@alpha hooks post-edit --file "[file]" --memory-key "swarm/[agent]/[step]"
|
|
108
|
-
npx claude-flow@alpha hooks notify --message "[what was done]"
|
|
93
|
+
# Auto-assign agents and load context
|
|
94
|
+
npx claude-flow-novice hooks pre-edit --file "[file]" --auto-assign-agents true --load-context true
|
|
109
95
|
```
|
|
110
96
|
|
|
111
|
-
|
|
97
|
+
#### Post-Task Hooks (Validation & Quality)
|
|
112
98
|
```bash
|
|
113
|
-
|
|
114
|
-
npx claude-flow
|
|
115
|
-
```
|
|
99
|
+
# Track metrics and store results
|
|
100
|
+
npx claude-flow-novice hooks post-command --command "[command]" --track-metrics true --store-results true
|
|
116
101
|
|
|
117
|
-
|
|
102
|
+
# Enhanced post-edit pipeline with comprehensive TDD validation
|
|
103
|
+
npx enhanced-hooks post-edit "[file]" --memory-key "swarm/[agent]/[step]" --minimum-coverage 80 --structured
|
|
118
104
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
npm install
|
|
122
|
-
npm run build
|
|
123
|
-
npm run test
|
|
124
|
-
npm run lint
|
|
125
|
-
|
|
126
|
-
# Claude Flow commands
|
|
127
|
-
npx claude-flow@alpha init
|
|
128
|
-
npx claude-flow@alpha hooks setup
|
|
129
|
-
npx claude-flow@alpha memory store
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
## Javascript Configuration
|
|
133
|
-
|
|
134
|
-
### JavaScript Development Patterns
|
|
135
|
-
|
|
136
|
-
**Code Style & Standards:**
|
|
137
|
-
- Use ES6+ features (arrow functions, destructuring, modules)
|
|
138
|
-
- Prefer `const`/`let` over `var`
|
|
139
|
-
- Use async/await over Promise chains
|
|
140
|
-
- Implement proper error boundaries
|
|
141
|
-
- Follow ESLint/Prettier configurations
|
|
142
|
-
|
|
143
|
-
**Concurrent Agent Execution:**
|
|
144
|
-
```javascript
|
|
145
|
-
// ✅ CORRECT: JavaScript development with concurrent agents
|
|
146
|
-
[Single Message]:
|
|
147
|
-
Task("Frontend Developer", "Build responsive UI with modern JavaScript", "coder")
|
|
148
|
-
Task("API Developer", "Create REST endpoints with Express/Fastify", "backend-dev")
|
|
149
|
-
Task("Test Engineer", "Write Jest/Vitest tests with >85% coverage", "tester")
|
|
150
|
-
Task("Build Engineer", "Configure Webpack/Vite build system", "system-architect")
|
|
151
|
-
Task("Quality Reviewer", "Review code quality and performance", "reviewer")
|
|
152
|
-
|
|
153
|
-
// Batch all file operations
|
|
154
|
-
Write("src/app.js")
|
|
155
|
-
Write("src/api/routes.js")
|
|
156
|
-
Write("tests/app.test.js")
|
|
157
|
-
Write("webpack.config.js")
|
|
158
|
-
|
|
159
|
-
// Batch todos for tracking
|
|
160
|
-
TodoWrite({ todos: [
|
|
161
|
-
{content: "Set up project structure", status: "in_progress", activeForm: "Setting up project structure"},
|
|
162
|
-
{content: "Implement core modules", status: "pending", activeForm: "Implementing core modules"},
|
|
163
|
-
{content: "Add error handling", status: "pending", activeForm: "Adding error handling"},
|
|
164
|
-
{content: "Write comprehensive tests", status: "pending", activeForm: "Writing comprehensive tests"},
|
|
165
|
-
{content: "Configure build pipeline", status: "pending", activeForm: "Configuring build pipeline"}
|
|
166
|
-
]})
|
|
167
|
-
```
|
|
105
|
+
# Manual hook execution (guaranteed working)
|
|
106
|
+
node src/hooks/enhanced-hooks-cli.js post-edit "[file]" --memory-key "[key]" --structured
|
|
168
107
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
// Preferred module structure
|
|
172
|
-
src/
|
|
173
|
-
components/ # Reusable components
|
|
174
|
-
utils/ # Helper functions
|
|
175
|
-
services/ # API and business logic
|
|
176
|
-
config/ # Configuration files
|
|
177
|
-
hooks/ # Custom hooks (if React)
|
|
178
|
-
types/ # Type definitions (if TypeScript)
|
|
108
|
+
# Validates: formatting, linting, type checking, dependencies, security, tests, TDD compliance
|
|
109
|
+
# Progressive validation: graceful degradation when dependencies missing (beginner-friendly)
|
|
179
110
|
```
|
|
180
111
|
|
|
181
|
-
**
|
|
182
|
-
```javascript
|
|
183
|
-
import { jest } from '@jest/globals';
|
|
112
|
+
## 🎯 **Enhanced Post-Edit Hook System**
|
|
184
113
|
|
|
185
|
-
|
|
186
|
-
beforeEach(() => {
|
|
187
|
-
jest.clearAllMocks();
|
|
188
|
-
});
|
|
114
|
+
### **🚨 MANDATORY: Manual Hook Execution After Every File Edit**
|
|
189
115
|
|
|
190
|
-
|
|
191
|
-
const mockFn = jest.fn().mockResolvedValue({ success: true });
|
|
192
|
-
const result = await asyncOperation(mockFn);
|
|
116
|
+
**CRITICAL RULE**: After **EVERY** file edit operation, you **MUST** run the enhanced post-edit hook:
|
|
193
117
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
118
|
+
```bash
|
|
119
|
+
# After editing any file, IMMEDIATELY run:
|
|
120
|
+
npx enhanced-hooks post-edit "[FILE_PATH]" --memory-key "swarm/[AGENT]/[STEP]" --minimum-coverage 80 --structured
|
|
121
|
+
|
|
122
|
+
# Or via slash command:
|
|
123
|
+
/hooks post-edit [FILE_PATH] --memory-key "[CONTEXT]" --structured
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**⚠️ NO EXCEPTIONS**: This applies to:
|
|
127
|
+
- All JavaScript/TypeScript files
|
|
128
|
+
- All Rust files
|
|
129
|
+
- All Python files
|
|
130
|
+
- All configuration files
|
|
131
|
+
- ALL file modifications
|
|
132
|
+
|
|
133
|
+
### **Enhanced Post-Edit Pipeline Features:**
|
|
134
|
+
- **🧪 TDD Testing**: Single-file testing without full system compilation
|
|
135
|
+
- **📊 Real-time Coverage**: Coverage analysis with configurable thresholds (default: 80%)
|
|
136
|
+
- **🌐 Multi-Language Support**:
|
|
137
|
+
- **JavaScript/TypeScript**: Jest, Mocha, Prettier, ESLint integration
|
|
138
|
+
- **Rust**: cargo check, cargo test, cargo-tarpaulin, rustfmt
|
|
139
|
+
- **Python**: pytest, unittest, black, pylint
|
|
140
|
+
- **Go**: go test, go fmt, go vet
|
|
141
|
+
- **Java**: JUnit, TestNG, google-java-format
|
|
142
|
+
- **C/C++**: GTest, Catch2, clang-format
|
|
143
|
+
- **🎨 Formatting**: Prettier, Black, RustFmt, GoFmt with diff preview
|
|
144
|
+
- **🔒 Security Analysis**: XSS, eval(), hardcoded credentials, SQL injection detection
|
|
145
|
+
- **✅ TDD Compliance**: Red-Green-Refactor phase detection and enforcement
|
|
146
|
+
- **🔍 Framework Detection**: Automatic test framework identification
|
|
147
|
+
- **🤖 Agent Feedback**: Structured JSON with actionable recommendations
|
|
148
|
+
- **💾 Memory Coordination**: Cross-agent state sharing and enhanced persistence
|
|
149
|
+
- **🚫 Blocking Mechanisms**: Quality gates for critical validation failures
|
|
150
|
+
|
|
151
|
+
### **Usage Examples:**
|
|
152
|
+
```bash
|
|
153
|
+
# For JavaScript/TypeScript files
|
|
154
|
+
npx enhanced-hooks post-edit "src/components/Button.tsx" --memory-key "frontend/button" --structured
|
|
197
155
|
|
|
198
|
-
|
|
199
|
-
|
|
156
|
+
# For Rust files (full cargo integration)
|
|
157
|
+
npx enhanced-hooks post-edit "src/lib.rs" --memory-key "backend/rust" --minimum-coverage 90 --structured
|
|
200
158
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
});
|
|
159
|
+
# Via slash commands in Claude Code
|
|
160
|
+
/hooks post-edit your-file.js --memory-key "agent-memory-key" --structured
|
|
204
161
|
```
|
|
205
162
|
|
|
206
|
-
**
|
|
207
|
-
- Use code splitting for large applications
|
|
208
|
-
- Implement lazy loading for routes/components
|
|
209
|
-
- Minimize bundle size with tree shaking
|
|
210
|
-
- Use Web Workers for heavy computations
|
|
211
|
-
- Implement proper caching strategies
|
|
212
|
-
|
|
213
|
-
**Error Handling:**
|
|
214
|
-
```javascript
|
|
215
|
-
// Global error handler
|
|
216
|
-
process.on('unhandledRejection', (reason, promise) => {
|
|
217
|
-
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
|
|
218
|
-
// Application specific logging logic here
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
// Async error wrapper
|
|
222
|
-
const asyncHandler = (fn) => (req, res, next) => {
|
|
223
|
-
Promise.resolve(fn(req, res, next)).catch(next);
|
|
224
|
-
};
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
**Environment Configuration:**
|
|
228
|
-
```javascript
|
|
229
|
-
// config/index.js
|
|
230
|
-
const config = {
|
|
231
|
-
development: {
|
|
232
|
-
api: {
|
|
233
|
-
baseURL: 'http://localhost:3000',
|
|
234
|
-
timeout: 5000
|
|
235
|
-
}
|
|
236
|
-
},
|
|
237
|
-
production: {
|
|
238
|
-
api: {
|
|
239
|
-
baseURL: process.env.API_BASE_URL,
|
|
240
|
-
timeout: 10000
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
|
|
245
|
-
export default config[process.env.NODE_ENV || 'development'];
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
## Typescript Configuration
|
|
249
|
-
|
|
250
|
-
### TypeScript Configuration & Patterns
|
|
251
|
-
|
|
252
|
-
**Type Safety & Standards:**
|
|
253
|
-
- Use strict TypeScript configuration
|
|
254
|
-
- Prefer interfaces over types for object shapes
|
|
255
|
-
- Use utility types (Partial, Pick, Omit, Record)
|
|
256
|
-
- Implement proper generic constraints
|
|
257
|
-
- Avoid `any` type - use `unknown` when necessary
|
|
258
|
-
|
|
259
|
-
**TypeScript Config (tsconfig.json):**
|
|
163
|
+
### **Response Structure:**
|
|
260
164
|
```json
|
|
261
165
|
{
|
|
262
|
-
"
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
"
|
|
270
|
-
"
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
"allowSyntheticDefaultImports": true,
|
|
274
|
-
"forceConsistentCasingInFileNames": true,
|
|
275
|
-
"moduleResolution": "node",
|
|
276
|
-
"resolveJsonModule": true,
|
|
277
|
-
"isolatedModules": true,
|
|
278
|
-
"noEmit": true
|
|
279
|
-
},
|
|
280
|
-
"include": ["src/**/*"],
|
|
281
|
-
"exclude": ["node_modules", "dist", "build"]
|
|
166
|
+
"success": true,
|
|
167
|
+
"file": "src/component.js",
|
|
168
|
+
"validation": { "passed": true, "issues": [], "coverage": "advanced" },
|
|
169
|
+
"formatting": { "needed": true, "changes": 12, "formatter": "prettier" },
|
|
170
|
+
"testing": { "executed": true, "framework": "jest", "results": {...} },
|
|
171
|
+
"tddCompliance": { "hasTests": true, "coverage": 85, "recommendations": [...] },
|
|
172
|
+
"recommendations": [
|
|
173
|
+
{ "type": "security", "priority": "high", "message": "...", "action": "..." },
|
|
174
|
+
{ "type": "formatting", "priority": "medium", "action": "prettier file.js" }
|
|
175
|
+
],
|
|
176
|
+
"memory": { "stored": true, "enhancedStore": true }
|
|
282
177
|
}
|
|
283
178
|
```
|
|
284
179
|
|
|
285
|
-
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
Task("TypeScript Developer", "Build type-safe modules with generics", "coder")
|
|
290
|
-
Task("Interface Designer", "Design comprehensive type definitions", "system-architect")
|
|
291
|
-
Task("Test Engineer", "Write typed tests with Jest and @types", "tester")
|
|
292
|
-
Task("Build Engineer", "Configure TypeScript compilation pipeline", "backend-dev")
|
|
293
|
-
Task("Type Reviewer", "Review type safety and consistency", "reviewer")
|
|
294
|
-
|
|
295
|
-
// Batch file operations with TypeScript focus
|
|
296
|
-
Write("src/types/api.ts")
|
|
297
|
-
Write("src/services/ApiService.ts")
|
|
298
|
-
Write("src/utils/validators.ts")
|
|
299
|
-
Write("tests/ApiService.test.ts")
|
|
300
|
-
|
|
301
|
-
// TypeScript-specific todos
|
|
302
|
-
TodoWrite({ todos: [
|
|
303
|
-
{content: "Define core type interfaces", status: "in_progress", activeForm: "Defining core type interfaces"},
|
|
304
|
-
{content: "Implement generic utility functions", status: "pending", activeForm: "Implementing generic utility functions"},
|
|
305
|
-
{content: "Add runtime type validation", status: "pending", activeForm: "Adding runtime type validation"},
|
|
306
|
-
{content: "Configure path mapping aliases", status: "pending", activeForm: "Configuring path mapping aliases"},
|
|
307
|
-
{content: "Setup strict linting rules", status: "pending", activeForm: "Setting up strict linting rules"}
|
|
308
|
-
]})
|
|
180
|
+
#### Session Management
|
|
181
|
+
```bash
|
|
182
|
+
# Generate summaries and persist state
|
|
183
|
+
npx claude-flow-novice hooks session-end --generate-summary true --persist-state true --export-metrics true
|
|
309
184
|
```
|
|
185
|
+
### 🎯 Swarm Initialization (MANDATORY for ALL Multi-Agent Tasks)
|
|
310
186
|
|
|
311
|
-
**
|
|
312
|
-
```typescript
|
|
313
|
-
// types/api.ts
|
|
314
|
-
export interface ApiResponse<T = unknown> {
|
|
315
|
-
data: T;
|
|
316
|
-
message: string;
|
|
317
|
-
status: 'success' | 'error';
|
|
318
|
-
timestamp: string;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
export interface PaginatedResponse<T> extends ApiResponse<T[]> {
|
|
322
|
-
pagination: {
|
|
323
|
-
page: number;
|
|
324
|
-
limit: number;
|
|
325
|
-
total: number;
|
|
326
|
-
hasNext: boolean;
|
|
327
|
-
};
|
|
328
|
-
}
|
|
187
|
+
**CRITICAL**: You MUST initialize swarm BEFORE spawning ANY multiple agents:
|
|
329
188
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
}
|
|
338
|
-
```
|
|
189
|
+
```javascript
|
|
190
|
+
[Single Message]:
|
|
191
|
+
// Step 1: ALWAYS initialize swarm first
|
|
192
|
+
mcp__claude-flow-novice__swarm_init({
|
|
193
|
+
topology: "mesh", // mesh (2-7 agents), hierarchical (8+)
|
|
194
|
+
maxAgents: 3, // Match your actual agent count
|
|
195
|
+
strategy: "balanced" // ensures agents coordinate and stay consistent
|
|
196
|
+
})
|
|
339
197
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
// Conditional types for API responses
|
|
346
|
-
type ApiResult<T> = T extends string
|
|
347
|
-
? ApiResponse<string>
|
|
348
|
-
: T extends number
|
|
349
|
-
? ApiResponse<number>
|
|
350
|
-
: ApiResponse<T>;
|
|
351
|
-
|
|
352
|
-
// Template literal types for routes
|
|
353
|
-
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
354
|
-
type ApiRoute<T extends string> = `/api/${T}`;
|
|
355
|
-
|
|
356
|
-
// Branded types for stronger type safety
|
|
357
|
-
type UserId = string & { readonly __brand: unique symbol };
|
|
358
|
-
type Email = string & { readonly __brand: unique symbol };
|
|
359
|
-
|
|
360
|
-
// Factory function with proper typing
|
|
361
|
-
function createUserId(value: string): UserId {
|
|
362
|
-
// Runtime validation here
|
|
363
|
-
return value as UserId;
|
|
364
|
-
}
|
|
198
|
+
// Step 2: Spawn working agents via Task tool
|
|
199
|
+
Task("Agent 1", "Specific instructions...", "type")
|
|
200
|
+
Task("Agent 2", "Specific instructions...", "type")
|
|
201
|
+
Task("Agent 3", "Specific instructions...", "type")
|
|
365
202
|
```
|
|
366
203
|
|
|
367
|
-
**
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
fetchUser: jest.MockedFunction<(id: string) => Promise<User>>;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
describe('UserService', () => {
|
|
376
|
-
let mockApi: MockApiService;
|
|
377
|
-
let userService: UserService;
|
|
378
|
-
|
|
379
|
-
beforeEach(() => {
|
|
380
|
-
mockApi = {
|
|
381
|
-
fetchUser: jest.fn()
|
|
382
|
-
};
|
|
383
|
-
userService = new UserService(mockApi);
|
|
384
|
-
});
|
|
204
|
+
**WHY THIS MATTERS:**
|
|
205
|
+
- ✅ **Prevents inconsistency**: Without swarm, 3 agents fixing JWT secrets will use 3 different methods
|
|
206
|
+
- ✅ **Ensures coordination**: Agents share findings and agree on approach
|
|
207
|
+
- ✅ **Memory coordination**: Agents access shared context via SwarmMemory
|
|
208
|
+
- ✅ **Byzantine consensus**: Final validation ensures all agents agree
|
|
385
209
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
name: 'Test User',
|
|
390
|
-
email: 'test@example.com'
|
|
391
|
-
};
|
|
210
|
+
**TOPOLOGY SELECTION:**
|
|
211
|
+
- **2-7 agents**: Use `topology: "mesh"` (peer-to-peer, equal collaboration)
|
|
212
|
+
- **8+ agents**: Use `topology: "hierarchical"` (coordinator-led structure)
|
|
392
213
|
|
|
393
|
-
|
|
214
|
+
**MCP Integration Tools:**
|
|
215
|
+
- `mcp__claude-flow-novice__swarm_init` - Initialize swarm topology (REQUIRED for ALL multi-agent tasks)
|
|
216
|
+
- `mcp__claude-flow-novice__agent_spawn` - Spawn coordination agents (recommended for consistency)
|
|
217
|
+
- `mcp__claude-flow-novice__task_orchestrate` - Orchestrate high-level workflows
|
|
218
|
+
- **Monitoring**: `swarm_status`, `agent_metrics`, `task_results`
|
|
219
|
+
- **Memory**: `memory_usage`, `memory_search`
|
|
394
220
|
|
|
395
|
-
|
|
221
|
+
---
|
|
396
222
|
|
|
397
|
-
|
|
398
|
-
expect(mockApi.fetchUser).toHaveBeenCalledWith('user-123');
|
|
399
|
-
});
|
|
400
|
-
});
|
|
401
|
-
```
|
|
223
|
+
## 📋 AGENT COORDINATION RULES
|
|
402
224
|
|
|
403
|
-
|
|
404
|
-
```typescript
|
|
405
|
-
// Result pattern for better error handling
|
|
406
|
-
type Result<T, E = Error> =
|
|
407
|
-
| { success: true; data: T }
|
|
408
|
-
| { success: false; error: E };
|
|
409
|
-
|
|
410
|
-
class ApiService {
|
|
411
|
-
async fetchData<T>(url: string): Promise<Result<T, ApiError>> {
|
|
412
|
-
try {
|
|
413
|
-
const response = await fetch(url);
|
|
414
|
-
if (!response.ok) {
|
|
415
|
-
return { success: false, error: new ApiError(response.statusText) };
|
|
416
|
-
}
|
|
417
|
-
const data = await response.json() as T;
|
|
418
|
-
return { success: true, data };
|
|
419
|
-
} catch (error) {
|
|
420
|
-
return { success: false, error: error as ApiError };
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
}
|
|
225
|
+
### Universal Agent Spawning Pattern
|
|
424
226
|
|
|
425
|
-
|
|
426
|
-
const result = await apiService.fetchData<User>('/api/users/123');
|
|
427
|
-
if (result.success) {
|
|
428
|
-
console.log(result.data.name); // TypeScript knows this is User
|
|
429
|
-
} else {
|
|
430
|
-
console.error(result.error.message); // TypeScript knows this is ApiError
|
|
431
|
-
}
|
|
432
|
-
```
|
|
227
|
+
**EVERY multi-agent task follows this structure:**
|
|
433
228
|
|
|
434
|
-
|
|
435
|
-
```
|
|
436
|
-
src/
|
|
437
|
-
types/
|
|
438
|
-
api.ts # API response types
|
|
439
|
-
domain.ts # Business domain types
|
|
440
|
-
utils.ts # Utility types
|
|
441
|
-
services/
|
|
442
|
-
BaseService.ts # Generic base service
|
|
443
|
-
UserService.ts # Concrete implementations
|
|
444
|
-
utils/
|
|
445
|
-
validators.ts # Runtime type validation
|
|
446
|
-
typeGuards.ts # Type guard functions
|
|
447
|
-
hooks/ # Custom hooks (if React)
|
|
448
|
-
useApi.ts # Generic API hook
|
|
449
|
-
```
|
|
450
|
-
|
|
451
|
-
## React Framework Configuration
|
|
452
|
-
|
|
453
|
-
### React Development Patterns
|
|
454
|
-
|
|
455
|
-
**Component Architecture:**
|
|
456
|
-
- Use functional components with hooks
|
|
457
|
-
- Implement proper component composition
|
|
458
|
-
- Follow single responsibility principle
|
|
459
|
-
- Use TypeScript for better type safety
|
|
460
|
-
- Implement proper error boundaries
|
|
461
|
-
|
|
462
|
-
**Concurrent Agent Execution:**
|
|
463
|
-
```jsx
|
|
464
|
-
// ✅ CORRECT: React development with specialized agents
|
|
229
|
+
```javascript
|
|
465
230
|
[Single Message]:
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
// Batch React file operations
|
|
473
|
-
Write("src/components/App.jsx")
|
|
474
|
-
Write("src/hooks/useApi.js")
|
|
475
|
-
Write("src/context/AppContext.jsx")
|
|
476
|
-
Write("src/styles/globals.css")
|
|
477
|
-
Write("tests/components/App.test.jsx")
|
|
478
|
-
|
|
479
|
-
// React-specific todos
|
|
480
|
-
TodoWrite({ todos: [
|
|
481
|
-
{content: "Setup component library structure", status: "in_progress", activeForm: "Setting up component library structure"},
|
|
482
|
-
{content: "Implement custom hooks for data fetching", status: "pending", activeForm: "Implementing custom hooks for data fetching"},
|
|
483
|
-
{content: "Add error boundaries and loading states", status: "pending", activeForm: "Adding error boundaries and loading states"},
|
|
484
|
-
{content: "Configure routing with React Router", status: "pending", activeForm: "Configuring routing with React Router"},
|
|
485
|
-
{content: "Optimize performance with memoization", status: "pending", activeForm: "Optimizing performance with memoization"}
|
|
486
|
-
]})
|
|
487
|
-
```
|
|
488
|
-
|
|
489
|
-
**Project Structure:**
|
|
490
|
-
```
|
|
491
|
-
src/
|
|
492
|
-
components/
|
|
493
|
-
common/ # Reusable UI components
|
|
494
|
-
Button.jsx
|
|
495
|
-
Modal.jsx
|
|
496
|
-
Input.jsx
|
|
497
|
-
layout/ # Layout components
|
|
498
|
-
Header.jsx
|
|
499
|
-
Sidebar.jsx
|
|
500
|
-
Footer.jsx
|
|
501
|
-
pages/ # Page-level components
|
|
502
|
-
HomePage.jsx
|
|
503
|
-
UserProfile.jsx
|
|
504
|
-
hooks/ # Custom hooks
|
|
505
|
-
useApi.js
|
|
506
|
-
useLocalStorage.js
|
|
507
|
-
useAuth.js
|
|
508
|
-
context/ # React context providers
|
|
509
|
-
AuthContext.jsx
|
|
510
|
-
ThemeContext.jsx
|
|
511
|
-
services/ # API services
|
|
512
|
-
api.js
|
|
513
|
-
auth.js
|
|
514
|
-
utils/ # Helper functions
|
|
515
|
-
validators.js
|
|
516
|
-
formatters.js
|
|
517
|
-
styles/ # Global styles
|
|
518
|
-
globals.css
|
|
519
|
-
variables.css
|
|
520
|
-
```
|
|
521
|
-
|
|
522
|
-
**Component Patterns:**
|
|
523
|
-
```jsx
|
|
524
|
-
import React, { useState, useEffect, useCallback, useMemo } from 'react';
|
|
525
|
-
import PropTypes from 'prop-types';
|
|
526
|
-
|
|
527
|
-
// Functional component with hooks
|
|
528
|
-
const UserProfile = ({ userId, onUpdate }) => {
|
|
529
|
-
const [user, setUser] = useState(null);
|
|
530
|
-
const [loading, setLoading] = useState(true);
|
|
531
|
-
const [error, setError] = useState(null);
|
|
532
|
-
|
|
533
|
-
// Memoized expensive calculations
|
|
534
|
-
const userStats = useMemo(() => {
|
|
535
|
-
if (!user) return null;
|
|
536
|
-
return {
|
|
537
|
-
totalPosts: user.posts?.length || 0,
|
|
538
|
-
joinedDate: new Date(user.createdAt).toLocaleDateString()
|
|
539
|
-
};
|
|
540
|
-
}, [user]);
|
|
541
|
-
|
|
542
|
-
// Memoized callbacks to prevent unnecessary re-renders
|
|
543
|
-
const handleUpdateUser = useCallback(async (updates) => {
|
|
544
|
-
try {
|
|
545
|
-
const updatedUser = await updateUser(userId, updates);
|
|
546
|
-
setUser(updatedUser);
|
|
547
|
-
onUpdate?.(updatedUser);
|
|
548
|
-
} catch (err) {
|
|
549
|
-
setError(err.message);
|
|
550
|
-
}
|
|
551
|
-
}, [userId, onUpdate]);
|
|
552
|
-
|
|
553
|
-
useEffect(() => {
|
|
554
|
-
let cancelled = false;
|
|
555
|
-
|
|
556
|
-
const fetchUser = async () => {
|
|
557
|
-
try {
|
|
558
|
-
setLoading(true);
|
|
559
|
-
const userData = await getUserById(userId);
|
|
560
|
-
if (!cancelled) {
|
|
561
|
-
setUser(userData);
|
|
562
|
-
}
|
|
563
|
-
} catch (err) {
|
|
564
|
-
if (!cancelled) {
|
|
565
|
-
setError(err.message);
|
|
566
|
-
}
|
|
567
|
-
} finally {
|
|
568
|
-
if (!cancelled) {
|
|
569
|
-
setLoading(false);
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
};
|
|
573
|
-
|
|
574
|
-
fetchUser();
|
|
575
|
-
|
|
576
|
-
return () => {
|
|
577
|
-
cancelled = true;
|
|
578
|
-
};
|
|
579
|
-
}, [userId]);
|
|
580
|
-
|
|
581
|
-
if (loading) return <LoadingSpinner />;
|
|
582
|
-
if (error) return <ErrorMessage message={error} />;
|
|
583
|
-
if (!user) return <NotFound />;
|
|
584
|
-
|
|
585
|
-
return (
|
|
586
|
-
<div className="user-profile">
|
|
587
|
-
<ProfileHeader user={user} stats={userStats} />
|
|
588
|
-
<ProfileContent user={user} onUpdate={handleUpdateUser} />
|
|
589
|
-
</div>
|
|
590
|
-
);
|
|
591
|
-
};
|
|
592
|
-
|
|
593
|
-
UserProfile.propTypes = {
|
|
594
|
-
userId: PropTypes.string.isRequired,
|
|
595
|
-
onUpdate: PropTypes.func
|
|
596
|
-
};
|
|
597
|
-
|
|
598
|
-
export default React.memo(UserProfile);
|
|
599
|
-
```
|
|
231
|
+
// Step 1: ALWAYS initialize swarm first
|
|
232
|
+
mcp__claude-flow-novice__swarm_init({
|
|
233
|
+
topology: "mesh", // or "hierarchical" for 8+ agents
|
|
234
|
+
maxAgents: X, // match your actual agent count
|
|
235
|
+
strategy: "balanced" // or "adaptive" for complex tasks
|
|
236
|
+
})
|
|
600
237
|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
//
|
|
606
|
-
export const useApi = (url, options = {}) => {
|
|
607
|
-
const [data, setData] = useState(null);
|
|
608
|
-
const [loading, setLoading] = useState(true);
|
|
609
|
-
const [error, setError] = useState(null);
|
|
610
|
-
|
|
611
|
-
const fetchData = useCallback(async () => {
|
|
612
|
-
try {
|
|
613
|
-
setLoading(true);
|
|
614
|
-
setError(null);
|
|
615
|
-
const response = await fetch(url, options);
|
|
616
|
-
|
|
617
|
-
if (!response.ok) {
|
|
618
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
const result = await response.json();
|
|
622
|
-
setData(result);
|
|
623
|
-
} catch (err) {
|
|
624
|
-
setError(err.message);
|
|
625
|
-
} finally {
|
|
626
|
-
setLoading(false);
|
|
627
|
-
}
|
|
628
|
-
}, [url, options]);
|
|
629
|
-
|
|
630
|
-
useEffect(() => {
|
|
631
|
-
fetchData();
|
|
632
|
-
}, [fetchData]);
|
|
633
|
-
|
|
634
|
-
const refetch = useCallback(() => {
|
|
635
|
-
fetchData();
|
|
636
|
-
}, [fetchData]);
|
|
637
|
-
|
|
638
|
-
return { data, loading, error, refetch };
|
|
639
|
-
};
|
|
640
|
-
|
|
641
|
-
// Local storage hook
|
|
642
|
-
export const useLocalStorage = (key, initialValue) => {
|
|
643
|
-
const [storedValue, setStoredValue] = useState(() => {
|
|
644
|
-
try {
|
|
645
|
-
const item = window.localStorage.getItem(key);
|
|
646
|
-
return item ? JSON.parse(item) : initialValue;
|
|
647
|
-
} catch (error) {
|
|
648
|
-
console.error(`Error reading localStorage key "${key}":`, error);
|
|
649
|
-
return initialValue;
|
|
650
|
-
}
|
|
651
|
-
});
|
|
652
|
-
|
|
653
|
-
const setValue = useCallback((value) => {
|
|
654
|
-
try {
|
|
655
|
-
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
|
656
|
-
setStoredValue(valueToStore);
|
|
657
|
-
window.localStorage.setItem(key, JSON.stringify(valueToStore));
|
|
658
|
-
} catch (error) {
|
|
659
|
-
console.error(`Error setting localStorage key "${key}":`, error);
|
|
660
|
-
}
|
|
661
|
-
}, [key, storedValue]);
|
|
662
|
-
|
|
663
|
-
return [storedValue, setValue];
|
|
664
|
-
};
|
|
238
|
+
// Step 2: Spawn ALL agents concurrently
|
|
239
|
+
Task("Agent Name", "Specific task instructions", "agent-type")
|
|
240
|
+
Task("Agent Name", "Specific task instructions", "agent-type")
|
|
241
|
+
Task("Agent Name", "Specific task instructions", "agent-type")
|
|
242
|
+
// ... continue for all agents
|
|
665
243
|
```
|
|
666
244
|
|
|
667
|
-
|
|
668
|
-
```jsx
|
|
669
|
-
import React, { createContext, useContext, useReducer, useCallback } from 'react';
|
|
670
|
-
|
|
671
|
-
// State and actions
|
|
672
|
-
const initialState = {
|
|
673
|
-
user: null,
|
|
674
|
-
isAuthenticated: false,
|
|
675
|
-
loading: false,
|
|
676
|
-
error: null
|
|
677
|
-
};
|
|
678
|
-
|
|
679
|
-
const authReducer = (state, action) => {
|
|
680
|
-
switch (action.type) {
|
|
681
|
-
case 'LOGIN_START':
|
|
682
|
-
return { ...state, loading: true, error: null };
|
|
683
|
-
case 'LOGIN_SUCCESS':
|
|
684
|
-
return {
|
|
685
|
-
...state,
|
|
686
|
-
user: action.payload,
|
|
687
|
-
isAuthenticated: true,
|
|
688
|
-
loading: false,
|
|
689
|
-
error: null
|
|
690
|
-
};
|
|
691
|
-
case 'LOGIN_FAILURE':
|
|
692
|
-
return {
|
|
693
|
-
...state,
|
|
694
|
-
user: null,
|
|
695
|
-
isAuthenticated: false,
|
|
696
|
-
loading: false,
|
|
697
|
-
error: action.payload
|
|
698
|
-
};
|
|
699
|
-
case 'LOGOUT':
|
|
700
|
-
return initialState;
|
|
701
|
-
default:
|
|
702
|
-
return state;
|
|
703
|
-
}
|
|
704
|
-
};
|
|
705
|
-
|
|
706
|
-
// Context creation
|
|
707
|
-
const AuthContext = createContext();
|
|
708
|
-
|
|
709
|
-
// Provider component
|
|
710
|
-
export const AuthProvider = ({ children }) => {
|
|
711
|
-
const [state, dispatch] = useReducer(authReducer, initialState);
|
|
712
|
-
|
|
713
|
-
const login = useCallback(async (credentials) => {
|
|
714
|
-
dispatch({ type: 'LOGIN_START' });
|
|
715
|
-
try {
|
|
716
|
-
const user = await authService.login(credentials);
|
|
717
|
-
dispatch({ type: 'LOGIN_SUCCESS', payload: user });
|
|
718
|
-
return user;
|
|
719
|
-
} catch (error) {
|
|
720
|
-
dispatch({ type: 'LOGIN_FAILURE', payload: error.message });
|
|
721
|
-
throw error;
|
|
722
|
-
}
|
|
723
|
-
}, []);
|
|
724
|
-
|
|
725
|
-
const logout = useCallback(() => {
|
|
726
|
-
authService.logout();
|
|
727
|
-
dispatch({ type: 'LOGOUT' });
|
|
728
|
-
}, []);
|
|
729
|
-
|
|
730
|
-
const value = {
|
|
731
|
-
...state,
|
|
732
|
-
login,
|
|
733
|
-
logout
|
|
734
|
-
};
|
|
735
|
-
|
|
736
|
-
return (
|
|
737
|
-
<AuthContext.Provider value={value}>
|
|
738
|
-
{children}
|
|
739
|
-
</AuthContext.Provider>
|
|
740
|
-
);
|
|
741
|
-
};
|
|
742
|
-
|
|
743
|
-
// Custom hook for using auth context
|
|
744
|
-
export const useAuth = () => {
|
|
745
|
-
const context = useContext(AuthContext);
|
|
746
|
-
if (!context) {
|
|
747
|
-
throw new Error('useAuth must be used within an AuthProvider');
|
|
748
|
-
}
|
|
749
|
-
return context;
|
|
750
|
-
};
|
|
751
|
-
```
|
|
752
|
-
|
|
753
|
-
**Testing with React Testing Library:**
|
|
754
|
-
```jsx
|
|
755
|
-
import React from 'react';
|
|
756
|
-
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
757
|
-
import userEvent from '@testing-library/user-event';
|
|
758
|
-
import { jest } from '@jest/globals';
|
|
759
|
-
import UserProfile from '../UserProfile';
|
|
760
|
-
import * as api from '../../services/api';
|
|
761
|
-
|
|
762
|
-
// Mock the API module
|
|
763
|
-
jest.mock('../../services/api');
|
|
764
|
-
|
|
765
|
-
describe('UserProfile', () => {
|
|
766
|
-
const mockUser = {
|
|
767
|
-
id: '123',
|
|
768
|
-
name: 'John Doe',
|
|
769
|
-
email: 'john@example.com',
|
|
770
|
-
posts: [{ id: 1, title: 'Test Post' }]
|
|
771
|
-
};
|
|
245
|
+
### Coordination Checklist
|
|
772
246
|
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
247
|
+
**Before spawning agents, ensure:**
|
|
248
|
+
- ✅ Task analyzed and complexity assessed (Simple/Medium/Complex/Enterprise)
|
|
249
|
+
- ✅ Agent count determined from requirements table
|
|
250
|
+
- ✅ Agent types selected for specific needs (not generic roles)
|
|
251
|
+
- ✅ Topology chosen: mesh (2-7) or hierarchical (8+)
|
|
252
|
+
- ✅ All agents will spawn in SINGLE message
|
|
253
|
+
- ✅ Each agent has specific, non-overlapping instructions
|
|
776
254
|
|
|
777
|
-
|
|
778
|
-
|
|
255
|
+
**During execution:**
|
|
256
|
+
- ✅ Agents coordinate through SwarmMemory
|
|
257
|
+
- ✅ Self-validation runs before consensus
|
|
258
|
+
- ✅ Each agent runs Post-edit hooks execute after file changes
|
|
779
259
|
|
|
780
|
-
|
|
260
|
+
**After completion:**
|
|
261
|
+
- ✅ Consensus validation achieved (≥90% agreement)
|
|
262
|
+
- ✅ Results stored in memory
|
|
263
|
+
- ✅ Next steps provided with claude code continuing to the next documented phase or next steps provided to user if no todos left
|
|
781
264
|
|
|
782
|
-
|
|
783
|
-
expect(screen.getByTestId('loading-spinner')).toBeInTheDocument();
|
|
265
|
+
### Agent Selection Guide
|
|
784
266
|
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
267
|
+
**Core Development**: coder, tester, reviewer
|
|
268
|
+
**Backend**: backend-dev, api-docs, system-architect
|
|
269
|
+
**Frontend**: coder (specialized), mobile-dev
|
|
270
|
+
**Quality**: tester, reviewer, security-specialist, perf-analyzer
|
|
271
|
+
**Planning**: researcher, planner, architect
|
|
272
|
+
**Operations**: devops-engineer, cicd-engineer
|
|
273
|
+
**Documentation**: api-docs, researcher
|
|
789
274
|
|
|
790
|
-
|
|
791
|
-
expect(screen.getByText('1 Posts')).toBeInTheDocument();
|
|
792
|
-
});
|
|
275
|
+
**Select agents based on actual task needs, not predefined patterns.**
|
|
793
276
|
|
|
794
|
-
|
|
795
|
-
const user = userEvent.setup();
|
|
796
|
-
const onUpdate = jest.fn();
|
|
277
|
+
---
|
|
797
278
|
|
|
798
|
-
|
|
799
|
-
api.updateUser.mockResolvedValue({ ...mockUser, name: 'Jane Doe' });
|
|
279
|
+
### ⚠️ Real-World Example: Why Swarm Coordination Matters
|
|
800
280
|
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
await waitFor(() => {
|
|
804
|
-
expect(screen.getByText('John Doe')).toBeInTheDocument();
|
|
805
|
-
});
|
|
806
|
-
|
|
807
|
-
const editButton = screen.getByRole('button', { name: /edit/i });
|
|
808
|
-
await user.click(editButton);
|
|
809
|
-
|
|
810
|
-
const nameInput = screen.getByDisplayValue('John Doe');
|
|
811
|
-
await user.clear(nameInput);
|
|
812
|
-
await user.type(nameInput, 'Jane Doe');
|
|
813
|
-
|
|
814
|
-
const saveButton = screen.getByRole('button', { name: /save/i });
|
|
815
|
-
await user.click(saveButton);
|
|
816
|
-
|
|
817
|
-
await waitFor(() => {
|
|
818
|
-
expect(onUpdate).toHaveBeenCalledWith({ ...mockUser, name: 'Jane Doe' });
|
|
819
|
-
});
|
|
820
|
-
});
|
|
821
|
-
|
|
822
|
-
test('displays error message on API failure', async () => {
|
|
823
|
-
api.getUserById.mockRejectedValue(new Error('Network error'));
|
|
824
|
-
|
|
825
|
-
render(<UserProfile userId="123" />);
|
|
826
|
-
|
|
827
|
-
await waitFor(() => {
|
|
828
|
-
expect(screen.getByText(/network error/i)).toBeInTheDocument();
|
|
829
|
-
});
|
|
830
|
-
});
|
|
831
|
-
});
|
|
832
|
-
```
|
|
833
|
-
|
|
834
|
-
**Performance Optimization:**
|
|
835
|
-
```jsx
|
|
836
|
-
import React, { memo, lazy, Suspense } from 'react';
|
|
837
|
-
|
|
838
|
-
// Lazy loading for code splitting
|
|
839
|
-
const LazyUserProfile = lazy(() => import('./UserProfile'));
|
|
840
|
-
const LazyUserSettings = lazy(() => import('./UserSettings'));
|
|
841
|
-
|
|
842
|
-
// Memoized component to prevent unnecessary re-renders
|
|
843
|
-
const UserCard = memo(({ user, onUpdate }) => {
|
|
844
|
-
return (
|
|
845
|
-
<div className="user-card">
|
|
846
|
-
<h3>{user.name}</h3>
|
|
847
|
-
<p>{user.email}</p>
|
|
848
|
-
<button onClick={() => onUpdate(user.id)}>
|
|
849
|
-
Update
|
|
850
|
-
</button>
|
|
851
|
-
</div>
|
|
852
|
-
);
|
|
853
|
-
});
|
|
854
|
-
|
|
855
|
-
// Main app with lazy loading
|
|
856
|
-
const App = () => {
|
|
857
|
-
return (
|
|
858
|
-
<div className="app">
|
|
859
|
-
<Suspense fallback={<div>Loading...</div>}>
|
|
860
|
-
<Routes>
|
|
861
|
-
<Route path="/profile" element={<LazyUserProfile />} />
|
|
862
|
-
<Route path="/settings" element={<LazyUserSettings />} />
|
|
863
|
-
</Routes>
|
|
864
|
-
</Suspense>
|
|
865
|
-
</div>
|
|
866
|
-
);
|
|
867
|
-
};
|
|
868
|
-
```
|
|
869
|
-
|
|
870
|
-
**State Management with Zustand:**
|
|
871
|
-
```jsx
|
|
872
|
-
import { create } from 'zustand';
|
|
873
|
-
import { devtools, persist } from 'zustand/middleware';
|
|
874
|
-
|
|
875
|
-
const useUserStore = create(
|
|
876
|
-
devtools(
|
|
877
|
-
persist(
|
|
878
|
-
(set, get) => ({
|
|
879
|
-
users: [],
|
|
880
|
-
currentUser: null,
|
|
881
|
-
loading: false,
|
|
882
|
-
|
|
883
|
-
fetchUsers: async () => {
|
|
884
|
-
set({ loading: true });
|
|
885
|
-
try {
|
|
886
|
-
const users = await api.getUsers();
|
|
887
|
-
set({ users, loading: false });
|
|
888
|
-
} catch (error) {
|
|
889
|
-
set({ loading: false });
|
|
890
|
-
throw error;
|
|
891
|
-
}
|
|
892
|
-
},
|
|
893
|
-
|
|
894
|
-
setCurrentUser: (user) => set({ currentUser: user }),
|
|
895
|
-
|
|
896
|
-
updateUser: async (userId, updates) => {
|
|
897
|
-
const updatedUser = await api.updateUser(userId, updates);
|
|
898
|
-
set((state) => ({
|
|
899
|
-
users: state.users.map((user) =>
|
|
900
|
-
user.id === userId ? updatedUser : user
|
|
901
|
-
),
|
|
902
|
-
currentUser: state.currentUser?.id === userId ? updatedUser : state.currentUser
|
|
903
|
-
}));
|
|
904
|
-
return updatedUser;
|
|
905
|
-
}
|
|
906
|
-
}),
|
|
907
|
-
{ name: 'user-store' }
|
|
908
|
-
)
|
|
909
|
-
)
|
|
910
|
-
);
|
|
911
|
-
|
|
912
|
-
// Usage in component
|
|
913
|
-
const UserList = () => {
|
|
914
|
-
const { users, loading, fetchUsers } = useUserStore();
|
|
915
|
-
|
|
916
|
-
useEffect(() => {
|
|
917
|
-
fetchUsers();
|
|
918
|
-
}, [fetchUsers]);
|
|
919
|
-
|
|
920
|
-
if (loading) return <LoadingSpinner />;
|
|
921
|
-
|
|
922
|
-
return (
|
|
923
|
-
<div>
|
|
924
|
-
{users.map((user) => (
|
|
925
|
-
<UserCard key={user.id} user={user} />
|
|
926
|
-
))}
|
|
927
|
-
</div>
|
|
928
|
-
);
|
|
929
|
-
};
|
|
930
|
-
```
|
|
931
|
-
|
|
932
|
-
## 🚀 Concurrent Execution Patterns
|
|
933
|
-
|
|
934
|
-
### JavaScript/TypeScript Patterns
|
|
935
|
-
|
|
936
|
-
```javascript
|
|
937
|
-
// ✅ CORRECT: Batch all operations in single message
|
|
938
|
-
[Single Message]:
|
|
939
|
-
Task("Frontend Developer", "Build React components with hooks", "coder")
|
|
940
|
-
Task("Backend Developer", "Create Express API endpoints", "backend-dev")
|
|
941
|
-
Task("Test Engineer", "Write Jest tests with >80% coverage", "tester")
|
|
942
|
-
|
|
943
|
-
// Batch file operations
|
|
944
|
-
Write("src/components/App.jsx")
|
|
945
|
-
Write("src/api/server.js")
|
|
946
|
-
Write("tests/App.test.js")
|
|
947
|
-
```
|
|
948
|
-
|
|
949
|
-
### Python Patterns
|
|
950
|
-
|
|
951
|
-
```python
|
|
952
|
-
# ✅ CORRECT: Parallel agent execution
|
|
953
|
-
[Single Message]:
|
|
954
|
-
Task("Django Developer", "Build models and views with DRF", "backend-dev")
|
|
955
|
-
Task("Frontend Developer", "Create React frontend with API integration", "coder")
|
|
956
|
-
Task("Test Engineer", "Write pytest tests with fixtures", "tester")
|
|
957
|
-
|
|
958
|
-
# Batch Python operations
|
|
959
|
-
Write("apps/models.py")
|
|
960
|
-
Write("apps/views.py")
|
|
961
|
-
Write("tests/test_models.py")
|
|
962
|
-
```
|
|
963
|
-
|
|
964
|
-
### React Development Patterns
|
|
965
|
-
|
|
966
|
-
```javascript
|
|
967
|
-
// React-specific concurrent patterns
|
|
968
|
-
[Single Message]:
|
|
969
|
-
Task("Component Developer", "Build reusable components with TypeScript", "coder")
|
|
970
|
-
Task("State Manager", "Implement Redux/Context state management", "coder")
|
|
971
|
-
Task("Test Engineer", "Write React Testing Library tests", "tester")
|
|
972
|
-
Task("Style Developer", "Create responsive CSS/Styled Components", "coder")
|
|
973
|
-
```
|
|
974
|
-
|
|
975
|
-
### API Development Patterns
|
|
976
|
-
|
|
977
|
-
```bash
|
|
978
|
-
# API-focused concurrent execution
|
|
979
|
-
[Single Message]:
|
|
980
|
-
Task("API Developer", "Build RESTful endpoints with validation", "backend-dev")
|
|
981
|
-
Task("Database Designer", "Design schema and migrations", "code-analyzer")
|
|
982
|
-
Task("Security Engineer", "Implement authentication and authorization", "reviewer")
|
|
983
|
-
Task("API Tester", "Create integration and unit tests", "tester")
|
|
984
|
-
Task("Documentation Writer", "Generate OpenAPI/Swagger docs", "researcher")
|
|
985
|
-
```
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
## 📋 Best Practices
|
|
990
|
-
|
|
991
|
-
### General Development
|
|
992
|
-
- **Modular Design**: Keep files under 500 lines
|
|
993
|
-
- **Environment Safety**: Never hardcode secrets
|
|
994
|
-
- **Test-First**: Write tests before implementation
|
|
995
|
-
- **Clean Architecture**: Separate concerns
|
|
996
|
-
- **Documentation**: Keep updated
|
|
997
|
-
|
|
998
|
-
### JavaScript/TypeScript
|
|
999
|
-
- **ES6+ Features**: Use modern JavaScript syntax
|
|
1000
|
-
- **Type Safety**: Prefer TypeScript for larger projects
|
|
1001
|
-
- **Async/Await**: Use async/await over Promise chains
|
|
1002
|
-
- **Error Handling**: Implement proper error boundaries
|
|
1003
|
-
- **Code Splitting**: Lazy load components and routes
|
|
1004
|
-
|
|
1005
|
-
### Python
|
|
1006
|
-
- **PEP 8**: Follow Python style guidelines
|
|
1007
|
-
- **Type Hints**: Use type annotations for clarity
|
|
1008
|
-
- **Virtual Environments**: Always use venv or conda
|
|
1009
|
-
- **Docstrings**: Document all functions and classes
|
|
1010
|
-
- **Error Handling**: Use specific exception types
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
## 🧪 Testing Patterns
|
|
1015
|
-
|
|
1016
|
-
### React Testing
|
|
1017
|
-
|
|
1018
|
-
```javascript
|
|
1019
|
-
import { render, screen, fireEvent } from '@testing-library/react';
|
|
1020
|
-
import userEvent from '@testing-library/user-event';
|
|
1021
|
-
|
|
1022
|
-
// Component testing pattern
|
|
1023
|
-
describe('Component', () => {
|
|
1024
|
-
test('renders and handles interaction', async () => {
|
|
1025
|
-
const user = userEvent.setup();
|
|
1026
|
-
render(<Component />);
|
|
1027
|
-
|
|
1028
|
-
const button = screen.getByRole('button');
|
|
1029
|
-
await user.click(button);
|
|
1030
|
-
|
|
1031
|
-
expect(screen.getByText(/result/i)).toBeInTheDocument();
|
|
1032
|
-
});
|
|
1033
|
-
});
|
|
1034
|
-
```
|
|
1035
|
-
|
|
1036
|
-
### Python Testing
|
|
1037
|
-
|
|
1038
|
-
```python
|
|
1039
|
-
import pytest
|
|
1040
|
-
from unittest.mock import patch, MagicMock
|
|
1041
|
-
|
|
1042
|
-
class TestAPI:
|
|
1043
|
-
@pytest.fixture
|
|
1044
|
-
def client(self):
|
|
1045
|
-
return TestClient()
|
|
1046
|
-
|
|
1047
|
-
def test_endpoint(self, client):
|
|
1048
|
-
response = client.get("/api/endpoint")
|
|
1049
|
-
assert response.status_code == 200
|
|
1050
|
-
assert response.json()["status"] == "success"
|
|
1051
|
-
```
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
## Custom Configuration
|
|
1056
|
-
|
|
1057
|
-
<!-- Preserved from existing CLAUDE.md -->
|
|
1058
|
-
hooks/ # Custom hooks (if React)
|
|
1059
|
-
types/ # Type definitions (if TypeScript)
|
|
1060
|
-
```
|
|
1061
|
-
|
|
1062
|
-
**Testing Patterns:**
|
|
281
|
+
**WITHOUT swarm_init (problematic):**
|
|
1063
282
|
```javascript
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
});
|
|
1070
|
-
|
|
1071
|
-
test('handles async operations correctly', async () => {
|
|
1072
|
-
const mockFn = jest.fn().mockResolvedValue({ success: true });
|
|
1073
|
-
const result = await asyncOperation(mockFn);
|
|
1074
|
-
|
|
1075
|
-
expect(result).toEqual({ success: true });
|
|
1076
|
-
expect(mockFn).toHaveBeenCalledTimes(1);
|
|
1077
|
-
});
|
|
1078
|
-
|
|
1079
|
-
test('handles errors gracefully', async () => {
|
|
1080
|
-
const mockFn = jest.fn().mockRejectedValue(new Error('Test error'));
|
|
1081
|
-
|
|
1082
|
-
await expect(asyncOperation(mockFn)).rejects.toThrow('Test error');
|
|
1083
|
-
});
|
|
1084
|
-
});
|
|
1085
|
-
```
|
|
1086
|
-
|
|
1087
|
-
**Performance Best Practices:**
|
|
1088
|
-
- Use code splitting for large applications
|
|
1089
|
-
- Implement lazy loading for routes/components
|
|
1090
|
-
- Minimize bundle size with tree shaking
|
|
1091
|
-
- Use Web Workers for heavy computations
|
|
1092
|
-
- Implement proper caching strategies
|
|
283
|
+
// ❌ BAD: Agents work independently with no coordination
|
|
284
|
+
[Single Message]:
|
|
285
|
+
Task("Agent 1", "Fix JWT secret issue", "coder")
|
|
286
|
+
Task("Agent 2", "Fix JWT secret issue", "coder")
|
|
287
|
+
Task("Agent 3", "Fix JWT secret issue", "coder")
|
|
1093
288
|
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
// Global error handler
|
|
1097
|
-
process.on('unhandledRejection', (reason, promise) => {
|
|
1098
|
-
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
|
|
1099
|
-
// Application specific logging logic here
|
|
1100
|
-
});
|
|
1101
|
-
|
|
1102
|
-
// Async error wrapper
|
|
1103
|
-
const asyncHandler = (fn) => (req, res, next) => {
|
|
1104
|
-
Promise.resolve(fn(req, res, next)).catch(next);
|
|
1105
|
-
};
|
|
289
|
+
// Result: 3 different solutions - environment variable, config file, hardcoded
|
|
290
|
+
// Problem: Inconsistent approach, wasted effort, integration conflicts
|
|
1106
291
|
```
|
|
1107
292
|
|
|
1108
|
-
**
|
|
293
|
+
**WITH swarm_init (correct):**
|
|
1109
294
|
```javascript
|
|
1110
|
-
//
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
},
|
|
1118
|
-
production: {
|
|
1119
|
-
api: {
|
|
1120
|
-
baseURL: process.env.API_BASE_URL,
|
|
1121
|
-
timeout: 10000
|
|
1122
|
-
}
|
|
1123
|
-
}
|
|
1124
|
-
};
|
|
1125
|
-
|
|
1126
|
-
export default config[process.env.NODE_ENV || 'development'];
|
|
1127
|
-
```
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
hooks/ # Custom hooks (if React)
|
|
1131
|
-
useApi.ts # Generic API hook
|
|
1132
|
-
```
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
hooks/ # Custom hooks
|
|
1136
|
-
useApi.js
|
|
1137
|
-
useLocalStorage.js
|
|
1138
|
-
useAuth.js
|
|
1139
|
-
context/ # React context providers
|
|
1140
|
-
AuthContext.jsx
|
|
1141
|
-
ThemeContext.jsx
|
|
1142
|
-
services/ # API services
|
|
1143
|
-
api.js
|
|
1144
|
-
auth.js
|
|
1145
|
-
utils/ # Helper functions
|
|
1146
|
-
validators.js
|
|
1147
|
-
formatters.js
|
|
1148
|
-
styles/ # Global styles
|
|
1149
|
-
globals.css
|
|
1150
|
-
variables.css
|
|
1151
|
-
```
|
|
1152
|
-
|
|
1153
|
-
**Component Patterns:**
|
|
1154
|
-
```jsx
|
|
1155
|
-
import React, { useState, useEffect, useCallback, useMemo } from 'react';
|
|
1156
|
-
import PropTypes from 'prop-types';
|
|
1157
|
-
|
|
1158
|
-
// Functional component with hooks
|
|
1159
|
-
const UserProfile = ({ userId, onUpdate }) => {
|
|
1160
|
-
const [user, setUser] = useState(null);
|
|
1161
|
-
const [loading, setLoading] = useState(true);
|
|
1162
|
-
const [error, setError] = useState(null);
|
|
1163
|
-
|
|
1164
|
-
// Memoized expensive calculations
|
|
1165
|
-
const userStats = useMemo(() => {
|
|
1166
|
-
if (!user) return null;
|
|
1167
|
-
return {
|
|
1168
|
-
totalPosts: user.posts?.length || 0,
|
|
1169
|
-
joinedDate: new Date(user.createdAt).toLocaleDateString()
|
|
1170
|
-
};
|
|
1171
|
-
}, [user]);
|
|
1172
|
-
|
|
1173
|
-
// Memoized callbacks to prevent unnecessary re-renders
|
|
1174
|
-
const handleUpdateUser = useCallback(async (updates) => {
|
|
1175
|
-
try {
|
|
1176
|
-
const updatedUser = await updateUser(userId, updates);
|
|
1177
|
-
setUser(updatedUser);
|
|
1178
|
-
onUpdate?.(updatedUser);
|
|
1179
|
-
} catch (err) {
|
|
1180
|
-
setError(err.message);
|
|
1181
|
-
}
|
|
1182
|
-
}, [userId, onUpdate]);
|
|
1183
|
-
|
|
1184
|
-
useEffect(() => {
|
|
1185
|
-
let cancelled = false;
|
|
1186
|
-
|
|
1187
|
-
const fetchUser = async () => {
|
|
1188
|
-
try {
|
|
1189
|
-
setLoading(true);
|
|
1190
|
-
const userData = await getUserById(userId);
|
|
1191
|
-
if (!cancelled) {
|
|
1192
|
-
setUser(userData);
|
|
1193
|
-
}
|
|
1194
|
-
} catch (err) {
|
|
1195
|
-
if (!cancelled) {
|
|
1196
|
-
setError(err.message);
|
|
1197
|
-
}
|
|
1198
|
-
} finally {
|
|
1199
|
-
if (!cancelled) {
|
|
1200
|
-
setLoading(false);
|
|
1201
|
-
}
|
|
1202
|
-
}
|
|
1203
|
-
};
|
|
1204
|
-
|
|
1205
|
-
fetchUser();
|
|
1206
|
-
|
|
1207
|
-
return () => {
|
|
1208
|
-
cancelled = true;
|
|
1209
|
-
};
|
|
1210
|
-
}, [userId]);
|
|
1211
|
-
|
|
1212
|
-
if (loading) return <LoadingSpinner />;
|
|
1213
|
-
if (error) return <ErrorMessage message={error} />;
|
|
1214
|
-
if (!user) return <NotFound />;
|
|
1215
|
-
|
|
1216
|
-
return (
|
|
1217
|
-
<div className="user-profile">
|
|
1218
|
-
<ProfileHeader user={user} stats={userStats} />
|
|
1219
|
-
<ProfileContent user={user} onUpdate={handleUpdateUser} />
|
|
1220
|
-
</div>
|
|
1221
|
-
);
|
|
1222
|
-
};
|
|
1223
|
-
|
|
1224
|
-
UserProfile.propTypes = {
|
|
1225
|
-
userId: PropTypes.string.isRequired,
|
|
1226
|
-
onUpdate: PropTypes.func
|
|
1227
|
-
};
|
|
1228
|
-
|
|
1229
|
-
export default React.memo(UserProfile);
|
|
1230
|
-
```
|
|
295
|
+
// ✅ GOOD: Agents coordinate through swarm
|
|
296
|
+
[Single Message]:
|
|
297
|
+
mcp__claude-flow-novice__swarm_init({
|
|
298
|
+
topology: "mesh",
|
|
299
|
+
maxAgents: 3,
|
|
300
|
+
strategy: "balanced"
|
|
301
|
+
})
|
|
1231
302
|
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
// Generic API hook
|
|
1237
|
-
export const useApi = (url, options = {}) => {
|
|
1238
|
-
const [data, setData] = useState(null);
|
|
1239
|
-
const [loading, setLoading] = useState(true);
|
|
1240
|
-
const [error, setError] = useState(null);
|
|
1241
|
-
|
|
1242
|
-
const fetchData = useCallback(async () => {
|
|
1243
|
-
try {
|
|
1244
|
-
setLoading(true);
|
|
1245
|
-
setError(null);
|
|
1246
|
-
const response = await fetch(url, options);
|
|
1247
|
-
|
|
1248
|
-
if (!response.ok) {
|
|
1249
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
1250
|
-
}
|
|
1251
|
-
|
|
1252
|
-
const result = await response.json();
|
|
1253
|
-
setData(result);
|
|
1254
|
-
} catch (err) {
|
|
1255
|
-
setError(err.message);
|
|
1256
|
-
} finally {
|
|
1257
|
-
setLoading(false);
|
|
1258
|
-
}
|
|
1259
|
-
}, [url, options]);
|
|
1260
|
-
|
|
1261
|
-
useEffect(() => {
|
|
1262
|
-
fetchData();
|
|
1263
|
-
}, [fetchData]);
|
|
1264
|
-
|
|
1265
|
-
const refetch = useCallback(() => {
|
|
1266
|
-
fetchData();
|
|
1267
|
-
}, [fetchData]);
|
|
1268
|
-
|
|
1269
|
-
return { data, loading, error, refetch };
|
|
1270
|
-
};
|
|
1271
|
-
|
|
1272
|
-
// Local storage hook
|
|
1273
|
-
export const useLocalStorage = (key, initialValue) => {
|
|
1274
|
-
const [storedValue, setStoredValue] = useState(() => {
|
|
1275
|
-
try {
|
|
1276
|
-
const item = window.localStorage.getItem(key);
|
|
1277
|
-
return item ? JSON.parse(item) : initialValue;
|
|
1278
|
-
} catch (error) {
|
|
1279
|
-
console.error(`Error reading localStorage key "${key}":`, error);
|
|
1280
|
-
return initialValue;
|
|
1281
|
-
}
|
|
1282
|
-
});
|
|
1283
|
-
|
|
1284
|
-
const setValue = useCallback((value) => {
|
|
1285
|
-
try {
|
|
1286
|
-
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
|
1287
|
-
setStoredValue(valueToStore);
|
|
1288
|
-
window.localStorage.setItem(key, JSON.stringify(valueToStore));
|
|
1289
|
-
} catch (error) {
|
|
1290
|
-
console.error(`Error setting localStorage key "${key}":`, error);
|
|
1291
|
-
}
|
|
1292
|
-
}, [key, storedValue]);
|
|
1293
|
-
|
|
1294
|
-
return [storedValue, setValue];
|
|
1295
|
-
};
|
|
1296
|
-
```
|
|
303
|
+
Task("Agent 1", "Fix JWT secret issue", "coder")
|
|
304
|
+
Task("Agent 2", "Fix JWT secret issue", "coder")
|
|
305
|
+
Task("Agent 3", "Fix JWT secret issue", "coder")
|
|
1297
306
|
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
import React, { createContext, useContext, useReducer, useCallback } from 'react';
|
|
1301
|
-
|
|
1302
|
-
// State and actions
|
|
1303
|
-
const initialState = {
|
|
1304
|
-
user: null,
|
|
1305
|
-
isAuthenticated: false,
|
|
1306
|
-
loading: false,
|
|
1307
|
-
error: null
|
|
1308
|
-
};
|
|
1309
|
-
|
|
1310
|
-
const authReducer = (state, action) => {
|
|
1311
|
-
switch (action.type) {
|
|
1312
|
-
case 'LOGIN_START':
|
|
1313
|
-
return { ...state, loading: true, error: null };
|
|
1314
|
-
case 'LOGIN_SUCCESS':
|
|
1315
|
-
return {
|
|
1316
|
-
...state,
|
|
1317
|
-
user: action.payload,
|
|
1318
|
-
isAuthenticated: true,
|
|
1319
|
-
loading: false,
|
|
1320
|
-
error: null
|
|
1321
|
-
};
|
|
1322
|
-
case 'LOGIN_FAILURE':
|
|
1323
|
-
return {
|
|
1324
|
-
...state,
|
|
1325
|
-
user: null,
|
|
1326
|
-
isAuthenticated: false,
|
|
1327
|
-
loading: false,
|
|
1328
|
-
error: action.payload
|
|
1329
|
-
};
|
|
1330
|
-
case 'LOGOUT':
|
|
1331
|
-
return initialState;
|
|
1332
|
-
default:
|
|
1333
|
-
return state;
|
|
1334
|
-
}
|
|
1335
|
-
};
|
|
1336
|
-
|
|
1337
|
-
// Context creation
|
|
1338
|
-
const AuthContext = createContext();
|
|
1339
|
-
|
|
1340
|
-
// Provider component
|
|
1341
|
-
export const AuthProvider = ({ children }) => {
|
|
1342
|
-
const [state, dispatch] = useReducer(authReducer, initialState);
|
|
1343
|
-
|
|
1344
|
-
const login = useCallback(async (credentials) => {
|
|
1345
|
-
dispatch({ type: 'LOGIN_START' });
|
|
1346
|
-
try {
|
|
1347
|
-
const user = await authService.login(credentials);
|
|
1348
|
-
dispatch({ type: 'LOGIN_SUCCESS', payload: user });
|
|
1349
|
-
return user;
|
|
1350
|
-
} catch (error) {
|
|
1351
|
-
dispatch({ type: 'LOGIN_FAILURE', payload: error.message });
|
|
1352
|
-
throw error;
|
|
1353
|
-
}
|
|
1354
|
-
}, []);
|
|
1355
|
-
|
|
1356
|
-
const logout = useCallback(() => {
|
|
1357
|
-
authService.logout();
|
|
1358
|
-
dispatch({ type: 'LOGOUT' });
|
|
1359
|
-
}, []);
|
|
1360
|
-
|
|
1361
|
-
const value = {
|
|
1362
|
-
...state,
|
|
1363
|
-
login,
|
|
1364
|
-
logout
|
|
1365
|
-
};
|
|
1366
|
-
|
|
1367
|
-
return (
|
|
1368
|
-
<AuthContext.Provider value={value}>
|
|
1369
|
-
{children}
|
|
1370
|
-
</AuthContext.Provider>
|
|
1371
|
-
);
|
|
1372
|
-
};
|
|
1373
|
-
|
|
1374
|
-
// Custom hook for using auth context
|
|
1375
|
-
export const useAuth = () => {
|
|
1376
|
-
const context = useContext(AuthContext);
|
|
1377
|
-
if (!context) {
|
|
1378
|
-
throw new Error('useAuth must be used within an AuthProvider');
|
|
1379
|
-
}
|
|
1380
|
-
return context;
|
|
1381
|
-
};
|
|
307
|
+
// Result: All 3 agents agree on environment variable approach
|
|
308
|
+
// Benefit: Consistent solution, shared context, coordinated implementation
|
|
1382
309
|
```
|
|
1383
310
|
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
import React from 'react';
|
|
1387
|
-
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
1388
|
-
import userEvent from '@testing-library/user-event';
|
|
1389
|
-
import { jest } from '@jest/globals';
|
|
1390
|
-
import UserProfile from '../UserProfile';
|
|
1391
|
-
import * as api from '../../services/api';
|
|
1392
|
-
|
|
1393
|
-
// Mock the API module
|
|
1394
|
-
jest.mock('../../services/api');
|
|
1395
|
-
|
|
1396
|
-
describe('UserProfile', () => {
|
|
1397
|
-
const mockUser = {
|
|
1398
|
-
id: '123',
|
|
1399
|
-
name: 'John Doe',
|
|
1400
|
-
email: 'john@example.com',
|
|
1401
|
-
posts: [{ id: 1, title: 'Test Post' }]
|
|
1402
|
-
};
|
|
1403
|
-
|
|
1404
|
-
beforeEach(() => {
|
|
1405
|
-
jest.clearAllMocks();
|
|
1406
|
-
});
|
|
1407
|
-
|
|
1408
|
-
test('renders user profile after loading', async () => {
|
|
1409
|
-
api.getUserById.mockResolvedValue(mockUser);
|
|
311
|
+
## File Organization
|
|
312
|
+
- **Never save working files to root**
|
|
1410
313
|
|
|
1411
|
-
|
|
314
|
+
# Add MCP server
|
|
315
|
+
claude mcp add claude-flow-novice npx claude-flow-novice mcp start
|
|
1412
316
|
|
|
1413
|
-
// Check loading state
|
|
1414
|
-
expect(screen.getByTestId('loading-spinner')).toBeInTheDocument();
|
|
1415
317
|
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
318
|
+
## Essential Commands
|
|
319
|
+
- `npx claude-flow-novice status` - System health
|
|
320
|
+
- `npx claude-flow-novice --help` - Available commands
|
|
321
|
+
- `/fullstack "goal"` - Launch full-stack development team with consensus validation
|
|
322
|
+
- `/swarm`, `/sparc`, `/hooks` - Other slash commands (auto-discovered)
|
|
1420
323
|
|
|
1421
|
-
|
|
1422
|
-
expect(screen.getByText('1 Posts')).toBeInTheDocument();
|
|
1423
|
-
});
|
|
324
|
+
## 🔄 MANDATORY DEVELOPMENT FLOW LOOP
|
|
1424
325
|
|
|
1425
|
-
|
|
1426
|
-
const user = userEvent.setup();
|
|
1427
|
-
const onUpdate = jest.fn();
|
|
326
|
+
**YOU MUST FOLLOW THIS LOOP FOR ALL NON-TRIVIAL WORK:**
|
|
1428
327
|
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
const editButton = screen.getByRole('button', { name: /edit/i });
|
|
1439
|
-
await user.click(editButton);
|
|
1440
|
-
|
|
1441
|
-
const nameInput = screen.getByDisplayValue('John Doe');
|
|
1442
|
-
await user.clear(nameInput);
|
|
1443
|
-
await user.type(nameInput, 'Jane Doe');
|
|
1444
|
-
|
|
1445
|
-
const saveButton = screen.getByRole('button', { name: /save/i });
|
|
1446
|
-
await user.click(saveButton);
|
|
1447
|
-
|
|
1448
|
-
await waitFor(() => {
|
|
1449
|
-
expect(onUpdate).toHaveBeenCalledWith({ ...mockUser, name: 'Jane Doe' });
|
|
1450
|
-
});
|
|
1451
|
-
});
|
|
1452
|
-
|
|
1453
|
-
test('displays error message on API failure', async () => {
|
|
1454
|
-
api.getUserById.mockRejectedValue(new Error('Network error'));
|
|
1455
|
-
|
|
1456
|
-
render(<UserProfile userId="123" />);
|
|
1457
|
-
|
|
1458
|
-
await waitFor(() => {
|
|
1459
|
-
expect(screen.getByText(/network error/i)).toBeInTheDocument();
|
|
1460
|
-
});
|
|
1461
|
-
});
|
|
1462
|
-
});
|
|
1463
|
-
```
|
|
328
|
+
### Step 1: Initialize Swarm (ALWAYS for multi-agent tasks)
|
|
329
|
+
```javascript
|
|
330
|
+
[Single Message]:
|
|
331
|
+
// ALWAYS initialize swarm when spawning multiple agents
|
|
332
|
+
mcp__claude-flow-novice__swarm_init({
|
|
333
|
+
topology: "mesh", // mesh for 2-7, hierarchical for 8+
|
|
334
|
+
maxAgents: 3, // match your actual agent count
|
|
335
|
+
strategy: "balanced" // ensures coordination and consistency
|
|
336
|
+
})
|
|
1464
337
|
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
// Lazy loading for code splitting
|
|
1470
|
-
const LazyUserProfile = lazy(() => import('./UserProfile'));
|
|
1471
|
-
const LazyUserSettings = lazy(() => import('./UserSettings'));
|
|
1472
|
-
|
|
1473
|
-
// Memoized component to prevent unnecessary re-renders
|
|
1474
|
-
const UserCard = memo(({ user, onUpdate }) => {
|
|
1475
|
-
return (
|
|
1476
|
-
<div className="user-card">
|
|
1477
|
-
<h3>{user.name}</h3>
|
|
1478
|
-
<p>{user.email}</p>
|
|
1479
|
-
<button onClick={() => onUpdate(user.id)}>
|
|
1480
|
-
Update
|
|
1481
|
-
</button>
|
|
1482
|
-
</div>
|
|
1483
|
-
);
|
|
1484
|
-
});
|
|
1485
|
-
|
|
1486
|
-
// Main app with lazy loading
|
|
1487
|
-
const App = () => {
|
|
1488
|
-
return (
|
|
1489
|
-
<div className="app">
|
|
1490
|
-
<Suspense fallback={<div>Loading...</div>}>
|
|
1491
|
-
<Routes>
|
|
1492
|
-
<Route path="/profile" element={<LazyUserProfile />} />
|
|
1493
|
-
<Route path="/settings" element={<LazyUserSettings />} />
|
|
1494
|
-
</Routes>
|
|
1495
|
-
</Suspense>
|
|
1496
|
-
</div>
|
|
1497
|
-
);
|
|
1498
|
-
};
|
|
338
|
+
// Then spawn all agents - they will coordinate via swarm
|
|
339
|
+
Task("Agent 1", "Specific instructions", "type")
|
|
340
|
+
Task("Agent 2", "Specific instructions", "type")
|
|
341
|
+
Task("Agent 3", "Specific instructions", "type")
|
|
1499
342
|
```
|
|
1500
343
|
|
|
1501
|
-
**
|
|
1502
|
-
```jsx
|
|
1503
|
-
import { create } from 'zustand';
|
|
1504
|
-
import { devtools, persist } from 'zustand/middleware';
|
|
1505
|
-
|
|
1506
|
-
const useUserStore = create(
|
|
1507
|
-
devtools(
|
|
1508
|
-
persist(
|
|
1509
|
-
(set, get) => ({
|
|
1510
|
-
users: [],
|
|
1511
|
-
currentUser: null,
|
|
1512
|
-
loading: false,
|
|
1513
|
-
|
|
1514
|
-
fetchUsers: async () => {
|
|
1515
|
-
set({ loading: true });
|
|
1516
|
-
try {
|
|
1517
|
-
const users = await api.getUsers();
|
|
1518
|
-
set({ users, loading: false });
|
|
1519
|
-
} catch (error) {
|
|
1520
|
-
set({ loading: false });
|
|
1521
|
-
throw error;
|
|
1522
|
-
}
|
|
1523
|
-
},
|
|
1524
|
-
|
|
1525
|
-
setCurrentUser: (user) => set({ currentUser: user }),
|
|
1526
|
-
|
|
1527
|
-
updateUser: async (userId, updates) => {
|
|
1528
|
-
const updatedUser = await api.updateUser(userId, updates);
|
|
1529
|
-
set((state) => ({
|
|
1530
|
-
users: state.users.map((user) =>
|
|
1531
|
-
user.id === userId ? updatedUser : user
|
|
1532
|
-
),
|
|
1533
|
-
currentUser: state.currentUser?.id === userId ? updatedUser : state.currentUser
|
|
1534
|
-
}));
|
|
1535
|
-
return updatedUser;
|
|
1536
|
-
}
|
|
1537
|
-
}),
|
|
1538
|
-
{ name: 'user-store' }
|
|
1539
|
-
)
|
|
1540
|
-
)
|
|
1541
|
-
);
|
|
1542
|
-
|
|
1543
|
-
// Usage in component
|
|
1544
|
-
const UserList = () => {
|
|
1545
|
-
const { users, loading, fetchUsers } = useUserStore();
|
|
1546
|
-
|
|
1547
|
-
useEffect(() => {
|
|
1548
|
-
fetchUsers();
|
|
1549
|
-
}, [fetchUsers]);
|
|
1550
|
-
|
|
1551
|
-
if (loading) return <LoadingSpinner />;
|
|
1552
|
-
|
|
1553
|
-
return (
|
|
1554
|
-
<div>
|
|
1555
|
-
{users.map((user) => (
|
|
1556
|
-
<UserCard key={user.id} user={user} />
|
|
1557
|
-
))}
|
|
1558
|
-
</div>
|
|
1559
|
-
);
|
|
1560
|
-
};
|
|
1561
|
-
```
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
hooks/ # Custom hooks
|
|
1565
|
-
useApi.js
|
|
1566
|
-
useLocalStorage.js
|
|
1567
|
-
useAuth.js
|
|
1568
|
-
context/ # React context providers
|
|
1569
|
-
AuthContext.jsx
|
|
1570
|
-
ThemeContext.jsx
|
|
1571
|
-
services/ # API services
|
|
1572
|
-
api.js
|
|
1573
|
-
auth.js
|
|
1574
|
-
utils/ # Helper functions
|
|
1575
|
-
validators.js
|
|
1576
|
-
formatters.js
|
|
1577
|
-
styles/ # Global styles
|
|
1578
|
-
globals.css
|
|
1579
|
-
variables.css
|
|
1580
|
-
```
|
|
344
|
+
**CRITICAL**: Without swarm_init, agents work independently and produce inconsistent results!
|
|
1581
345
|
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
// Functional component with hooks
|
|
1588
|
-
const UserProfile = ({ userId, onUpdate }) => {
|
|
1589
|
-
const [user, setUser] = useState(null);
|
|
1590
|
-
const [loading, setLoading] = useState(true);
|
|
1591
|
-
const [error, setError] = useState(null);
|
|
1592
|
-
|
|
1593
|
-
// Memoized expensive calculations
|
|
1594
|
-
const userStats = useMemo(() => {
|
|
1595
|
-
if (!user) return null;
|
|
1596
|
-
return {
|
|
1597
|
-
totalPosts: user.posts?.length || 0,
|
|
1598
|
-
joinedDate: new Date(user.createdAt).toLocaleDateString()
|
|
1599
|
-
};
|
|
1600
|
-
}, [user]);
|
|
1601
|
-
|
|
1602
|
-
// Memoized callbacks to prevent unnecessary re-renders
|
|
1603
|
-
const handleUpdateUser = useCallback(async (updates) => {
|
|
1604
|
-
try {
|
|
1605
|
-
const updatedUser = await updateUser(userId, updates);
|
|
1606
|
-
setUser(updatedUser);
|
|
1607
|
-
onUpdate?.(updatedUser);
|
|
1608
|
-
} catch (err) {
|
|
1609
|
-
setError(err.message);
|
|
1610
|
-
}
|
|
1611
|
-
}, [userId, onUpdate]);
|
|
1612
|
-
|
|
1613
|
-
useEffect(() => {
|
|
1614
|
-
let cancelled = false;
|
|
1615
|
-
|
|
1616
|
-
const fetchUser = async () => {
|
|
1617
|
-
try {
|
|
1618
|
-
setLoading(true);
|
|
1619
|
-
const userData = await getUserById(userId);
|
|
1620
|
-
if (!cancelled) {
|
|
1621
|
-
setUser(userData);
|
|
1622
|
-
}
|
|
1623
|
-
} catch (err) {
|
|
1624
|
-
if (!cancelled) {
|
|
1625
|
-
setError(err.message);
|
|
1626
|
-
}
|
|
1627
|
-
} finally {
|
|
1628
|
-
if (!cancelled) {
|
|
1629
|
-
setLoading(false);
|
|
1630
|
-
}
|
|
1631
|
-
}
|
|
1632
|
-
};
|
|
1633
|
-
|
|
1634
|
-
fetchUser();
|
|
1635
|
-
|
|
1636
|
-
return () => {
|
|
1637
|
-
cancelled = true;
|
|
1638
|
-
};
|
|
1639
|
-
}, [userId]);
|
|
1640
|
-
|
|
1641
|
-
if (loading) return <LoadingSpinner />;
|
|
1642
|
-
if (error) return <ErrorMessage message={error} />;
|
|
1643
|
-
if (!user) return <NotFound />;
|
|
1644
|
-
|
|
1645
|
-
return (
|
|
1646
|
-
<div className="user-profile">
|
|
1647
|
-
<ProfileHeader user={user} stats={userStats} />
|
|
1648
|
-
<ProfileContent user={user} onUpdate={handleUpdateUser} />
|
|
1649
|
-
</div>
|
|
1650
|
-
);
|
|
1651
|
-
};
|
|
1652
|
-
|
|
1653
|
-
UserProfile.propTypes = {
|
|
1654
|
-
userId: PropTypes.string.isRequired,
|
|
1655
|
-
onUpdate: PropTypes.func
|
|
1656
|
-
};
|
|
1657
|
-
|
|
1658
|
-
export default React.memo(UserProfile);
|
|
1659
|
-
```
|
|
346
|
+
### Step 2: Execute - Primary Swarm (3-20 agents)
|
|
347
|
+
- **Primary swarm** (3-8 agents minimum) produces deliverables with confidence scores
|
|
348
|
+
- **Self-validation**: Each agent validates own work (confidence threshold: 0.75)
|
|
349
|
+
- **Cross-agent coordination**: Agents share findings via SwarmMemory
|
|
1660
350
|
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
// Generic API hook
|
|
1666
|
-
export const useApi = (url, options = {}) => {
|
|
1667
|
-
const [data, setData] = useState(null);
|
|
1668
|
-
const [loading, setLoading] = useState(true);
|
|
1669
|
-
const [error, setError] = useState(null);
|
|
1670
|
-
|
|
1671
|
-
const fetchData = useCallback(async () => {
|
|
1672
|
-
try {
|
|
1673
|
-
setLoading(true);
|
|
1674
|
-
setError(null);
|
|
1675
|
-
const response = await fetch(url, options);
|
|
1676
|
-
|
|
1677
|
-
if (!response.ok) {
|
|
1678
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
1679
|
-
}
|
|
1680
|
-
|
|
1681
|
-
const result = await response.json();
|
|
1682
|
-
setData(result);
|
|
1683
|
-
} catch (err) {
|
|
1684
|
-
setError(err.message);
|
|
1685
|
-
} finally {
|
|
1686
|
-
setLoading(false);
|
|
1687
|
-
}
|
|
1688
|
-
}, [url, options]);
|
|
1689
|
-
|
|
1690
|
-
useEffect(() => {
|
|
1691
|
-
fetchData();
|
|
1692
|
-
}, [fetchData]);
|
|
1693
|
-
|
|
1694
|
-
const refetch = useCallback(() => {
|
|
1695
|
-
fetchData();
|
|
1696
|
-
}, [fetchData]);
|
|
1697
|
-
|
|
1698
|
-
return { data, loading, error, refetch };
|
|
1699
|
-
};
|
|
1700
|
-
|
|
1701
|
-
// Local storage hook
|
|
1702
|
-
export const useLocalStorage = (key, initialValue) => {
|
|
1703
|
-
const [storedValue, setStoredValue] = useState(() => {
|
|
1704
|
-
try {
|
|
1705
|
-
const item = window.localStorage.getItem(key);
|
|
1706
|
-
return item ? JSON.parse(item) : initialValue;
|
|
1707
|
-
} catch (error) {
|
|
1708
|
-
console.error(`Error reading localStorage key "${key}":`, error);
|
|
1709
|
-
return initialValue;
|
|
1710
|
-
}
|
|
1711
|
-
});
|
|
1712
|
-
|
|
1713
|
-
const setValue = useCallback((value) => {
|
|
1714
|
-
try {
|
|
1715
|
-
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
|
1716
|
-
setStoredValue(valueToStore);
|
|
1717
|
-
window.localStorage.setItem(key, JSON.stringify(valueToStore));
|
|
1718
|
-
} catch (error) {
|
|
1719
|
-
console.error(`Error setting localStorage key "${key}":`, error);
|
|
1720
|
-
}
|
|
1721
|
-
}, [key, storedValue]);
|
|
1722
|
-
|
|
1723
|
-
return [storedValue, setValue];
|
|
1724
|
-
};
|
|
1725
|
-
```
|
|
351
|
+
### Step 3: Self-Assessment Gate
|
|
352
|
+
- **If confidence scores ≥75%** → Proceed to Step 4 (Consensus Verification)
|
|
353
|
+
- **If confidence scores <75%** → Relaunch agents for Step 2 with feedback
|
|
354
|
+
- **Maximum iterations**: 3 attempts before escalation
|
|
1726
355
|
|
|
1727
|
-
|
|
1728
|
-
```
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
loading: false,
|
|
1736
|
-
error: null
|
|
1737
|
-
};
|
|
1738
|
-
|
|
1739
|
-
const authReducer = (state, action) => {
|
|
1740
|
-
switch (action.type) {
|
|
1741
|
-
case 'LOGIN_START':
|
|
1742
|
-
return { ...state, loading: true, error: null };
|
|
1743
|
-
case 'LOGIN_SUCCESS':
|
|
1744
|
-
return {
|
|
1745
|
-
...state,
|
|
1746
|
-
user: action.payload,
|
|
1747
|
-
isAuthenticated: true,
|
|
1748
|
-
loading: false,
|
|
1749
|
-
error: null
|
|
1750
|
-
};
|
|
1751
|
-
case 'LOGIN_FAILURE':
|
|
1752
|
-
return {
|
|
1753
|
-
...state,
|
|
1754
|
-
user: null,
|
|
1755
|
-
isAuthenticated: false,
|
|
1756
|
-
loading: false,
|
|
1757
|
-
error: action.payload
|
|
1758
|
-
};
|
|
1759
|
-
case 'LOGOUT':
|
|
1760
|
-
return initialState;
|
|
1761
|
-
default:
|
|
1762
|
-
return state;
|
|
1763
|
-
}
|
|
1764
|
-
};
|
|
1765
|
-
|
|
1766
|
-
// Context creation
|
|
1767
|
-
const AuthContext = createContext();
|
|
1768
|
-
|
|
1769
|
-
// Provider component
|
|
1770
|
-
export const AuthProvider = ({ children }) => {
|
|
1771
|
-
const [state, dispatch] = useReducer(authReducer, initialState);
|
|
1772
|
-
|
|
1773
|
-
const login = useCallback(async (credentials) => {
|
|
1774
|
-
dispatch({ type: 'LOGIN_START' });
|
|
1775
|
-
try {
|
|
1776
|
-
const user = await authService.login(credentials);
|
|
1777
|
-
dispatch({ type: 'LOGIN_SUCCESS', payload: user });
|
|
1778
|
-
return user;
|
|
1779
|
-
} catch (error) {
|
|
1780
|
-
dispatch({ type: 'LOGIN_FAILURE', payload: error.message });
|
|
1781
|
-
throw error;
|
|
1782
|
-
}
|
|
1783
|
-
}, []);
|
|
1784
|
-
|
|
1785
|
-
const logout = useCallback(() => {
|
|
1786
|
-
authService.logout();
|
|
1787
|
-
dispatch({ type: 'LOGOUT' });
|
|
1788
|
-
}, []);
|
|
1789
|
-
|
|
1790
|
-
const value = {
|
|
1791
|
-
...state,
|
|
1792
|
-
login,
|
|
1793
|
-
logout
|
|
1794
|
-
};
|
|
1795
|
-
|
|
1796
|
-
return (
|
|
1797
|
-
<AuthContext.Provider value={value}>
|
|
1798
|
-
{children}
|
|
1799
|
-
</AuthContext.Provider>
|
|
1800
|
-
);
|
|
1801
|
-
};
|
|
1802
|
-
|
|
1803
|
-
// Custom hook for using auth context
|
|
1804
|
-
export const useAuth = () => {
|
|
1805
|
-
const context = useContext(AuthContext);
|
|
1806
|
-
if (!context) {
|
|
1807
|
-
throw new Error('useAuth must be used within an AuthProvider');
|
|
1808
|
-
}
|
|
1809
|
-
return context;
|
|
1810
|
-
};
|
|
356
|
+
### Step 4: Verify - Consensus Swarm (2-4 validators REQUIRED)
|
|
357
|
+
```javascript
|
|
358
|
+
// MANDATORY: Spawn consensus validation swarm
|
|
359
|
+
[Single Message]:
|
|
360
|
+
Task("Validator 1", "Comprehensive quality review", "reviewer")
|
|
361
|
+
Task("Validator 2", "Security and performance audit", "security-specialist")
|
|
362
|
+
Task("Validator 3", "Architecture validation", "system-architect")
|
|
363
|
+
Task("Validator 4", "Integration testing", "tester")
|
|
1811
364
|
```
|
|
365
|
+
- **Byzantine consensus voting** across all validators
|
|
366
|
+
- **Multi-dimensional checks**: quality, security, performance, tests, docs
|
|
1812
367
|
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
1817
|
-
import userEvent from '@testing-library/user-event';
|
|
1818
|
-
import { jest } from '@jest/globals';
|
|
1819
|
-
import UserProfile from '../UserProfile';
|
|
1820
|
-
import * as api from '../../services/api';
|
|
1821
|
-
|
|
1822
|
-
// Mock the API module
|
|
1823
|
-
jest.mock('../../services/api');
|
|
1824
|
-
|
|
1825
|
-
describe('UserProfile', () => {
|
|
1826
|
-
const mockUser = {
|
|
1827
|
-
id: '123',
|
|
1828
|
-
name: 'John Doe',
|
|
1829
|
-
email: 'john@example.com',
|
|
1830
|
-
posts: [{ id: 1, title: 'Test Post' }]
|
|
1831
|
-
};
|
|
1832
|
-
|
|
1833
|
-
beforeEach(() => {
|
|
1834
|
-
jest.clearAllMocks();
|
|
1835
|
-
});
|
|
1836
|
-
|
|
1837
|
-
test('renders user profile after loading', async () => {
|
|
1838
|
-
api.getUserById.mockResolvedValue(mockUser);
|
|
1839
|
-
|
|
1840
|
-
render(<UserProfile userId="123" />);
|
|
1841
|
-
|
|
1842
|
-
// Check loading state
|
|
1843
|
-
expect(screen.getByTestId('loading-spinner')).toBeInTheDocument();
|
|
1844
|
-
|
|
1845
|
-
// Wait for user data to load
|
|
1846
|
-
await waitFor(() => {
|
|
1847
|
-
expect(screen.getByText('John Doe')).toBeInTheDocument();
|
|
1848
|
-
});
|
|
368
|
+
### Step 5: Decision Gate
|
|
369
|
+
- **PASS**: ≥90% validator agreement + all critical criteria met
|
|
370
|
+
- **FAIL**: <90% agreement OR any critical criterion failed
|
|
1849
371
|
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
372
|
+
### Step 6: Action Based on Decision
|
|
373
|
+
- **PASS** →
|
|
374
|
+
1. Store results in SwarmMemory
|
|
375
|
+
2. Update documentation
|
|
376
|
+
3. Update todos and move to next task
|
|
1853
377
|
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
378
|
+
- **FAIL** →
|
|
379
|
+
1. Round counter++
|
|
380
|
+
2. If Round < 10: Inject validator feedback → Return to Step 2
|
|
381
|
+
3. If Round ≥ 10: Escalate to human with comprehensive report
|
|
1857
382
|
|
|
1858
|
-
|
|
1859
|
-
api.updateUser.mockResolvedValue({ ...mockUser, name: 'Jane Doe' });
|
|
383
|
+
### 🚨 ENFORCEMENT CHECKPOINTS
|
|
1860
384
|
|
|
1861
|
-
|
|
385
|
+
**MANDATORY before proceeding:**
|
|
386
|
+
1. ✅ Agents spawned
|
|
387
|
+
2. ✅ Each file edit followed by enhanced post-edit hook
|
|
388
|
+
3. ✅ Self-validation confidence scores recorded
|
|
389
|
+
4. ✅ Consensus swarm spawned for verification
|
|
390
|
+
5. ✅ Byzantine voting completed
|
|
391
|
+
6. ✅ Results stored in SwarmMemory
|
|
1862
392
|
|
|
1863
|
-
|
|
1864
|
-
expect(screen.getByText('John Doe')).toBeInTheDocument();
|
|
1865
|
-
});
|
|
393
|
+
---
|
|
1866
394
|
|
|
1867
|
-
|
|
1868
|
-
await user.click(editButton);
|
|
395
|
+
## 🎯 MANDATORY: NEXT STEPS GUIDANCE
|
|
1869
396
|
|
|
1870
|
-
|
|
1871
|
-
await user.clear(nameInput);
|
|
1872
|
-
await user.type(nameInput, 'Jane Doe');
|
|
1873
|
-
|
|
1874
|
-
const saveButton = screen.getByRole('button', { name: /save/i });
|
|
1875
|
-
await user.click(saveButton);
|
|
1876
|
-
|
|
1877
|
-
await waitFor(() => {
|
|
1878
|
-
expect(onUpdate).toHaveBeenCalledWith({ ...mockUser, name: 'Jane Doe' });
|
|
1879
|
-
});
|
|
1880
|
-
});
|
|
1881
|
-
|
|
1882
|
-
test('displays error message on API failure', async () => {
|
|
1883
|
-
api.getUserById.mockRejectedValue(new Error('Network error'));
|
|
1884
|
-
|
|
1885
|
-
render(<UserProfile userId="123" />);
|
|
1886
|
-
|
|
1887
|
-
await waitFor(() => {
|
|
1888
|
-
expect(screen.getByText(/network error/i)).toBeInTheDocument();
|
|
1889
|
-
});
|
|
1890
|
-
});
|
|
1891
|
-
});
|
|
1892
|
-
```
|
|
1893
|
-
|
|
1894
|
-
**Performance Optimization:**
|
|
1895
|
-
```jsx
|
|
1896
|
-
import React, { memo, lazy, Suspense } from 'react';
|
|
1897
|
-
|
|
1898
|
-
// Lazy loading for code splitting
|
|
1899
|
-
const LazyUserProfile = lazy(() => import('./UserProfile'));
|
|
1900
|
-
const LazyUserSettings = lazy(() => import('./UserSettings'));
|
|
1901
|
-
|
|
1902
|
-
// Memoized component to prevent unnecessary re-renders
|
|
1903
|
-
const UserCard = memo(({ user, onUpdate }) => {
|
|
1904
|
-
return (
|
|
1905
|
-
<div className="user-card">
|
|
1906
|
-
<h3>{user.name}</h3>
|
|
1907
|
-
<p>{user.email}</p>
|
|
1908
|
-
<button onClick={() => onUpdate(user.id)}>
|
|
1909
|
-
Update
|
|
1910
|
-
</button>
|
|
1911
|
-
</div>
|
|
1912
|
-
);
|
|
1913
|
-
});
|
|
1914
|
-
|
|
1915
|
-
// Main app with lazy loading
|
|
1916
|
-
const App = () => {
|
|
1917
|
-
return (
|
|
1918
|
-
<div className="app">
|
|
1919
|
-
<Suspense fallback={<div>Loading...</div>}>
|
|
1920
|
-
<Routes>
|
|
1921
|
-
<Route path="/profile" element={<LazyUserProfile />} />
|
|
1922
|
-
<Route path="/settings" element={<LazyUserSettings />} />
|
|
1923
|
-
</Routes>
|
|
1924
|
-
</Suspense>
|
|
1925
|
-
</div>
|
|
1926
|
-
);
|
|
1927
|
-
};
|
|
1928
|
-
```
|
|
397
|
+
**After completing ANY task, you MUST provide:**
|
|
1929
398
|
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
const useUserStore = create(
|
|
1936
|
-
devtools(
|
|
1937
|
-
persist(
|
|
1938
|
-
(set, get) => ({
|
|
1939
|
-
users: [],
|
|
1940
|
-
currentUser: null,
|
|
1941
|
-
loading: false,
|
|
1942
|
-
|
|
1943
|
-
fetchUsers: async () => {
|
|
1944
|
-
set({ loading: true });
|
|
1945
|
-
try {
|
|
1946
|
-
const users = await api.getUsers();
|
|
1947
|
-
set({ users, loading: false });
|
|
1948
|
-
} catch (error) {
|
|
1949
|
-
set({ loading: false });
|
|
1950
|
-
throw error;
|
|
1951
|
-
}
|
|
1952
|
-
},
|
|
1953
|
-
|
|
1954
|
-
setCurrentUser: (user) => set({ currentUser: user }),
|
|
1955
|
-
|
|
1956
|
-
updateUser: async (userId, updates) => {
|
|
1957
|
-
const updatedUser = await api.updateUser(userId, updates);
|
|
1958
|
-
set((state) => ({
|
|
1959
|
-
users: state.users.map((user) =>
|
|
1960
|
-
user.id === userId ? updatedUser : user
|
|
1961
|
-
),
|
|
1962
|
-
currentUser: state.currentUser?.id === userId ? updatedUser : state.currentUser
|
|
1963
|
-
}));
|
|
1964
|
-
return updatedUser;
|
|
1965
|
-
}
|
|
1966
|
-
}),
|
|
1967
|
-
{ name: 'user-store' }
|
|
1968
|
-
)
|
|
1969
|
-
)
|
|
1970
|
-
);
|
|
1971
|
-
|
|
1972
|
-
// Usage in component
|
|
1973
|
-
const UserList = () => {
|
|
1974
|
-
const { users, loading, fetchUsers } = useUserStore();
|
|
1975
|
-
|
|
1976
|
-
useEffect(() => {
|
|
1977
|
-
fetchUsers();
|
|
1978
|
-
}, [fetchUsers]);
|
|
1979
|
-
|
|
1980
|
-
if (loading) return <LoadingSpinner />;
|
|
1981
|
-
|
|
1982
|
-
return (
|
|
1983
|
-
<div>
|
|
1984
|
-
{users.map((user) => (
|
|
1985
|
-
<UserCard key={user.id} user={user} />
|
|
1986
|
-
))}
|
|
1987
|
-
</div>
|
|
1988
|
-
);
|
|
1989
|
-
};
|
|
1990
|
-
```
|
|
399
|
+
1. **✅ What was completed**: Brief summary of delivered work
|
|
400
|
+
2. **📊 Validation results**: Confidence scores, test coverage, consensus approval
|
|
401
|
+
3. **🔍 Identified issues**: Any technical debt, warnings, or concerns discovered
|
|
402
|
+
4. **💡 Recommended next steps**: Prioritized suggestions for logical continuation
|