@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 CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  import { Command } from 'commander';
4
4
  import { AuthCommand } from '../src/cli/AuthCommand.js';
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.9",
4
4
  "description": "Structured AI-assisted development framework for Claude Code with enforced quality standards",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -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
+ }