@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.
@@ -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. Say "Plan created"
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. Write code ONLY in `Agent/src/`
12
- 3. Write tests ONLY in `Agent/tests/`
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": "Implement user registration API",
49
- "description": "POST /api/auth/register endpoint",
48
+ "title": "Write tests for user registration API (TDD)",
49
+ "description": "Write comprehensive tests BEFORE implementing registration endpoint",
50
50
  "status": "pending",
51
- "phase": "implementation",
51
+ "phase": "testing",
52
52
  "dependencies": ["TASK-001"],
53
- "estimatedHours": 6,
53
+ "estimatedHours": 3,
54
54
  "completionCriteria": [
55
- "Email validation implemented",
56
- "Password hashing with bcrypt",
57
- "Duplicate email check",
58
- "Returns JWT token"
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 rejected",
63
- "Weak password rejected",
64
- "Duplicate email rejected"
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
- "./Agent/src/controllers/authController.js",
70
- "./Agent/src/services/userService.js"
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": "Write unit tests for registration",
79
- "description": "Test all registration edge cases",
82
+ "title": "Implement user registration API",
83
+ "description": "POST /api/auth/register endpoint - implement to make tests pass",
80
84
  "status": "pending",
81
- "phase": "testing",
85
+ "phase": "implementation",
82
86
  "dependencies": ["TASK-002"],
83
- "estimatedHours": 3,
87
+ "estimatedHours": 6,
84
88
  "completionCriteria": [
85
- "100% code coverage for registration",
86
- "All edge cases tested",
87
- "Integration tests pass"
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
- "code": [],
91
- "tests": [
92
- "./Agent/tests/auth.test.js",
93
- "./Agent/tests/integration/register.test.js"
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": "Create profile update API",
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": "implementation",
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": ["./Agent/tests/userProfile.test.js"]
159
+ "tests": []
122
160
  }
123
161
  }
124
162
  ]
@@ -140,7 +178,7 @@
140
178
  "dependencies": [],
141
179
  "tasks": [
142
180
  {
143
- "id": "TASK-005",
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-006",
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-005"],
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": ["./Agent/tests/products.test.js"]
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-007",
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-002", "TASK-006"],
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": ["./Agent/tests/cart.test.js"]
310
+ "tests": []
215
311
  }
216
312
  }
217
313
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentic15.com/agentic15-claude-zen",
3
- "version": "5.0.8",
3
+ "version": "5.0.10",
4
4
  "description": "Structured AI-assisted development framework for Claude Code with enforced quality standards",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -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
