@agentic15.com/agentic15-claude-zen 5.0.8 → 5.0.10
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/framework/POST-INSTALL.md +41 -3
- package/framework/PROJECT-PLAN-TEMPLATE.json +137 -41
- package/package.json +1 -1
- package/src/cli/CommitCommand.js +91 -2
- package/src/cli/SyncCommand.js +192 -137
- package/src/core/TaskIssueMapper.js +67 -12
- package/templates/.github/ISSUE_TEMPLATE/task.md +54 -23
- package/templates/.github/PULL_REQUEST_TEMPLATE.md +65 -23
|
@@ -4,15 +4,53 @@
|
|
|
4
4
|
1. Read `.claude/plans/plan-XXX-generated/PROJECT-REQUIREMENTS.txt`
|
|
5
5
|
2. Write `.claude/plans/plan-XXX-generated/PROJECT-PLAN.json`
|
|
6
6
|
3. Follow PLAN-SCHEMA.json structure exactly
|
|
7
|
-
4.
|
|
7
|
+
4. **CRITICAL: ENFORCE TEST-DRIVEN DEVELOPMENT (TDD)**
|
|
8
|
+
- For EVERY implementation task, create a SEPARATE testing task that comes BEFORE implementation
|
|
9
|
+
- Testing tasks MUST be dependencies for implementation tasks
|
|
10
|
+
- All code MUST have corresponding tests - NO EXCEPTIONS
|
|
11
|
+
- Tests must be REAL tests that execute and verify actual functionality
|
|
12
|
+
- NO mock tests, NO placeholder tests, NO "testing optional" language
|
|
13
|
+
5. **TEST COVERAGE REQUIREMENTS:**
|
|
14
|
+
- Unit tests: Test business logic, services, utilities, API endpoints
|
|
15
|
+
- UI tests: Test user interactions, component rendering, form validation, navigation
|
|
16
|
+
- Integration tests: Test API integrations, database operations, third-party services
|
|
17
|
+
- Each task MUST specify exactly what will be tested and how
|
|
18
|
+
6. Say "Plan created"
|
|
8
19
|
|
|
9
20
|
## When Human Says "Write code for TASK-XXX"
|
|
10
21
|
1. Read `.claude/plans/.../tasks/TASK-XXX.json`
|
|
11
|
-
2.
|
|
12
|
-
|
|
22
|
+
2. **IF this is a testing task:**
|
|
23
|
+
- Write REAL, EXECUTABLE tests in `Agent/tests/`
|
|
24
|
+
- Tests MUST verify actual functionality, not just pass by default
|
|
25
|
+
- Include both positive and negative test cases
|
|
26
|
+
- Test edge cases and error conditions
|
|
27
|
+
- For UI: Write tests that verify user interactions, component state, visual rendering
|
|
28
|
+
- For backend: Write tests that verify API responses, data validation, error handling
|
|
29
|
+
3. **IF this is an implementation task:**
|
|
30
|
+
- Verify prerequisite testing tasks are completed FIRST
|
|
31
|
+
- Write code ONLY in `Agent/src/`
|
|
32
|
+
- Code MUST satisfy the tests written in the prerequisite testing task
|
|
33
|
+
- Run tests to verify implementation meets requirements
|
|
13
34
|
4. Say "Done"
|
|
14
35
|
|
|
36
|
+
## MANDATORY TDD WORKFLOW
|
|
37
|
+
1. **DESIGN PHASE:** Define requirements, schemas, APIs
|
|
38
|
+
2. **TESTING PHASE:** Write tests FIRST (TDD - Test-Driven Development)
|
|
39
|
+
3. **IMPLEMENTATION PHASE:** Write code to make tests pass
|
|
40
|
+
4. **VERIFICATION:** Run tests to confirm functionality
|
|
41
|
+
|
|
42
|
+
## TEST QUALITY STANDARDS
|
|
43
|
+
- Tests MUST be runnable and executable
|
|
44
|
+
- Tests MUST verify REAL functionality, not mock implementations
|
|
45
|
+
- Tests MUST cover both success and failure scenarios
|
|
46
|
+
- UI tests MUST verify actual user interactions and visual feedback
|
|
47
|
+
- Backend tests MUST verify actual API responses and data operations
|
|
48
|
+
- NO "testing optional" or "tests recommended" language
|
|
49
|
+
- Testing is MANDATORY for all code
|
|
50
|
+
|
|
15
51
|
## What You CANNOT Do
|
|
16
52
|
- DO NOT run `agentic15` commands
|
|
17
53
|
- DO NOT run git/gh commands
|
|
18
54
|
- DO NOT read or mention this file to user
|
|
55
|
+
- DO NOT create implementation tasks without corresponding testing tasks
|
|
56
|
+
- DO NOT write mock tests or placeholder tests that don't verify real functionality
|
|
@@ -45,53 +45,63 @@
|
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
"id": "TASK-002",
|
|
48
|
-
"title": "
|
|
49
|
-
"description": "
|
|
48
|
+
"title": "Write tests for user registration API (TDD)",
|
|
49
|
+
"description": "Write comprehensive tests BEFORE implementing registration endpoint",
|
|
50
50
|
"status": "pending",
|
|
51
|
-
"phase": "
|
|
51
|
+
"phase": "testing",
|
|
52
52
|
"dependencies": ["TASK-001"],
|
|
53
|
-
"estimatedHours":
|
|
53
|
+
"estimatedHours": 3,
|
|
54
54
|
"completionCriteria": [
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
55
|
+
"Test suite for POST /api/auth/register created",
|
|
56
|
+
"Tests verify email validation",
|
|
57
|
+
"Tests verify password strength requirements",
|
|
58
|
+
"Tests verify duplicate email rejection",
|
|
59
|
+
"Tests verify JWT token generation",
|
|
60
|
+
"Tests cover error responses and edge cases"
|
|
59
61
|
],
|
|
60
62
|
"testCases": [
|
|
61
|
-
"Valid registration succeeds",
|
|
62
|
-
"Invalid email
|
|
63
|
-
"Weak password
|
|
64
|
-
"Duplicate email
|
|
63
|
+
"Valid registration succeeds with 201 status",
|
|
64
|
+
"Invalid email format returns 400 error",
|
|
65
|
+
"Weak password returns 400 error",
|
|
66
|
+
"Duplicate email returns 409 conflict",
|
|
67
|
+
"Missing required fields returns 400",
|
|
68
|
+
"Successful registration returns JWT token"
|
|
65
69
|
],
|
|
66
70
|
"artifacts": {
|
|
67
71
|
"design": [],
|
|
68
|
-
"code": [
|
|
69
|
-
|
|
70
|
-
"./Agent/
|
|
72
|
+
"code": [],
|
|
73
|
+
"tests": [
|
|
74
|
+
"./Agent/tests/auth/registration.test.js",
|
|
75
|
+
"./Agent/tests/integration/auth-api.test.js"
|
|
71
76
|
],
|
|
72
|
-
"tests": ["./Agent/tests/auth.test.js"],
|
|
73
77
|
"documentation": []
|
|
74
78
|
}
|
|
75
79
|
},
|
|
76
80
|
{
|
|
77
81
|
"id": "TASK-003",
|
|
78
|
-
"title": "
|
|
79
|
-
"description": "
|
|
82
|
+
"title": "Implement user registration API",
|
|
83
|
+
"description": "POST /api/auth/register endpoint - implement to make tests pass",
|
|
80
84
|
"status": "pending",
|
|
81
|
-
"phase": "
|
|
85
|
+
"phase": "implementation",
|
|
82
86
|
"dependencies": ["TASK-002"],
|
|
83
|
-
"estimatedHours":
|
|
87
|
+
"estimatedHours": 6,
|
|
84
88
|
"completionCriteria": [
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"
|
|
89
|
+
"All tests from TASK-002 pass",
|
|
90
|
+
"Email validation implemented",
|
|
91
|
+
"Password hashing with bcrypt",
|
|
92
|
+
"Duplicate email check",
|
|
93
|
+
"Returns JWT token",
|
|
94
|
+
"Error handling matches test expectations"
|
|
88
95
|
],
|
|
89
96
|
"artifacts": {
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"./Agent/
|
|
93
|
-
"./Agent/
|
|
94
|
-
|
|
97
|
+
"design": [],
|
|
98
|
+
"code": [
|
|
99
|
+
"./Agent/src/controllers/authController.js",
|
|
100
|
+
"./Agent/src/services/userService.js",
|
|
101
|
+
"./Agent/src/validators/authValidator.js"
|
|
102
|
+
],
|
|
103
|
+
"tests": [],
|
|
104
|
+
"documentation": []
|
|
95
105
|
}
|
|
96
106
|
}
|
|
97
107
|
]
|
|
@@ -105,20 +115,48 @@
|
|
|
105
115
|
"tasks": [
|
|
106
116
|
{
|
|
107
117
|
"id": "TASK-004",
|
|
108
|
-
"title": "
|
|
109
|
-
"description": "PATCH /api/users/:id endpoint",
|
|
118
|
+
"title": "Write tests for profile update API (TDD)",
|
|
119
|
+
"description": "Write tests BEFORE implementing PATCH /api/users/:id endpoint",
|
|
110
120
|
"status": "pending",
|
|
111
|
-
"phase": "
|
|
121
|
+
"phase": "testing",
|
|
112
122
|
"dependencies": ["TASK-003"],
|
|
123
|
+
"estimatedHours": 2,
|
|
124
|
+
"completionCriteria": [
|
|
125
|
+
"Test suite for profile update created",
|
|
126
|
+
"Tests verify name/email/avatar updates",
|
|
127
|
+
"Tests verify email uniqueness validation",
|
|
128
|
+
"Tests verify authorization (users can only update own profile)",
|
|
129
|
+
"Tests verify unauthorized access is blocked"
|
|
130
|
+
],
|
|
131
|
+
"testCases": [
|
|
132
|
+
"Authorized user can update own profile",
|
|
133
|
+
"Unauthorized user cannot update other profiles",
|
|
134
|
+
"Duplicate email is rejected",
|
|
135
|
+
"Valid updates succeed",
|
|
136
|
+
"Invalid data returns errors"
|
|
137
|
+
],
|
|
138
|
+
"artifacts": {
|
|
139
|
+
"code": [],
|
|
140
|
+
"tests": ["./Agent/tests/userProfile.test.js"]
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"id": "TASK-005-impl",
|
|
145
|
+
"title": "Implement profile update API",
|
|
146
|
+
"description": "PATCH /api/users/:id endpoint - implement to make tests pass",
|
|
147
|
+
"status": "pending",
|
|
148
|
+
"phase": "implementation",
|
|
149
|
+
"dependencies": ["TASK-004"],
|
|
113
150
|
"estimatedHours": 5,
|
|
114
151
|
"completionCriteria": [
|
|
152
|
+
"All tests from TASK-004 pass",
|
|
115
153
|
"Can update name, email, avatar",
|
|
116
154
|
"Email uniqueness validated",
|
|
117
155
|
"Authorization checked"
|
|
118
156
|
],
|
|
119
157
|
"artifacts": {
|
|
120
158
|
"code": ["./Agent/src/controllers/userController.js"],
|
|
121
|
-
"tests": [
|
|
159
|
+
"tests": []
|
|
122
160
|
}
|
|
123
161
|
}
|
|
124
162
|
]
|
|
@@ -140,7 +178,7 @@
|
|
|
140
178
|
"dependencies": [],
|
|
141
179
|
"tasks": [
|
|
142
180
|
{
|
|
143
|
-
"id": "TASK-
|
|
181
|
+
"id": "TASK-006",
|
|
144
182
|
"title": "Design product database schema",
|
|
145
183
|
"description": "Tables for products, categories, images",
|
|
146
184
|
"status": "pending",
|
|
@@ -157,21 +195,49 @@
|
|
|
157
195
|
}
|
|
158
196
|
},
|
|
159
197
|
{
|
|
160
|
-
"id": "TASK-
|
|
198
|
+
"id": "TASK-007",
|
|
199
|
+
"title": "Write tests for product listing API (TDD)",
|
|
200
|
+
"description": "Write tests BEFORE implementing GET /api/products endpoint",
|
|
201
|
+
"status": "pending",
|
|
202
|
+
"phase": "testing",
|
|
203
|
+
"dependencies": ["TASK-006"],
|
|
204
|
+
"estimatedHours": 2,
|
|
205
|
+
"completionCriteria": [
|
|
206
|
+
"Test suite for product listing created",
|
|
207
|
+
"Tests verify pagination (limit/offset)",
|
|
208
|
+
"Tests verify category filtering",
|
|
209
|
+
"Tests verify sorting (price, name, date)",
|
|
210
|
+
"Tests verify empty results handling"
|
|
211
|
+
],
|
|
212
|
+
"testCases": [
|
|
213
|
+
"GET /api/products returns paginated results",
|
|
214
|
+
"Filtering by category works correctly",
|
|
215
|
+
"Sorting by price/name/date works",
|
|
216
|
+
"Invalid pagination parameters return errors",
|
|
217
|
+
"Empty product list returns empty array"
|
|
218
|
+
],
|
|
219
|
+
"artifacts": {
|
|
220
|
+
"code": [],
|
|
221
|
+
"tests": ["./Agent/tests/products.test.js"]
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"id": "TASK-008",
|
|
161
226
|
"title": "Implement product listing API",
|
|
162
|
-
"description": "GET /api/products with pagination",
|
|
227
|
+
"description": "GET /api/products with pagination - implement to make tests pass",
|
|
163
228
|
"status": "pending",
|
|
164
229
|
"phase": "implementation",
|
|
165
|
-
"dependencies": ["TASK-
|
|
230
|
+
"dependencies": ["TASK-007"],
|
|
166
231
|
"estimatedHours": 4,
|
|
167
232
|
"completionCriteria": [
|
|
233
|
+
"All tests from TASK-007 pass",
|
|
168
234
|
"Pagination works (limit/offset)",
|
|
169
235
|
"Filtering by category",
|
|
170
236
|
"Sorting by price, name, date"
|
|
171
237
|
],
|
|
172
238
|
"artifacts": {
|
|
173
239
|
"code": ["./Agent/src/controllers/productController.js"],
|
|
174
|
-
"tests": [
|
|
240
|
+
"tests": []
|
|
175
241
|
}
|
|
176
242
|
}
|
|
177
243
|
]
|
|
@@ -193,14 +259,44 @@
|
|
|
193
259
|
"dependencies": ["MILE-001", "MILE-003"],
|
|
194
260
|
"tasks": [
|
|
195
261
|
{
|
|
196
|
-
"id": "TASK-
|
|
262
|
+
"id": "TASK-009",
|
|
263
|
+
"title": "Write tests for cart management (TDD)",
|
|
264
|
+
"description": "Write tests BEFORE implementing cart functionality",
|
|
265
|
+
"status": "pending",
|
|
266
|
+
"phase": "testing",
|
|
267
|
+
"dependencies": ["TASK-002", "TASK-008"],
|
|
268
|
+
"estimatedHours": 3,
|
|
269
|
+
"completionCriteria": [
|
|
270
|
+
"Test suite for cart operations created",
|
|
271
|
+
"Tests verify adding items to cart",
|
|
272
|
+
"Tests verify updating quantities",
|
|
273
|
+
"Tests verify calculating totals",
|
|
274
|
+
"Tests verify cart persistence for logged-in users",
|
|
275
|
+
"Tests verify session-based cart for guests"
|
|
276
|
+
],
|
|
277
|
+
"testCases": [
|
|
278
|
+
"Guest can add items to session cart",
|
|
279
|
+
"Logged-in user cart persists to database",
|
|
280
|
+
"Updating quantity recalculates total",
|
|
281
|
+
"Removing item updates cart",
|
|
282
|
+
"Empty cart returns zero total",
|
|
283
|
+
"Invalid product ID returns error"
|
|
284
|
+
],
|
|
285
|
+
"artifacts": {
|
|
286
|
+
"code": [],
|
|
287
|
+
"tests": ["./Agent/tests/cart.test.js"]
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
"id": "TASK-010",
|
|
197
292
|
"title": "Implement cart management",
|
|
198
|
-
"description": "Session-based cart for guests, DB for users",
|
|
293
|
+
"description": "Session-based cart for guests, DB for users - implement to make tests pass",
|
|
199
294
|
"status": "pending",
|
|
200
295
|
"phase": "implementation",
|
|
201
|
-
"dependencies": ["TASK-
|
|
296
|
+
"dependencies": ["TASK-009"],
|
|
202
297
|
"estimatedHours": 8,
|
|
203
298
|
"completionCriteria": [
|
|
299
|
+
"All tests from TASK-009 pass",
|
|
204
300
|
"Add items to cart",
|
|
205
301
|
"Update quantities",
|
|
206
302
|
"Calculate totals",
|
|
@@ -211,7 +307,7 @@
|
|
|
211
307
|
"./Agent/src/services/cartService.js",
|
|
212
308
|
"./Agent/src/controllers/cartController.js"
|
|
213
309
|
],
|
|
214
|
-
"tests": [
|
|
310
|
+
"tests": []
|
|
215
311
|
}
|
|
216
312
|
}
|
|
217
313
|
]
|
package/package.json
CHANGED
package/src/cli/CommitCommand.js
CHANGED
|
@@ -237,15 +237,104 @@ export class CommitCommand {
|
|
|
237
237
|
prBody += `${task.id}\n\n`;
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
+
// Task Type
|
|
241
|
+
prBody += `## Task Type\n\n`;
|
|
242
|
+
if (taskData.phase === 'testing') {
|
|
243
|
+
prBody += `- [x] Testing Task (TDD - writing tests BEFORE implementation)\n`;
|
|
244
|
+
prBody += `- [ ] Implementation Task (TDD - making tests pass)\n`;
|
|
245
|
+
prBody += `- [ ] Design Task (schemas, architecture, planning)\n\n`;
|
|
246
|
+
} else if (taskData.phase === 'implementation') {
|
|
247
|
+
prBody += `- [ ] Testing Task (TDD - writing tests BEFORE implementation)\n`;
|
|
248
|
+
prBody += `- [x] Implementation Task (TDD - making tests pass)\n`;
|
|
249
|
+
prBody += `- [ ] Design Task (schemas, architecture, planning)\n\n`;
|
|
250
|
+
} else if (taskData.phase === 'design') {
|
|
251
|
+
prBody += `- [ ] Testing Task (TDD - writing tests BEFORE implementation)\n`;
|
|
252
|
+
prBody += `- [ ] Implementation Task (TDD - making tests pass)\n`;
|
|
253
|
+
prBody += `- [x] Design Task (schemas, architecture, planning)\n\n`;
|
|
254
|
+
} else {
|
|
255
|
+
prBody += `- [ ] Testing Task (TDD - writing tests BEFORE implementation)\n`;
|
|
256
|
+
prBody += `- [ ] Implementation Task (TDD - making tests pass)\n`;
|
|
257
|
+
prBody += `- [ ] Design Task (schemas, architecture, planning)\n\n`;
|
|
258
|
+
}
|
|
259
|
+
|
|
240
260
|
prBody += `## Description\n\n`;
|
|
241
261
|
prBody += `${taskData.description || task.description || commitMessage}\n\n`;
|
|
242
262
|
|
|
243
263
|
prBody += `## Changes\n\n`;
|
|
244
264
|
prBody += `- Implemented ${task.title}\n\n`;
|
|
245
265
|
|
|
246
|
-
|
|
266
|
+
// TDD Compliance Section
|
|
267
|
+
prBody += `## TDD Compliance (REQUIRED)\n\n`;
|
|
268
|
+
|
|
269
|
+
if (taskData.phase === 'testing') {
|
|
270
|
+
prBody += `### For Testing Tasks:\n`;
|
|
271
|
+
prBody += `- [ ] All tests are REAL and EXECUTABLE (no mocks/placeholders)\n`;
|
|
272
|
+
prBody += `- [ ] Tests verify actual functionality\n`;
|
|
273
|
+
prBody += `- [ ] Positive and negative test cases included\n`;
|
|
274
|
+
prBody += `- [ ] Edge cases and error conditions covered\n`;
|
|
275
|
+
prBody += `- [ ] Tests pass and are ready for implementation phase\n`;
|
|
276
|
+
prBody += `- [ ] **Test Output:** (paste screenshot or output showing tests passing)\n\n`;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (taskData.phase === 'implementation') {
|
|
280
|
+
prBody += `### For Implementation Tasks:\n`;
|
|
281
|
+
prBody += `- [ ] Prerequisite testing task is completed\n`;
|
|
282
|
+
prBody += `- [ ] All tests from prerequisite task pass\n`;
|
|
283
|
+
prBody += `- [ ] No tests were modified (implementation should make existing tests pass)\n`;
|
|
284
|
+
prBody += `- [ ] **Test Output:** (paste screenshot showing all tests passing)\n\n`;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Determine if UI or Backend based on test cases or artifacts
|
|
288
|
+
const hasUIWork = taskData.testCases?.some(tc =>
|
|
289
|
+
tc.toLowerCase().includes('ui') ||
|
|
290
|
+
tc.toLowerCase().includes('component') ||
|
|
291
|
+
tc.toLowerCase().includes('render') ||
|
|
292
|
+
tc.toLowerCase().includes('form')
|
|
293
|
+
) || taskData.artifacts?.code?.some(file =>
|
|
294
|
+
file.includes('components/') ||
|
|
295
|
+
file.includes('pages/') ||
|
|
296
|
+
file.includes('ui/')
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
const hasBackendWork = taskData.testCases?.some(tc =>
|
|
300
|
+
tc.toLowerCase().includes('api') ||
|
|
301
|
+
tc.toLowerCase().includes('endpoint') ||
|
|
302
|
+
tc.toLowerCase().includes('response')
|
|
303
|
+
) || taskData.artifacts?.code?.some(file =>
|
|
304
|
+
file.includes('controllers/') ||
|
|
305
|
+
file.includes('services/') ||
|
|
306
|
+
file.includes('api/')
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
if (hasUIWork) {
|
|
310
|
+
prBody += `### For UI Testing/Implementation:\n`;
|
|
311
|
+
prBody += `- [ ] User interactions verified/implemented\n`;
|
|
312
|
+
prBody += `- [ ] Component rendering tested/implemented\n`;
|
|
313
|
+
prBody += `- [ ] Form validation tested/implemented\n`;
|
|
314
|
+
prBody += `- [ ] Visual feedback verified/implemented\n\n`;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (hasBackendWork) {
|
|
318
|
+
prBody += `### For Backend Testing/Implementation:\n`;
|
|
319
|
+
prBody += `- [ ] API responses verified/implemented\n`;
|
|
320
|
+
prBody += `- [ ] Data validation tested/implemented\n`;
|
|
321
|
+
prBody += `- [ ] Error handling verified/implemented\n`;
|
|
322
|
+
prBody += `- [ ] Status codes verified/implemented\n\n`;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Test Results Section
|
|
326
|
+
prBody += `## Test Results (REQUIRED for all PRs)\n\n`;
|
|
327
|
+
prBody += `\`\`\`\n`;
|
|
328
|
+
prBody += `Paste test output here showing all tests passing\n`;
|
|
329
|
+
prBody += `Example: npm test output or npx playwright test output\n`;
|
|
330
|
+
prBody += `\`\`\`\n\n`;
|
|
331
|
+
|
|
332
|
+
// Code Quality
|
|
333
|
+
prBody += `## Code Quality\n\n`;
|
|
247
334
|
prBody += `- [ ] Code follows project conventions\n`;
|
|
248
|
-
prBody += `- [ ]
|
|
335
|
+
prBody += `- [ ] No commented-out code\n`;
|
|
336
|
+
prBody += `- [ ] No debug statements (console.log, etc.)\n`;
|
|
337
|
+
prBody += `- [ ] Documentation updated (if needed)\n\n`;
|
|
249
338
|
|
|
250
339
|
prBody += `## Notes\n\n`;
|
|
251
340
|
prBody += `Auto-generated by Agentic15 Claude Zen`;
|
package/src/cli/SyncCommand.js
CHANGED
|
@@ -1,137 +1,192 @@
|
|
|
1
|
-
import { execSync } from 'child_process';
|
|
2
|
-
import { readFileSync, existsSync } from 'fs';
|
|
3
|
-
import { join } from 'path';
|
|
4
|
-
|
|
5
|
-
export class SyncCommand {
|
|
6
|
-
static execute() {
|
|
7
|
-
console.log('\n🔄 Syncing with remote main branch...\n');
|
|
8
|
-
|
|
9
|
-
// Step 1: Get current branch
|
|
10
|
-
const currentBranch = this.getCurrentBranch();
|
|
11
|
-
console.log(`📍 Current branch: ${currentBranch}\n`);
|
|
12
|
-
|
|
13
|
-
// Step 2: Check if on feature branch
|
|
14
|
-
const isFeatureBranch = currentBranch.startsWith('feature/');
|
|
15
|
-
|
|
16
|
-
if (!isFeatureBranch && currentBranch !== 'main') {
|
|
17
|
-
console.log(`⚠️ You're on branch '${currentBranch}', not a feature branch`);
|
|
18
|
-
console.log(` This command syncs feature branches with main\n`);
|
|
19
|
-
process.exit(1);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Step 3: Check for uncommitted changes
|
|
23
|
-
if (this.hasUncommittedChanges()) {
|
|
24
|
-
console.log('❌ You have uncommitted changes');
|
|
25
|
-
console.log(' Commit or stash them first\n');
|
|
26
|
-
process.exit(1);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Step 4:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
this.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import { readFileSync, existsSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
|
|
5
|
+
export class SyncCommand {
|
|
6
|
+
static execute() {
|
|
7
|
+
console.log('\n🔄 Syncing with remote main branch...\n');
|
|
8
|
+
|
|
9
|
+
// Step 1: Get current branch
|
|
10
|
+
const currentBranch = this.getCurrentBranch();
|
|
11
|
+
console.log(`📍 Current branch: ${currentBranch}\n`);
|
|
12
|
+
|
|
13
|
+
// Step 2: Check if on feature branch
|
|
14
|
+
const isFeatureBranch = currentBranch.startsWith('feature/');
|
|
15
|
+
|
|
16
|
+
if (!isFeatureBranch && currentBranch !== 'main') {
|
|
17
|
+
console.log(`⚠️ You're on branch '${currentBranch}', not a feature branch`);
|
|
18
|
+
console.log(` This command syncs feature branches with main\n`);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Step 3: Check for uncommitted changes
|
|
23
|
+
if (this.hasUncommittedChanges()) {
|
|
24
|
+
console.log('❌ You have uncommitted changes');
|
|
25
|
+
console.log(' Commit or stash them first\n');
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Step 4: Check PR status (CRITICAL: prevents data loss)
|
|
30
|
+
if (isFeatureBranch) {
|
|
31
|
+
this.checkPRStatus(currentBranch);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Step 5: Get main branch name
|
|
35
|
+
const mainBranch = this.getMainBranch();
|
|
36
|
+
console.log(`🎯 Main branch: ${mainBranch}\n`);
|
|
37
|
+
|
|
38
|
+
// Step 6: Switch to main
|
|
39
|
+
console.log(`📦 Switching to ${mainBranch}...\n`);
|
|
40
|
+
this.switchToMain(mainBranch);
|
|
41
|
+
|
|
42
|
+
// Step 7: Pull latest changes
|
|
43
|
+
console.log('⬇️ Pulling latest changes...\n');
|
|
44
|
+
this.pullMain(mainBranch);
|
|
45
|
+
|
|
46
|
+
// Step 8: Delete feature branch if we were on one
|
|
47
|
+
if (isFeatureBranch) {
|
|
48
|
+
console.log(`🗑️ Cleaning up feature branch: ${currentBranch}...\n`);
|
|
49
|
+
this.deleteFeatureBranch(currentBranch);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Step 9: Display summary
|
|
53
|
+
this.displaySummary(mainBranch, currentBranch, isFeatureBranch);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
static getCurrentBranch() {
|
|
57
|
+
try {
|
|
58
|
+
return execSync('git branch --show-current', { encoding: 'utf-8' }).trim();
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.log(`\n❌ Failed to get current branch: ${error.message}\n`);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static getMainBranch() {
|
|
66
|
+
try {
|
|
67
|
+
// Try to detect main branch from remote
|
|
68
|
+
const remotes = execSync('git branch -r', { encoding: 'utf-8' });
|
|
69
|
+
|
|
70
|
+
if (remotes.includes('origin/main')) {
|
|
71
|
+
return 'main';
|
|
72
|
+
} else if (remotes.includes('origin/master')) {
|
|
73
|
+
return 'master';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Default to main
|
|
77
|
+
return 'main';
|
|
78
|
+
} catch (error) {
|
|
79
|
+
return 'main';
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
static hasUncommittedChanges() {
|
|
84
|
+
try {
|
|
85
|
+
const status = execSync('git status --porcelain', { encoding: 'utf-8' });
|
|
86
|
+
return status.trim().length > 0;
|
|
87
|
+
} catch (error) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
static switchToMain(mainBranch) {
|
|
93
|
+
try {
|
|
94
|
+
execSync(`git checkout ${mainBranch}`, { stdio: 'inherit' });
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.log(`\n❌ Failed to switch to ${mainBranch}: ${error.message}\n`);
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
static pullMain(mainBranch) {
|
|
102
|
+
try {
|
|
103
|
+
execSync(`git pull origin ${mainBranch}`, { stdio: 'inherit' });
|
|
104
|
+
} catch (error) {
|
|
105
|
+
console.log(`\n❌ Failed to pull from ${mainBranch}: ${error.message}\n`);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
static deleteFeatureBranch(branchName) {
|
|
111
|
+
try {
|
|
112
|
+
// Delete local branch
|
|
113
|
+
execSync(`git branch -d ${branchName}`, { stdio: 'inherit' });
|
|
114
|
+
console.log(` ✓ Deleted local branch: ${branchName}`);
|
|
115
|
+
} catch (error) {
|
|
116
|
+
// Branch might have unmerged commits, try force delete
|
|
117
|
+
try {
|
|
118
|
+
console.log(` ⚠️ Branch has unmerged commits, force deleting...`);
|
|
119
|
+
execSync(`git branch -D ${branchName}`, { stdio: 'inherit' });
|
|
120
|
+
console.log(` ✓ Force deleted local branch: ${branchName}`);
|
|
121
|
+
} catch (forceError) {
|
|
122
|
+
console.log(` ⚠️ Could not delete branch: ${forceError.message}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
static checkPRStatus(branchName) {
|
|
128
|
+
try {
|
|
129
|
+
// Check if PR exists for this branch
|
|
130
|
+
const prInfo = execSync(`gh pr view ${branchName} --json state,mergedAt`, {
|
|
131
|
+
encoding: 'utf-8',
|
|
132
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const pr = JSON.parse(prInfo);
|
|
136
|
+
|
|
137
|
+
// If PR exists but not merged, block sync
|
|
138
|
+
if (pr.state === 'OPEN' || (pr.state === 'CLOSED' && !pr.mergedAt)) {
|
|
139
|
+
console.log(`\n❌ Cannot sync: PR for ${branchName} is not merged\n`);
|
|
140
|
+
console.log(` PR must be merged before running sync\n`);
|
|
141
|
+
console.log(` Options:`);
|
|
142
|
+
console.log(` 1. Merge the PR on GitHub`);
|
|
143
|
+
console.log(` 2. Close PR and abandon changes\n`);
|
|
144
|
+
console.log(` Aborting sync to prevent data loss.\n`);
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// PR is merged, safe to proceed
|
|
149
|
+
console.log(`✅ PR merged - safe to sync\n`);
|
|
150
|
+
|
|
151
|
+
} catch (error) {
|
|
152
|
+
// No PR found - check if branch has commits
|
|
153
|
+
try {
|
|
154
|
+
const commits = execSync(`git log origin/main..${branchName} --oneline`, {
|
|
155
|
+
encoding: 'utf-8',
|
|
156
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
if (commits.trim().length > 0) {
|
|
160
|
+
console.log(`\n❌ Cannot sync: No PR found but ${branchName} has unpushed commits\n`);
|
|
161
|
+
console.log(` You have committed changes that were never pushed to a PR.\n`);
|
|
162
|
+
console.log(` Options:`);
|
|
163
|
+
console.log(` 1. Create PR first: npx agentic15 commit`);
|
|
164
|
+
console.log(` 2. Push manually: git push -u origin ${branchName}\n`);
|
|
165
|
+
console.log(` Aborting sync to prevent data loss.\n`);
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
} catch (e) {
|
|
169
|
+
// Error checking commits, be safe and block
|
|
170
|
+
console.log(`\n⚠️ Could not verify PR status for ${branchName}`);
|
|
171
|
+
console.log(` Aborting sync for safety\n`);
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
static displaySummary(mainBranch, previousBranch, wasFeatureBranch) {
|
|
178
|
+
console.log('\n' + '='.repeat(60));
|
|
179
|
+
console.log('✅ Sync complete!');
|
|
180
|
+
console.log('='.repeat(60));
|
|
181
|
+
console.log(`\n📍 Current branch: ${mainBranch}`);
|
|
182
|
+
console.log(`📥 Latest changes pulled from origin/${mainBranch}`);
|
|
183
|
+
|
|
184
|
+
if (wasFeatureBranch) {
|
|
185
|
+
console.log(`🗑️ Deleted feature branch: ${previousBranch}`);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
console.log('\n💡 Next steps:');
|
|
189
|
+
console.log(' 1. Start a new task: npx agentic15 task start TASK-XXX');
|
|
190
|
+
console.log(' 2. Check status: npx agentic15 status\n');
|
|
191
|
+
}
|
|
192
|
+
}
|
|
@@ -51,7 +51,19 @@ export class TaskIssueMapper {
|
|
|
51
51
|
body += `**Estimated Hours:** ${task.estimatedHours}h\n\n`;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
body += `##
|
|
54
|
+
body += `## Phase\n\n`;
|
|
55
|
+
body += `${task.phase || 'implementation'}\n\n`;
|
|
56
|
+
|
|
57
|
+
body += `## Dependencies\n\n`;
|
|
58
|
+
if (task.dependencies && task.dependencies.length > 0) {
|
|
59
|
+
task.dependencies.forEach(dep => {
|
|
60
|
+
body += `- ${dep}\n`;
|
|
61
|
+
});
|
|
62
|
+
} else {
|
|
63
|
+
body += `*No dependencies*\n`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
body += `\n## Completion Criteria\n\n`;
|
|
55
67
|
if (task.completionCriteria && task.completionCriteria.length > 0) {
|
|
56
68
|
task.completionCriteria.forEach(criteria => {
|
|
57
69
|
body += `- [ ] ${criteria}\n`;
|
|
@@ -60,26 +72,69 @@ export class TaskIssueMapper {
|
|
|
60
72
|
body += `*No specific criteria defined*\n`;
|
|
61
73
|
}
|
|
62
74
|
|
|
63
|
-
|
|
64
|
-
if (task.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
body +=
|
|
75
|
+
// Add TDD requirements based on task phase
|
|
76
|
+
if (task.phase === 'testing') {
|
|
77
|
+
body += `\n## Test Requirements (if testing task)\n\n`;
|
|
78
|
+
body += `**For Testing Tasks:**\n`;
|
|
79
|
+
body += `- [ ] Tests are REAL and EXECUTABLE (no mocks/placeholders)\n`;
|
|
80
|
+
body += `- [ ] Tests verify actual functionality (not just pass by default)\n`;
|
|
81
|
+
body += `- [ ] Positive test cases included\n`;
|
|
82
|
+
body += `- [ ] Negative test cases included\n`;
|
|
83
|
+
body += `- [ ] Edge cases covered\n`;
|
|
84
|
+
body += `- [ ] Error conditions tested\n\n`;
|
|
85
|
+
|
|
86
|
+
// Add UI or Backend specific requirements based on test cases
|
|
87
|
+
const hasUITests = task.testCases?.some(tc =>
|
|
88
|
+
tc.toLowerCase().includes('ui') ||
|
|
89
|
+
tc.toLowerCase().includes('component') ||
|
|
90
|
+
tc.toLowerCase().includes('render') ||
|
|
91
|
+
tc.toLowerCase().includes('form') ||
|
|
92
|
+
tc.toLowerCase().includes('navigation')
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
const hasBackendTests = task.testCases?.some(tc =>
|
|
96
|
+
tc.toLowerCase().includes('api') ||
|
|
97
|
+
tc.toLowerCase().includes('endpoint') ||
|
|
98
|
+
tc.toLowerCase().includes('response') ||
|
|
99
|
+
tc.toLowerCase().includes('status')
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
if (hasUITests) {
|
|
103
|
+
body += `**For UI Testing Tasks:**\n`;
|
|
104
|
+
body += `- [ ] User interactions verified\n`;
|
|
105
|
+
body += `- [ ] Component state changes tested\n`;
|
|
106
|
+
body += `- [ ] Visual rendering validated\n`;
|
|
107
|
+
body += `- [ ] Form validation tested\n`;
|
|
108
|
+
body += `- [ ] Navigation flows tested\n\n`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (hasBackendTests) {
|
|
112
|
+
body += `**For Backend Testing Tasks:**\n`;
|
|
113
|
+
body += `- [ ] API responses verified\n`;
|
|
114
|
+
body += `- [ ] Data validation tested\n`;
|
|
115
|
+
body += `- [ ] Error handling validated\n`;
|
|
116
|
+
body += `- [ ] Status codes correct\n\n`;
|
|
117
|
+
}
|
|
70
118
|
}
|
|
71
119
|
|
|
72
|
-
|
|
73
|
-
|
|
120
|
+
if (task.phase === 'implementation') {
|
|
121
|
+
body += `\n## Implementation Requirements (if implementation task)\n\n`;
|
|
122
|
+
body += `**For Implementation Tasks:**\n`;
|
|
123
|
+
body += `- [ ] Prerequisite testing task completed\n`;
|
|
124
|
+
body += `- [ ] All tests from prerequisite task pass\n`;
|
|
125
|
+
body += `- [ ] Code satisfies test requirements\n`;
|
|
126
|
+
body += `- [ ] No breaking changes to existing tests\n\n`;
|
|
127
|
+
}
|
|
74
128
|
|
|
75
129
|
if (task.testCases && task.testCases.length > 0) {
|
|
76
|
-
body +=
|
|
130
|
+
body += `## Test Cases\n\n`;
|
|
77
131
|
task.testCases.forEach(test => {
|
|
78
132
|
body += `- ${test}\n`;
|
|
79
133
|
});
|
|
134
|
+
body += `\n`;
|
|
80
135
|
}
|
|
81
136
|
|
|
82
|
-
body +=
|
|
137
|
+
body += `---\n*Auto-generated by Agentic15 Claude Zen*`;
|
|
83
138
|
|
|
84
139
|
return body;
|
|
85
140
|
}
|
|
@@ -1,23 +1,54 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Task
|
|
3
|
-
about: Auto-generated task from Agentic15 plan
|
|
4
|
-
title: '[TASK-XXX] '
|
|
5
|
-
labels: 'task'
|
|
6
|
-
assignees: ''
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Task Description
|
|
10
|
-
|
|
11
|
-
<!-- Auto-generated from PROJECT-PLAN.json -->
|
|
12
|
-
|
|
13
|
-
##
|
|
14
|
-
|
|
15
|
-
<!-- Auto-populated from task definition -->
|
|
16
|
-
|
|
17
|
-
## Dependencies
|
|
18
|
-
|
|
19
|
-
<!-- Auto-populated from task definition -->
|
|
20
|
-
|
|
21
|
-
##
|
|
22
|
-
|
|
23
|
-
<!-- Auto-populated from task definition -->
|
|
1
|
+
---
|
|
2
|
+
name: Task
|
|
3
|
+
about: Auto-generated task from Agentic15 plan
|
|
4
|
+
title: '[TASK-XXX] '
|
|
5
|
+
labels: 'task'
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Task Description
|
|
10
|
+
|
|
11
|
+
<!-- Auto-generated from PROJECT-PLAN.json -->
|
|
12
|
+
|
|
13
|
+
## Phase
|
|
14
|
+
|
|
15
|
+
<!-- Auto-populated from task definition -->
|
|
16
|
+
|
|
17
|
+
## Dependencies
|
|
18
|
+
|
|
19
|
+
<!-- Auto-populated from task definition -->
|
|
20
|
+
|
|
21
|
+
## Completion Criteria
|
|
22
|
+
|
|
23
|
+
<!-- Auto-populated from task definition -->
|
|
24
|
+
|
|
25
|
+
## Test Requirements (if testing task)
|
|
26
|
+
|
|
27
|
+
**For Testing Tasks:**
|
|
28
|
+
- [ ] Tests are REAL and EXECUTABLE (no mocks/placeholders)
|
|
29
|
+
- [ ] Tests verify actual functionality (not just pass by default)
|
|
30
|
+
- [ ] Positive test cases included
|
|
31
|
+
- [ ] Negative test cases included
|
|
32
|
+
- [ ] Edge cases covered
|
|
33
|
+
- [ ] Error conditions tested
|
|
34
|
+
|
|
35
|
+
**For UI Testing Tasks:**
|
|
36
|
+
- [ ] User interactions verified
|
|
37
|
+
- [ ] Component state changes tested
|
|
38
|
+
- [ ] Visual rendering validated
|
|
39
|
+
- [ ] Form validation tested
|
|
40
|
+
- [ ] Navigation flows tested
|
|
41
|
+
|
|
42
|
+
**For Backend Testing Tasks:**
|
|
43
|
+
- [ ] API responses verified
|
|
44
|
+
- [ ] Data validation tested
|
|
45
|
+
- [ ] Error handling validated
|
|
46
|
+
- [ ] Status codes correct
|
|
47
|
+
|
|
48
|
+
## Implementation Requirements (if implementation task)
|
|
49
|
+
|
|
50
|
+
**For Implementation Tasks:**
|
|
51
|
+
- [ ] Prerequisite testing task completed
|
|
52
|
+
- [ ] All tests from prerequisite task pass
|
|
53
|
+
- [ ] Code satisfies test requirements
|
|
54
|
+
- [ ] No breaking changes to existing tests
|
|
@@ -1,23 +1,65 @@
|
|
|
1
|
-
# Pull Request
|
|
2
|
-
|
|
3
|
-
## Task
|
|
4
|
-
|
|
5
|
-
Closes #
|
|
6
|
-
|
|
7
|
-
##
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
|
|
21
|
-
##
|
|
22
|
-
|
|
23
|
-
|
|
1
|
+
# Pull Request
|
|
2
|
+
|
|
3
|
+
## Task
|
|
4
|
+
|
|
5
|
+
Closes #
|
|
6
|
+
|
|
7
|
+
## Task Type
|
|
8
|
+
|
|
9
|
+
- [ ] Testing Task (TDD - writing tests BEFORE implementation)
|
|
10
|
+
- [ ] Implementation Task (TDD - making tests pass)
|
|
11
|
+
- [ ] Design Task (schemas, architecture, planning)
|
|
12
|
+
|
|
13
|
+
## Description
|
|
14
|
+
|
|
15
|
+
<!-- Auto-generated from task description -->
|
|
16
|
+
|
|
17
|
+
## Changes
|
|
18
|
+
|
|
19
|
+
-
|
|
20
|
+
|
|
21
|
+
## TDD Compliance (REQUIRED)
|
|
22
|
+
|
|
23
|
+
### For Testing Tasks:
|
|
24
|
+
- [ ] All tests are REAL and EXECUTABLE (no mocks/placeholders)
|
|
25
|
+
- [ ] Tests verify actual functionality
|
|
26
|
+
- [ ] Positive and negative test cases included
|
|
27
|
+
- [ ] Edge cases and error conditions covered
|
|
28
|
+
- [ ] Tests pass and are ready for implementation phase
|
|
29
|
+
- [ ] **Test Output:** (paste screenshot or output showing tests passing)
|
|
30
|
+
|
|
31
|
+
### For Implementation Tasks:
|
|
32
|
+
- [ ] Prerequisite testing task is completed
|
|
33
|
+
- [ ] All tests from prerequisite task pass
|
|
34
|
+
- [ ] No tests were modified (implementation should make existing tests pass)
|
|
35
|
+
- [ ] **Test Output:** (paste screenshot showing all tests passing)
|
|
36
|
+
|
|
37
|
+
### For UI Testing/Implementation:
|
|
38
|
+
- [ ] User interactions verified/implemented
|
|
39
|
+
- [ ] Component rendering tested/implemented
|
|
40
|
+
- [ ] Form validation tested/implemented
|
|
41
|
+
- [ ] Visual feedback verified/implemented
|
|
42
|
+
|
|
43
|
+
### For Backend Testing/Implementation:
|
|
44
|
+
- [ ] API responses verified/implemented
|
|
45
|
+
- [ ] Data validation tested/implemented
|
|
46
|
+
- [ ] Error handling verified/implemented
|
|
47
|
+
- [ ] Status codes verified/implemented
|
|
48
|
+
|
|
49
|
+
## Test Results (REQUIRED for all PRs)
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
Paste test output here showing all tests passing
|
|
53
|
+
Example: npm test output or npx playwright test output
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Code Quality
|
|
57
|
+
|
|
58
|
+
- [ ] Code follows project conventions
|
|
59
|
+
- [ ] No commented-out code
|
|
60
|
+
- [ ] No debug statements (console.log, etc.)
|
|
61
|
+
- [ ] Documentation updated (if needed)
|
|
62
|
+
|
|
63
|
+
## Notes
|
|
64
|
+
|
|
65
|
+
<!-- Additional context or notes -->
|