@jojonax/codex-copilot 1.4.0 → 1.4.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jojonax/codex-copilot",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "PRD-driven automated development orchestrator for CodeX / Cursor",
5
5
  "bin": {
6
6
  "codex-copilot": "./bin/cli.js"
@@ -95,7 +95,8 @@ export async function run(projectDir) {
95
95
 
96
96
  // ===== Auto-retry blocked tasks =====
97
97
  // On each run, reset blocked tasks to pending so they're retried in order.
98
- // Checkpoint is NOT cleared it stays at the last position for non-blocked tasks.
98
+ // Per-task checkpoint steps are cleared so the task starts fresh.
99
+ // The main checkpoint position (current_task) is preserved.
99
100
  const blockedTasks = tasks.tasks.filter(t => t.status === 'blocked');
100
101
  if (blockedTasks.length > 0) {
101
102
  log.blank();
@@ -104,8 +105,30 @@ export async function run(projectDir) {
104
105
  bt.status = 'pending';
105
106
  bt.retry_count = (bt.retry_count || 0) + 1;
106
107
  bt._retrying = true; // Flag: don't skip even if below checkpoint
107
- log.dim(` ↳ Task #${bt.id}: ${bt.title.substring(0, 50)} (attempt ${bt.retry_count + 1})`);
108
+
109
+ // Clear per-task checkpoint steps — the task needs a fresh start
110
+ // (The main checkpoint.current_task is NOT affected)
111
+ checkpoint.clearTask(bt.id);
112
+
113
+ // Clean up old branch to avoid "branch already exists" errors
114
+ try {
115
+ git.resetBranch(projectDir, bt.branch, baseBranch);
116
+ log.dim(` ↳ Task #${bt.id}: ${bt.title.substring(0, 50)} (attempt ${bt.retry_count + 1}, branch reset)`);
117
+ } catch {
118
+ // If branch cleanup fails, still let the task try
119
+ log.dim(` ↳ Task #${bt.id}: ${bt.title.substring(0, 50)} (attempt ${bt.retry_count + 1})`);
120
+ }
121
+
122
+ // Close any existing PR for this task (stale from previous attempt)
123
+ if (bt.pr_number) {
124
+ try {
125
+ github.closePR(projectDir, bt.pr_number);
126
+ delete bt.pr_number;
127
+ } catch { /* ignore */ }
128
+ }
108
129
  }
130
+ // Switch back to base branch after all resets
131
+ git.checkoutMain(projectDir, baseBranch);
109
132
  writeJSON(tasksPath, tasks);
110
133
  }
111
134
 
package/src/utils/git.js CHANGED
@@ -65,13 +65,37 @@ export function checkoutBranch(cwd, branch, baseBranch = 'main') {
65
65
  execSafe(`git checkout ${baseBranch}`, cwd);
66
66
  execSafe(`git pull origin ${baseBranch}`, cwd);
67
67
 
68
- // Try to switch, create if not exists
68
+ // Try to switch to existing branch
69
69
  const result = execSafe(`git checkout ${branch}`, cwd);
70
70
  if (!result.ok) {
71
+ // Branch doesn't exist or checkout failed — clean up and create fresh
72
+ execSafe(`git branch -D ${branch}`, cwd); // Delete if exists but broken
71
73
  exec(`git checkout -b ${branch}`, cwd);
72
74
  }
73
75
  }
74
76
 
77
+ /**
78
+ * Delete a branch (local + remote) and recreate fresh from base.
79
+ * Used when retrying blocked tasks to ensure a clean slate.
80
+ */
81
+ export function resetBranch(cwd, branch, baseBranch = 'main') {
82
+ validateBranch(branch);
83
+ validateBranch(baseBranch);
84
+
85
+ // Switch to base first (can't delete current branch)
86
+ execSafe(`git checkout ${baseBranch}`, cwd);
87
+ execSafe(`git pull origin ${baseBranch}`, cwd);
88
+
89
+ // Delete local branch (force, ignore errors if doesn't exist)
90
+ execSafe(`git branch -D ${branch}`, cwd);
91
+
92
+ // Delete remote branch (ignore errors if doesn't exist)
93
+ execSafe(`git push origin --delete ${branch}`, cwd);
94
+
95
+ // Create fresh branch from base
96
+ exec(`git checkout -b ${branch}`, cwd);
97
+ }
98
+
75
99
  /**
76
100
  * Commit all changes
77
101
  */
@@ -111,6 +135,6 @@ export function checkoutMain(cwd, baseBranch = 'main') {
111
135
  }
112
136
 
113
137
  export const git = {
114
- isClean, currentBranch, getRepoInfo, checkoutBranch,
138
+ isClean, currentBranch, getRepoInfo, checkoutBranch, resetBranch,
115
139
  commitAll, pushBranch, checkoutMain, exec, execSafe,
116
140
  };