@agentic15.com/agentic15-claude-zen 5.0.8 ā 5.0.9
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/bin/agentic15.js +1 -1
- package/package.json +1 -1
- package/src/cli/SyncCommand.js +192 -137
package/bin/agentic15.js
CHANGED
package/package.json
CHANGED
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
|
+
}
|