- prBody += `## Testing\n\n`;
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 += `- [ ] Manual testing completed\n\n`;
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`;
@@ -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: Get main branch name
30
- const mainBranch = this.getMainBranch();
31
- console.log(`🎯 Main branch: ${mainBranch}\n`);
32
-
33
- // Step 5: Switch to main
34
- console.log(`📦 Switching to ${mainBranch}...\n`);
35
- this.switchToMain(mainBranch);
36
-
37
- // Step 6: Pull latest changes
38
- console.log('⬇️ Pulling latest changes...\n');
39
- this.pullMain(mainBranch);
40
-
41
- // Step 7: Delete feature branch if we were on one
42
- if (isFeatureBranch) {
43
- console.log(`🗑️ Cleaning up feature branch: ${currentBranch}...\n`);
44
- this.deleteFeatureBranch(currentBranch);
45
- }
46
-
47
- // Step 8: Display summary
48
- this.displaySummary(mainBranch, currentBranch, isFeatureBranch);
49
- }
50
-
51
- static getCurrentBranch() {
52
- try {
53
- return execSync('git branch --show-current', { encoding: 'utf-8' }).trim();
54
- } catch (error) {
55
- console.log(`\n❌ Failed to get current branch: ${error.message}\n`);
56
- process.exit(1);
57
- }
58
- }
59
-
60
- static getMainBranch() {
61
- try {
62
- // Try to detect main branch from remote
63
- const remotes = execSync('git branch -r', { encoding: 'utf-8' });
64
-
65
- if (remotes.includes('origin/main')) {
66
- return 'main';
67
- } else if (remotes.includes('origin/master')) {
68
- return 'master';
69
- }
70
-
71
- // Default to main
72
- return 'main';
73
- } catch (error) {
74
- return 'main';
75
- }
76
- }
77
-
78
- static hasUncommittedChanges() {
79
- try {
80
- const status = execSync('git status --porcelain', { encoding: 'utf-8' });
81
- return status.trim().length > 0;
82
- } catch (error) {
83
- return false;
84
- }
85
- }
86
-
87
- static switchToMain(mainBranch) {
88
- try {
89
- execSync(`git checkout ${mainBranch}`, { stdio: 'inherit' });
90
- } catch (error) {
91
- console.log(`\n❌ Failed to switch to ${mainBranch}: ${error.message}\n`);
92
- process.exit(1);
93
- }
94
- }
95
-
96
- static pullMain(mainBranch) {
97
- try {
98
- execSync(`git pull origin ${mainBranch}`, { stdio: 'inherit' });
99
- } catch (error) {
100
- console.log(`\n❌ Failed to pull from ${mainBranch}: ${error.message}\n`);
101
- process.exit(1);
102
- }
103
- }
104
-
105
- static deleteFeatureBranch(branchName) {
106
- try {
107
- // Delete local branch
108
- execSync(`git branch -d ${branchName}`, { stdio: 'inherit' });
109
- console.log(` ✓ Deleted local branch: ${branchName}`);
110
- } catch (error) {
111
- // Branch might have unmerged commits, try force delete
112
- try {
113
- console.log(` ⚠️ Branch has unmerged commits, force deleting...`);
114
- execSync(`git branch -D ${branchName}`, { stdio: 'inherit' });
115
- console.log(` ✓ Force deleted local branch: ${branchName}`);
116
- } catch (forceError) {
117
- console.log(` ⚠️ Could not delete branch: ${forceError.message}`);
118
- }
119
- }
120
- }
121
-
122
- static displaySummary(mainBranch, previousBranch, wasFeatureBranch) {
123
- console.log('\n' + '='.repeat(60));
124
- console.log('✅ Sync complete!');
125
- console.log('='.repeat(60));
126
- console.log(`\n📍 Current branch: ${mainBranch}`);
127
- console.log(`📥 Latest changes pulled from origin/${mainBranch}`);
128
-
129
- if (wasFeatureBranch) {
130
- console.log(`🗑️ Deleted feature branch: ${previousBranch}`);
131
- }
132
-
133
- console.log('\n💡 Next steps:');
134
- console.log(' 1. Start a new task: npx agentic15 task start TASK-XXX');
135
- console.log(' 2. Check status: npx agentic15 status\n');
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 += `## Completion Criteria\n\n`;
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
- body += `\n## Dependencies\n\n`;
64
- if (task.dependencies && task.dependencies.length > 0) {
65
- task.dependencies.forEach(dep => {
66
- body += `- ${dep}\n`;
67
- });
68
- } else {
69
- body += `*No dependencies*\n`;
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
- body += `\n## Phase\n\n`;
73
- body += `${task.phase || 'implementation'}\n`;
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 += `\n## Test Cases\n\n`;
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 += `\n---\n*Auto-generated by Agentic15 Claude Zen*`;
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
- ## Completion Criteria
14
-
15
- <!-- Auto-populated from task definition -->
16
-
17
- ## Dependencies
18
-
19
- <!-- Auto-populated from task definition -->
20
-
21
- ## Phase
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
- ## Description
8
-
9
- <!-- Auto-generated from task description -->
10
-
11
- ## Changes
12
-
13
- -
14
-
15
- ## Testing
16
-
17
- - [ ] Unit tests pass (`npm test`)
18
- - [ ] Visual tests pass (if applicable) (`npx playwright test`)
19
- - [ ] Code follows project conventions
20
-
21
- ## Notes
22
-
23
- <!-- Additional context or notes -->
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 -->