@agentic15.com/agentic15-claude-zen 4.0.2 โ 4.0.4
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/package.json +1 -1
- package/src/cli/CommitCommand.js +316 -331
- package/src/cli/UpgradeCommand.js +191 -189
- package/src/core/TemplateManager.js +0 -8
- package/templates/.claude/hooks/session-start-context.js +131 -128
- package/templates/.claude/settings.json +1 -81
- package/templates/package.json +1 -16
- package/templates/.babelrc +0 -6
- package/templates/.claude/hooks/post-merge.js +0 -163
- package/templates/.claude/hooks/validate-git-workflow.js +0 -74
- package/templates/__mocks__/fileMock.js +0 -9
- package/templates/jest.config.js +0 -48
- package/templates/jest.setup.js +0 -13
package/src/cli/CommitCommand.js
CHANGED
|
@@ -1,331 +1,316 @@
|
|
|
1
|
-
import { execSync } from 'child_process';
|
|
2
|
-
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
3
|
-
import { join } from 'path';
|
|
4
|
-
import { GitHubClient } from '../core/GitHubClient.js';
|
|
5
|
-
import { GitHubConfig } from '../core/GitHubConfig.js';
|
|
6
|
-
|
|
7
|
-
export class CommitCommand {
|
|
8
|
-
static async execute() {
|
|
9
|
-
console.log('\n๐ Starting commit workflow...\n');
|
|
10
|
-
|
|
11
|
-
// Step 1: Find active task
|
|
12
|
-
const { task, tracker } = this.getActiveTask();
|
|
13
|
-
|
|
14
|
-
if (!task) {
|
|
15
|
-
console.log('โ No task in progress');
|
|
16
|
-
console.log(' Start a task first: agentic15 task start TASK-001\n');
|
|
17
|
-
process.exit(1);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
console.log(`๐ Task: ${task.id} - ${task.title}\n`);
|
|
21
|
-
|
|
22
|
-
// Step 2:
|
|
23
|
-
console.log('
|
|
24
|
-
this.
|
|
25
|
-
|
|
26
|
-
// Step 3:
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
// Step 5:
|
|
34
|
-
console.log('
|
|
35
|
-
this.
|
|
36
|
-
|
|
37
|
-
// Step 6:
|
|
38
|
-
console.log('
|
|
39
|
-
this.
|
|
40
|
-
|
|
41
|
-
// Step 7:
|
|
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
|
-
} catch (
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
try {
|
|
136
|
-
//
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
prBody
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
);
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
console.log('
|
|
296
|
-
console.log('
|
|
297
|
-
console.log('
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
// Try to detect main branch
|
|
318
|
-
const branches = execSync('git branch -r', { encoding: 'utf-8' });
|
|
319
|
-
|
|
320
|
-
if (branches.includes('origin/main')) {
|
|
321
|
-
return 'main';
|
|
322
|
-
} else if (branches.includes('origin/master')) {
|
|
323
|
-
return 'master';
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
return 'main'; // Default
|
|
327
|
-
} catch (e) {
|
|
328
|
-
return 'main';
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
}
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { GitHubClient } from '../core/GitHubClient.js';
|
|
5
|
+
import { GitHubConfig } from '../core/GitHubConfig.js';
|
|
6
|
+
|
|
7
|
+
export class CommitCommand {
|
|
8
|
+
static async execute() {
|
|
9
|
+
console.log('\n๐ Starting commit workflow...\n');
|
|
10
|
+
|
|
11
|
+
// Step 1: Find active task
|
|
12
|
+
const { task, tracker } = this.getActiveTask();
|
|
13
|
+
|
|
14
|
+
if (!task) {
|
|
15
|
+
console.log('โ No task in progress');
|
|
16
|
+
console.log(' Start a task first: agentic15 task start TASK-001\n');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
console.log(`๐ Task: ${task.id} - ${task.title}\n`);
|
|
21
|
+
|
|
22
|
+
// Step 2: Stage files in Agent/
|
|
23
|
+
console.log('๐ฆ Staging changes...\n');
|
|
24
|
+
this.stageFiles();
|
|
25
|
+
|
|
26
|
+
// Step 3: Generate commit message
|
|
27
|
+
const commitMessage = this.generateCommitMessage(task);
|
|
28
|
+
|
|
29
|
+
// Step 4: Commit
|
|
30
|
+
console.log('๐พ Creating commit...\n');
|
|
31
|
+
this.createCommit(commitMessage);
|
|
32
|
+
|
|
33
|
+
// Step 5: Push to feature branch
|
|
34
|
+
console.log('โฌ๏ธ Pushing to remote...\n');
|
|
35
|
+
this.pushBranch(task.id);
|
|
36
|
+
|
|
37
|
+
// Step 6: Create PR
|
|
38
|
+
console.log('๐ Creating pull request...\n');
|
|
39
|
+
const prUrl = await this.createPullRequest(task, commitMessage);
|
|
40
|
+
|
|
41
|
+
// Step 7: Update GitHub issue status
|
|
42
|
+
await this.updateGitHubIssue(task, prUrl);
|
|
43
|
+
|
|
44
|
+
// Step 8: Mark task as completed
|
|
45
|
+
this.markTaskCompleted(task);
|
|
46
|
+
|
|
47
|
+
// Step 9: Display summary
|
|
48
|
+
this.displaySummary(task, prUrl, tracker);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static getActiveTask() {
|
|
52
|
+
const activePlanPath = join(process.cwd(), '.claude', 'ACTIVE-PLAN');
|
|
53
|
+
|
|
54
|
+
if (!existsSync(activePlanPath)) {
|
|
55
|
+
console.log('\nโ No active plan found\n');
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const planId = readFileSync(activePlanPath, 'utf-8').trim();
|
|
60
|
+
const trackerPath = join(process.cwd(), '.claude', 'plans', planId, 'TASK-TRACKER.json');
|
|
61
|
+
|
|
62
|
+
if (!existsSync(trackerPath)) {
|
|
63
|
+
console.log('\nโ Task tracker not found\n');
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const tracker = JSON.parse(readFileSync(trackerPath, 'utf-8'));
|
|
68
|
+
const task = tracker.taskFiles.find(t => t.status === 'in_progress');
|
|
69
|
+
|
|
70
|
+
return { task, tracker };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static stageFiles() {
|
|
74
|
+
try {
|
|
75
|
+
// Stage all files in Agent/
|
|
76
|
+
execSync('git add Agent/', { stdio: 'inherit' });
|
|
77
|
+
|
|
78
|
+
// Also stage scripts/ if exists
|
|
79
|
+
try {
|
|
80
|
+
execSync('git add scripts/', { stdio: 'pipe' });
|
|
81
|
+
} catch (e) {
|
|
82
|
+
// scripts/ might not exist
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Show what was staged
|
|
86
|
+
const staged = execSync('git diff --cached --name-only', { encoding: 'utf-8' });
|
|
87
|
+
|
|
88
|
+
if (!staged.trim()) {
|
|
89
|
+
console.log('โ ๏ธ No changes to commit\n');
|
|
90
|
+
process.exit(0);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
console.log('Staged files:');
|
|
94
|
+
staged.trim().split('\n').forEach(file => {
|
|
95
|
+
console.log(` โ ${file}`);
|
|
96
|
+
});
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.log(`\nโ Failed to stage files: ${error.message}\n`);
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
static generateCommitMessage(task) {
|
|
104
|
+
// Load full task details
|
|
105
|
+
const activePlanPath = join(process.cwd(), '.claude', 'ACTIVE-PLAN');
|
|
106
|
+
const planId = readFileSync(activePlanPath, 'utf-8').trim();
|
|
107
|
+
const taskPath = join(process.cwd(), '.claude', 'plans', planId, 'tasks', `${task.id}.json`);
|
|
108
|
+
|
|
109
|
+
let taskData;
|
|
110
|
+
try {
|
|
111
|
+
taskData = JSON.parse(readFileSync(taskPath, 'utf-8'));
|
|
112
|
+
} catch (e) {
|
|
113
|
+
taskData = task;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Format: [TASK-001] Task title
|
|
117
|
+
return `[${task.id}] ${taskData.title || task.title}`;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
static createCommit(message) {
|
|
121
|
+
try {
|
|
122
|
+
// Escape double quotes and backslashes for shell
|
|
123
|
+
const escapedMessage = message.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
124
|
+
execSync(`git commit -m "${escapedMessage}"`, { stdio: 'inherit' });
|
|
125
|
+
console.log('โ
Commit created');
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.log(`\nโ Failed to create commit: ${error.message}\n`);
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
static pushBranch(taskId) {
|
|
133
|
+
const branchName = `feature/${taskId.toLowerCase()}`;
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
// Check if branch has upstream
|
|
137
|
+
try {
|
|
138
|
+
execSync('git rev-parse --abbrev-ref --symbolic-full-name @{u}', { stdio: 'pipe' });
|
|
139
|
+
// Has upstream, just push
|
|
140
|
+
execSync('git push', { stdio: 'inherit' });
|
|
141
|
+
} catch (e) {
|
|
142
|
+
// No upstream, set it
|
|
143
|
+
execSync(`git push -u origin ${branchName}`, { stdio: 'inherit' });
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
console.log('โ
Pushed to remote');
|
|
147
|
+
} catch (error) {
|
|
148
|
+
console.log(`\nโ Failed to push: ${error.message}\n`);
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
static async createPullRequest(task, commitMessage) {
|
|
154
|
+
try {
|
|
155
|
+
// Get main branch name
|
|
156
|
+
const mainBranch = this.getMainBranch();
|
|
157
|
+
|
|
158
|
+
// Load task for issue number
|
|
159
|
+
const activePlanPath = join(process.cwd(), '.claude', 'ACTIVE-PLAN');
|
|
160
|
+
const planId = readFileSync(activePlanPath, 'utf-8').trim();
|
|
161
|
+
const taskPath = join(process.cwd(), '.claude', 'plans', planId, 'tasks', `${task.id}.json`);
|
|
162
|
+
|
|
163
|
+
let taskData;
|
|
164
|
+
try {
|
|
165
|
+
taskData = JSON.parse(readFileSync(taskPath, 'utf-8'));
|
|
166
|
+
} catch (e) {
|
|
167
|
+
taskData = task;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Build PR body following .github/PULL_REQUEST_TEMPLATE.md structure
|
|
171
|
+
let prBody = `## Task\n\n`;
|
|
172
|
+
|
|
173
|
+
if (taskData.githubIssue) {
|
|
174
|
+
prBody += `Closes #${taskData.githubIssue}\n\n`;
|
|
175
|
+
} else {
|
|
176
|
+
prBody += `${task.id}\n\n`;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
prBody += `## Description\n\n`;
|
|
180
|
+
prBody += `${taskData.description || task.description || commitMessage}\n\n`;
|
|
181
|
+
|
|
182
|
+
prBody += `## Changes\n\n`;
|
|
183
|
+
prBody += `- Implemented ${task.title}\n\n`;
|
|
184
|
+
|
|
185
|
+
prBody += `## Testing\n\n`;
|
|
186
|
+
prBody += `- [ ] Code follows project conventions\n`;
|
|
187
|
+
prBody += `- [ ] Manual testing completed\n\n`;
|
|
188
|
+
|
|
189
|
+
prBody += `## Notes\n\n`;
|
|
190
|
+
prBody += `Auto-generated by Agentic15 Claude Zen`;
|
|
191
|
+
|
|
192
|
+
// Create PR using gh CLI
|
|
193
|
+
const prCommand = `gh pr create --title "${commitMessage}" --body "${prBody}" --base ${mainBranch}`;
|
|
194
|
+
const prOutput = execSync(prCommand, { encoding: 'utf-8' });
|
|
195
|
+
|
|
196
|
+
// Extract PR URL from output
|
|
197
|
+
const prUrl = prOutput.match(/https:\/\/github\.com\/[^\s]+/)?.[0];
|
|
198
|
+
|
|
199
|
+
if (prUrl) {
|
|
200
|
+
console.log(`โ
Pull request created: ${prUrl}`);
|
|
201
|
+
return prUrl;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
console.log('โ
Pull request created');
|
|
205
|
+
return null;
|
|
206
|
+
} catch (error) {
|
|
207
|
+
console.log(`\nโ ๏ธ Failed to create PR: ${error.message}`);
|
|
208
|
+
console.log(' You may need to install GitHub CLI: https://cli.github.com/\n');
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
static async updateGitHubIssue(task, prUrl) {
|
|
214
|
+
const config = new GitHubConfig(process.cwd());
|
|
215
|
+
|
|
216
|
+
if (!config.isAutoUpdateEnabled()) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
try {
|
|
221
|
+
// Load task data
|
|
222
|
+
const activePlanPath = join(process.cwd(), '.claude', 'ACTIVE-PLAN');
|
|
223
|
+
const planId = readFileSync(activePlanPath, 'utf-8').trim();
|
|
224
|
+
const taskPath = join(process.cwd(), '.claude', 'plans', planId, 'tasks', `${task.id}.json`);
|
|
225
|
+
|
|
226
|
+
const taskData = JSON.parse(readFileSync(taskPath, 'utf-8'));
|
|
227
|
+
|
|
228
|
+
if (!taskData.githubIssue) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const client = new GitHubClient(
|
|
233
|
+
config.getToken(),
|
|
234
|
+
config.getRepoInfo().owner,
|
|
235
|
+
config.getRepoInfo().repo
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
if (!client.isConfigured()) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Update labels to "in review"
|
|
243
|
+
await client.updateIssueLabels(taskData.githubIssue, ['status: in-review', `phase: ${taskData.phase || 'implementation'}`]);
|
|
244
|
+
|
|
245
|
+
// Add comment with PR link
|
|
246
|
+
if (prUrl) {
|
|
247
|
+
const comment = `Pull request created: ${prUrl}\n\nTask is now in code review.`;
|
|
248
|
+
await client.addIssueComment(taskData.githubIssue, comment);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
console.log(`โ
Updated GitHub issue #${taskData.githubIssue}`);
|
|
252
|
+
} catch (error) {
|
|
253
|
+
console.log(`\nโ ๏ธ Failed to update GitHub issue: ${error.message}\n`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
static markTaskCompleted(task) {
|
|
258
|
+
try {
|
|
259
|
+
const activePlanPath = join(process.cwd(), '.claude', 'ACTIVE-PLAN');
|
|
260
|
+
const planId = readFileSync(activePlanPath, 'utf-8').trim();
|
|
261
|
+
const trackerPath = join(process.cwd(), '.claude', 'plans', planId, 'TASK-TRACKER.json');
|
|
262
|
+
|
|
263
|
+
// Update tracker
|
|
264
|
+
const tracker = JSON.parse(readFileSync(trackerPath, 'utf-8'));
|
|
265
|
+
const taskInTracker = tracker.taskFiles.find(t => t.id === task.id);
|
|
266
|
+
|
|
267
|
+
if (taskInTracker) {
|
|
268
|
+
taskInTracker.status = 'completed';
|
|
269
|
+
taskInTracker.completedAt = new Date().toISOString();
|
|
270
|
+
writeFileSync(trackerPath, JSON.stringify(tracker, null, 2));
|
|
271
|
+
console.log(`\nโ
Marked ${task.id} as completed`);
|
|
272
|
+
}
|
|
273
|
+
} catch (error) {
|
|
274
|
+
console.log(`\nโ ๏ธ Failed to mark task as completed: ${error.message}`);
|
|
275
|
+
console.log(' You may need to manually update TASK-TRACKER.json\n');
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
static displaySummary(task, prUrl, tracker) {
|
|
280
|
+
console.log('\nโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ');
|
|
281
|
+
console.log('โ โ
Commit Workflow Complete โ');
|
|
282
|
+
console.log('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n');
|
|
283
|
+
|
|
284
|
+
console.log(`๐ Task: ${task.id} - ${task.title}`);
|
|
285
|
+
|
|
286
|
+
if (prUrl) {
|
|
287
|
+
console.log(`๐ PR: ${prUrl}`);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const completed = tracker.taskFiles.filter(t => t.status === 'completed').length;
|
|
291
|
+
const total = tracker.taskFiles.length;
|
|
292
|
+
|
|
293
|
+
console.log(`\n๐ Progress: ${completed}/${total} completed\n`);
|
|
294
|
+
|
|
295
|
+
console.log('๐ก Next steps:');
|
|
296
|
+
console.log(' 1. Review and merge PR on GitHub');
|
|
297
|
+
console.log(' 2. After merge, run: agentic15 task next\n');
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
static getMainBranch() {
|
|
301
|
+
try {
|
|
302
|
+
// Try to detect main branch
|
|
303
|
+
const branches = execSync('git branch -r', { encoding: 'utf-8' });
|
|
304
|
+
|
|
305
|
+
if (branches.includes('origin/main')) {
|
|
306
|
+
return 'main';
|
|
307
|
+
} else if (branches.includes('origin/master')) {
|
|
308
|
+
return 'master';
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return 'main'; // Default
|
|
312
|
+
} catch (e) {
|
|
313
|
+
return 'main';
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|