create-claude-workspace 2.3.14 → 2.3.16

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.
@@ -911,34 +911,57 @@ async function pollAndMergePR(task, pipeline, branch, platform, projectDir, work
911
911
  return true;
912
912
  if (prStatus.status === 'closed')
913
913
  return false;
914
- // CI failedspawn agent to fix
915
- if (prStatus.ciStatus === 'failed' && pipeline.ciFixes < MAX_CI_FIXES) {
914
+ // Ready to merge CI passed and mergeable
915
+ if (prStatus.mergeable) {
916
+ logger.info(`[${task.id}] PR mergeable — merging`);
917
+ return mergePR(projectDir, platform, prStatus.number);
918
+ }
919
+ // CI still running or not started — poll
920
+ if (prStatus.ciStatus === 'pending' || prStatus.ciStatus === 'not-found') {
921
+ logger.info(`[${task.id}] CI: ${prStatus.ciStatus} — polling...`);
922
+ await sleep(PR_POLL_INTERVAL);
923
+ continue;
924
+ }
925
+ // CI passed but not mergeable (needs approval, merge checks, etc.) — poll
926
+ if (prStatus.ciStatus === 'passed' && !prStatus.mergeable) {
927
+ logger.info(`[${task.id}] CI passed, not yet mergeable — polling...`);
928
+ await sleep(PR_POLL_INTERVAL);
929
+ continue;
930
+ }
931
+ // CI failed — delegate to implementing agent to fix
932
+ if (prStatus.ciStatus === 'failed') {
933
+ if (pipeline.ciFixes >= MAX_CI_FIXES) {
934
+ logger.error(`[${task.id}] CI fix limit (${MAX_CI_FIXES}) reached — giving up`);
935
+ return false;
936
+ }
916
937
  pipeline.ciFixes++;
917
- logger.warn(`[${task.id}] CI failed — fix attempt ${pipeline.ciFixes}/${MAX_CI_FIXES}`);
938
+ logger.warn(`[${task.id}] CI failed — delegating fix to agent (attempt ${pipeline.ciFixes}/${MAX_CI_FIXES})`);
918
939
  const logs = fetchFailureLogs(branch, platform === 'github' ? 'github' : 'gitlab', projectDir);
919
- if (logs) {
920
- const fixResult = await spawnAgent(pool, pipeline.workerId, {
921
- agent: pipeline.assignedAgent ?? undefined,
922
- cwd: worktreePath,
923
- prompt: buildCIFixPrompt({ task, worktreePath, projectDir }, logs),
924
- model: getAgentModel(pipeline.assignedAgent, agents, task),
925
- }, state, task.id, logger, onMessage, onSpawnStart, onSpawnEnd);
926
- if (fixResult.success) {
927
- commitInWorktree(worktreePath, `fix: CI failure for ${task.title}`);
940
+ const fixResult = await spawnAgent(pool, pipeline.workerId, {
941
+ agent: pipeline.assignedAgent ?? undefined,
942
+ cwd: worktreePath,
943
+ prompt: buildCIFixPrompt({ task, worktreePath, projectDir }, logs ?? 'No logs available — check the CI pipeline manually'),
944
+ model: getAgentModel(pipeline.assignedAgent, agents, task),
945
+ }, state, task.id, logger, onMessage, onSpawnStart, onSpawnEnd);
946
+ if (fixResult.success) {
947
+ const sha = commitInWorktree(worktreePath, `fix: CI failure for ${task.title}`);
948
+ if (sha) {
928
949
  forcePushWorktree(worktreePath);
950
+ logger.info(`[${task.id}] Fix pushed — polling for new CI pipeline`);
951
+ // Poll until CI status changes from 'failed' (= new pipeline picked up)
952
+ await waitForCIRefresh(task.id, projectDir, platform, branch, logger);
929
953
  continue;
930
954
  }
931
955
  }
932
- if (pipeline.ciFixes >= MAX_CI_FIXES) {
933
- logger.error(`[${task.id}] CI fix limit (${MAX_CI_FIXES}) reached`);
934
- return false;
935
- }
956
+ // Fix didn't produce changes — poll and let next iteration re-evaluate
957
+ await sleep(PR_POLL_INTERVAL);
958
+ continue;
936
959
  }
937
960
  // Unresolved PR comments — spawn agent to address
938
961
  const comments = getPRComments(projectDir, platform, prStatus.number);
939
962
  const unresolved = comments.filter(c => !c.resolved);
940
963
  if (unresolved.length > 0) {
941
- logger.info(`[${task.id}] ${unresolved.length} unresolved PR comments — addressing`);
964
+ logger.info(`[${task.id}] ${unresolved.length} unresolved PR comments — delegating to agent`);
942
965
  const commentText = unresolved
943
966
  .map(c => `${c.path ?? 'general'}${c.line ? `:${c.line}` : ''} — ${c.author}: ${c.body}`)
944
967
  .join('\n\n');
@@ -949,25 +972,14 @@ async function pollAndMergePR(task, pipeline, branch, platform, projectDir, work
949
972
  model: getAgentModel(pipeline.assignedAgent, agents, task),
950
973
  }, state, task.id, logger, onMessage, onSpawnStart, onSpawnEnd);
951
974
  if (commentResult.success) {
952
- commitInWorktree(worktreePath, `fix: address PR review comments`);
953
- forcePushWorktree(worktreePath);
954
- appendEvent(projectDir, createEvent('pr_comment_resolved', { taskId: task.id, detail: `${unresolved.length} comments` }));
955
- continue;
975
+ const sha = commitInWorktree(worktreePath, 'fix: address PR review comments');
976
+ if (sha) {
977
+ forcePushWorktree(worktreePath);
978
+ appendEvent(projectDir, createEvent('pr_comment_resolved', { taskId: task.id, detail: `${unresolved.length} comments` }));
979
+ await waitForCIRefresh(task.id, projectDir, platform, branch, logger);
980
+ continue;
981
+ }
956
982
  }
957
- }
958
- // Ready to merge
959
- if (prStatus.mergeable) {
960
- const merged = mergePR(projectDir, platform, prStatus.number);
961
- return merged;
962
- }
963
- // CI pending or waiting for approval — keep polling
964
- if (prStatus.ciStatus === 'pending' || prStatus.ciStatus === 'not-found') {
965
- await sleep(PR_POLL_INTERVAL);
966
- continue;
967
- }
968
- // CI passed but not mergeable (needs approval?) — wait
969
- if (prStatus.ciStatus === 'passed' && !prStatus.mergeable) {
970
- logger.info(`[${task.id}] CI passed but not mergeable (waiting for approval?)`);
971
983
  await sleep(PR_POLL_INTERVAL);
972
984
  continue;
973
985
  }
@@ -976,6 +988,24 @@ async function pollAndMergePR(task, pipeline, branch, platform, projectDir, work
976
988
  logger.warn(`[${task.id}] PR poll timeout (${PR_MAX_POLL_TIME / 60_000}min)`);
977
989
  return false;
978
990
  }
991
+ /** Poll until CI status is no longer the previous 'failed' (= new pipeline started) */
992
+ async function waitForCIRefresh(taskId, projectDir, platform, branch, logger) {
993
+ const maxWait = 5 * 60_000; // 5 min max to wait for new pipeline
994
+ const start = Date.now();
995
+ while (Date.now() - start < maxWait) {
996
+ await sleep(PR_POLL_INTERVAL);
997
+ try {
998
+ const status = getPRStatus(projectDir, platform, branch);
999
+ if (status.ciStatus !== 'failed') {
1000
+ logger.info(`[${taskId}] New CI pipeline detected: ${status.ciStatus}`);
1001
+ return;
1002
+ }
1003
+ logger.info(`[${taskId}] CI still shows previous failure — polling...`);
1004
+ }
1005
+ catch { /* ignore */ }
1006
+ }
1007
+ logger.warn(`[${taskId}] Timed out waiting for new CI pipeline`);
1008
+ }
979
1009
  function buildPRBody(task, pipeline) {
980
1010
  const lines = [
981
1011
  `## Summary`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-claude-workspace",
3
- "version": "2.3.14",
3
+ "version": "2.3.16",
4
4
  "author": "",
5
5
  "repository": {
6
6
  "type": "git",