claude-task-worker 0.105.0 → 0.107.0

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.
Files changed (3) hide show
  1. package/README.md +2 -1
  2. package/dist/index.js +115 -48
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -105,7 +105,8 @@ claude-task-worker init --force # 強制上書き
105
105
 
106
106
  | ラベル | 用途 |
107
107
  |---|---|
108
- | `cc-triage-scope` | トリアージ対象マーク(Issue/PR) |
108
+ | `cc-triage-scope` | トリアージ対象マーク(Issue/PR)=ワーカーのキュー合流口 |
109
+ | `cc-issue-request` | 人が Issue テンプレートから作成を依頼した印。起票者を assignee に自動設定するワークフローの発火条件(`cc-triage-scope` と役割を分けてあり、ワーカーの自動起票では付かない) |
109
110
  | `cc-issue-created` | `create-issue` 由来の Issue マーク |
110
111
  | `cc-update-issue` / `cc-answer-issue-questions` / `cc-exec-issue` | Issue の更新 / 確認事項回答 / 実行トリガー |
111
112
  | `cc-fix-onetime` / `cc-resolve-conflict` | PR の修正 / コンフリクト解消トリガー |
package/dist/index.js CHANGED
@@ -1917,9 +1917,8 @@ var SCHEDULED_WORKER_NAMES = [
1917
1917
  "update-design-md"
1918
1918
  ];
1919
1919
  var CLOUD_DONE_LABEL = "cc-cloud-done";
1920
- var CLOUD_ALLOWED_WORKERS = ["exec-issue", "fix-review-point"];
1921
- function isCloudWorker(name) {
1922
- return hasCloudFlag() && CLOUD_ALLOWED_WORKERS.includes(name);
1920
+ function isCloudWorker(_name) {
1921
+ return hasCloudFlag();
1923
1922
  }
1924
1923
  function checkCloudAuth(input) {
1925
1924
  if (input.status.kind === "unknown") return [];
@@ -2594,14 +2593,14 @@ function appendCloudDoneInstruction(prompt, target) {
2594
2593
  const labelInstruction = `\u4E0A\u8A18\u30B3\u30E1\u30F3\u30C8\u306E\u6295\u7A3F\u5F8C\u3001\u3053\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u6700\u5F8C\u306E\u64CD\u4F5C\u3068\u3057\u3066 ${targetLabel} \u306B \`${CLOUD_DONE_LABEL}\` \u30E9\u30D9\u30EB\u3092\u4ED8\u4E0E\u3059\u308B\u3053\u3068\u3002GitHub MCP\uFF08\`issue_write\` / method: \`update\`\uFF09\u3092\u512A\u5148\u3057\u3001\u5931\u6557\u3057\u305F\u5834\u5408\u306E\u307F \`gh ${target.type} edit ${target.number} --add-label ${CLOUD_DONE_LABEL}\` \u3078\u30D5\u30A9\u30FC\u30EB\u30D0\u30C3\u30AF\u3059\u308B\u3053\u3068\uFF08\u30D5\u30A9\u30FC\u30EB\u30D0\u30C3\u30AF\u306F1\u56DE\u307E\u3067\uFF09\u3002\u30EF\u30FC\u30AB\u30FC\u306F\u3053\u306E\u30E9\u30D9\u30EB\u3067\u30BF\u30B9\u30AF\u306E\u7D42\u4E86\u3092\u691C\u77E5\u3057\u3066\u304A\u308A\u3001\u4ED8\u4E0E\u3055\u308C\u306A\u3044\u3068\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8\u307E\u3067\u5B8C\u4E86\u6271\u3044\u306B\u306A\u3089\u306A\u3044\u3002`;
2595
2594
  return [prompt, checkoutInstruction, worktreeInstruction, reportInstruction, labelInstruction].filter((part) => part !== "").join("\n\n");
2596
2595
  }
2597
- var CLOUD_WORKTREE_EXEMPT_SKILLS = ["exec-issue", "fix-review-point"];
2596
+ var CLOUD_WORKTREE_EXEMPT_SKILLS = ["exec-issue", "fix-review-point", "create-ui-design"];
2598
2597
  function buildCloudWorktreeInstruction(prompt) {
2599
2598
  const skill = prompt.trim().split(/\s+/)[0] ?? "";
2600
2599
  if (!CLOUD_WORKTREE_EXEMPT_SKILLS.some((name) => skill.endsWith(`:${name}`))) return "";
2601
2600
  return "\u3053\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u30AF\u30E9\u30A6\u30C9\u5B9F\u884C\u306E\u305F\u3081 worktree \u3092\u6301\u305F\u305A\u3001cwd \u306F\u30EA\u30DD\u30B8\u30C8\u30EA\u30EB\u30FC\u30C8\u3067\u3042\u308B\uFF08\u30EF\u30FC\u30AB\u30FC\u306F\u30AF\u30E9\u30A6\u30C9\u5B9F\u884C\u6642\u306B worktree \u3092\u4F5C\u3089\u306A\u3044\uFF09\u3002\u30B9\u30AD\u30EB\u672C\u6587\u306E\u30D5\u30A7\u30FC\u30BA0\u306B\u3042\u308B\u300C`pwd` \u304C `.claude/worktrees/` \u914D\u4E0B\u3067\u306A\u3051\u308C\u3070\u4E2D\u65AD\u3059\u308B\u300D\u78BA\u8A8D\u306F\u3001\u3053\u306E\u6307\u793A\u304C\u3042\u308B\u5834\u5408\u306B\u9650\u308A\u9069\u7528\u3057\u306A\u3044\u3053\u3068\u3002\u305F\u3060\u3057\u30AC\u30FC\u30C9\u306E\u76EE\u7684\u3067\u3042\u308B\u300C\u30C7\u30D5\u30A9\u30EB\u30C8\u30D6\u30E9\u30F3\u30C1\u3067\u4F5C\u696D\u3057\u306A\u3044\u300D\u306F\u7DAD\u6301\u3059\u308B\u3053\u3068 \u2014 \u540C\u3058\u30D5\u30A7\u30FC\u30BA0\u306E\u300C\u30C7\u30D5\u30A9\u30EB\u30C8\u30D6\u30E9\u30F3\u30C1\u540D\u3092\u53D6\u5F97\u3057\u3001\u73FE\u5728\u30D6\u30E9\u30F3\u30C1\u3068\u4E00\u81F4\u3059\u308B\u5834\u5408\u306F\u4E2D\u65AD\u3059\u308B\uFF08\u53D6\u5F97\u5931\u6557\u3082\u4E2D\u65AD\uFF09\u300D\u306F\u5FC5\u305A\u5B9F\u884C\u3057\u3001\u4E00\u81F4\u3057\u305F\u5834\u5408\u306F\u5F93\u6765\u3069\u304A\u308A\u4E2D\u65AD\u3059\u308B\u3053\u3068\u3002";
2602
2601
  }
2603
2602
  function buildCloudCheckoutInstruction(target) {
2604
- if (target.type !== "pr") return "";
2603
+ if (target.type !== "pr" || !target.onBranch) return "";
2605
2604
  return `\u3053\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306F PR #${target.number} \u306E head \u30D6\u30E9\u30F3\u30C1\u4E0A\u3067\u958B\u59CB\u3057\u3066\u3044\u308B\uFF08\u30EF\u30FC\u30AB\u30FC\u304C \`--on-branch\` \u3067\u6307\u5B9A\u6E08\u307F\uFF09\u3002\u30B9\u30AD\u30EB\u672C\u6587\u304C\u6307\u793A\u3059\u308B \`gh pr checkout\` \u306F\u5B9F\u884C\u3057\u306A\u3044\u3053\u3068\uFF08\u30AF\u30E9\u30A6\u30C9\u3067\u306F GraphQL \u30B2\u30FC\u30C8\u306B\u3088\u308A 403 \u3067\u5931\u6557\u3057\u3001\u304B\u3064\u65E2\u306B\u30D6\u30E9\u30F3\u30C1\u4E0A\u306B\u3044\u308B\u306E\u3067\u4E0D\u8981\uFF09\u3002\u30D6\u30E9\u30F3\u30C1\u306E\u78BA\u8A8D\u304C\u8981\u308B\u5834\u5408\u306F \`git rev-parse --abbrev-ref HEAD\` \u3092\u4F7F\u3046\u3053\u3068\u3002`;
2606
2605
  }
2607
2606
  function buildCloudGitHubAccessInstruction() {
@@ -2899,8 +2898,7 @@ async function pollCloudWaiters() {
2899
2898
  const now = Date.now();
2900
2899
  for (const [key, waiter] of [...cloudWaiters.entries()]) {
2901
2900
  const done = doneKeys.get(waiter.type);
2902
- const number = Number(key.split(":")[1]);
2903
- if (done?.has(number)) {
2901
+ if (done?.has(waiter.number)) {
2904
2902
  waiter.settle("completed");
2905
2903
  cloudWaiters.delete(key);
2906
2904
  } else if (now >= waiter.deadline) {
@@ -2915,19 +2913,21 @@ async function pollCloudWaiters() {
2915
2913
  }
2916
2914
  }
2917
2915
  }
2918
- function waitForCloudTask(id, type) {
2916
+ function waitForCloudTask(id, target) {
2919
2917
  return new Promise((resolve3) => {
2920
- cloudWaiters.set(`${type}:${id}`, {
2921
- type,
2918
+ cloudWaiters.set(`${target.type}:${target.number}:${id}`, {
2919
+ type: target.type,
2920
+ number: target.number,
2922
2921
  deadline: Date.now() + CLOUD_TASK_TIMEOUT_MS,
2923
2922
  settle: resolve3
2924
2923
  });
2925
2924
  ensureCloudPollLoop();
2926
2925
  });
2927
2926
  }
2928
- async function flagOrphanedCloudSession(target, id, reason, cloudSessionId) {
2929
- await addLabel(target, id, "cc-need-human-check").catch((err) => {
2930
- console.error(`[worker] failed to add cc-need-human-check to ${target} #${id}: ${err}`);
2927
+ async function flagOrphanedCloudSession(target, reason, cloudSessionId) {
2928
+ const { type, number: id } = target;
2929
+ await addLabel(type, id, "cc-need-human-check").catch((err) => {
2930
+ console.error(`[worker] failed to add cc-need-human-check to ${type} #${id}: ${err}`);
2931
2931
  });
2932
2932
  const causeLine = reason === "session-id" ? "\u30BB\u30C3\u30B7\u30E7\u30F3ID\u306E\u62BD\u51FA\u306B\u5931\u6557\u3057\u3066\u5F85\u6A5F\u3092\u6253\u3061\u5207\u308A\u307E\u3057\u305F\u3002\u30D7\u30ED\u30F3\u30D7\u30C8\u306F\u6295\u5165\u6E08\u307F\u3067\u3001\u30AF\u30E9\u30A6\u30C9\u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u72EC\u7ACB\u3057\u3066\u7A3C\u50CD\u3057\u3066\u3044\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002" : "\u30EF\u30FC\u30AB\u30FC\u306E\u30B7\u30E3\u30C3\u30C8\u30C0\u30A6\u30F3\u3067\u5F85\u6A5F\u3092\u6253\u3061\u5207\u308A\u307E\u3057\u305F\u3002\u30AF\u30E9\u30A6\u30C9\u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u7D99\u7D9A\u3057\u3066\u3044\u308B\u53EF\u80FD\u6027\u304C\u9AD8\u3044\u3067\u3059\u3002";
2933
2933
  const sessionLine = cloudSessionId ? `https://claude.ai/code/${cloudSessionId}` : "\u30BB\u30C3\u30B7\u30E7\u30F3URL\u4E0D\u660E\uFF08ID\u62BD\u51FA\u306B\u5931\u6557\uFF09";
@@ -2938,9 +2938,9 @@ async function flagOrphanedCloudSession(target, id, reason, cloudSessionId) {
2938
2938
  **\u30BB\u30C3\u30B7\u30E7\u30F3URL**: ${sessionLine}
2939
2939
 
2940
2940
  **\u518D\u958B\u65B9\u6CD5**: \u5B64\u7ACB\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u6210\u679C\u7269\u304C\u5C4A\u3044\u3066\u3044\u306A\u3044\u304B\u78BA\u8A8D\u3057\u305F\u3046\u3048\u3067\u3001\`cc-need-human-check\` \u30E9\u30D9\u30EB\u3092\u5916\u3059\u3068\u30DD\u30FC\u30EA\u30F3\u30B0\u5BFE\u8C61\u306B\u623B\u308A\u307E\u3059\u3002`;
2941
- const commentFn = target === "issue" ? commentOnIssue : commentOnPR;
2941
+ const commentFn = type === "issue" ? commentOnIssue : commentOnPR;
2942
2942
  await commentFn(id, body).catch((err) => {
2943
- console.error(`[worker] failed to comment on ${target} #${id} about the orphaned cloud session: ${err}`);
2943
+ console.error(`[worker] failed to comment on ${type} #${id} about the orphaned cloud session: ${err}`);
2944
2944
  });
2945
2945
  }
2946
2946
  async function createCloudSession(args, initialPrompt, cwd, env) {
@@ -2992,11 +2992,7 @@ async function createCloudSession(args, initialPrompt, cwd, env) {
2992
2992
  }
2993
2993
  async function runViaCloud(args, prompt, id, onComplete, cwd, env, cloudTarget, model) {
2994
2994
  herdrTasks.set(id, { paneId: "", tabId: "" });
2995
- const initialPrompt = buildCloudPrompt(
2996
- prompt,
2997
- model ?? "",
2998
- cloudTarget ? { type: cloudTarget, number: id } : void 0
2999
- );
2995
+ const initialPrompt = buildCloudPrompt(prompt, model ?? "", cloudTarget);
3000
2996
  let result;
3001
2997
  let cloudSessionId;
3002
2998
  try {
@@ -3007,17 +3003,20 @@ async function runViaCloud(args, prompt, id, onComplete, cwd, env, cloudTarget,
3007
3003
  result = { status: "completed", output: createOutput };
3008
3004
  } else {
3009
3005
  const outcome = await waitForCloudTask(id, cloudTarget);
3006
+ const { type: targetType, number: targetNumber } = cloudTarget;
3010
3007
  if (outcome === "completed") {
3011
- await removeLabel(cloudTarget, id, CLOUD_DONE_LABEL).catch((err) => {
3012
- console.error(`[worker] failed to remove ${CLOUD_DONE_LABEL} from ${cloudTarget} #${id}: ${err}`);
3008
+ await removeLabel(targetType, targetNumber, CLOUD_DONE_LABEL).catch((err) => {
3009
+ console.error(`[worker] failed to remove ${CLOUD_DONE_LABEL} from ${targetType} #${targetNumber}: ${err}`);
3013
3010
  });
3014
3011
  let reportBody = null;
3015
3012
  const startedAt = tasks.get(id)?.startedAt;
3016
3013
  if (startedAt) {
3017
3014
  try {
3018
- reportBody = await findCommentSince(id, startedAt, CLOUD_REPORT_HEADING);
3015
+ reportBody = await findCommentSince(targetNumber, startedAt, CLOUD_REPORT_HEADING);
3019
3016
  } catch (err) {
3020
- console.error(`[worker] failed to fetch the cloud report comment for ${cloudTarget} #${id}: ${err}`);
3017
+ console.error(
3018
+ `[worker] failed to fetch the cloud report comment for ${targetType} #${targetNumber}: ${err}`
3019
+ );
3021
3020
  }
3022
3021
  }
3023
3022
  result = {
@@ -3026,8 +3025,8 @@ async function runViaCloud(args, prompt, id, onComplete, cwd, env, cloudTarget,
3026
3025
  [worker] detected completion via the ${CLOUD_DONE_LABEL} label`
3027
3026
  };
3028
3027
  } else if (outcome === "timeout") {
3029
- await addLabel(cloudTarget, id, "cc-need-human-check").catch((err) => {
3030
- console.error(`[worker] failed to add cc-need-human-check to ${cloudTarget} #${id}: ${err}`);
3028
+ await addLabel(targetType, targetNumber, "cc-need-human-check").catch((err) => {
3029
+ console.error(`[worker] failed to add cc-need-human-check to ${targetType} #${targetNumber}: ${err}`);
3031
3030
  });
3032
3031
  result = {
3033
3032
  status: "failed",
@@ -3035,7 +3034,7 @@ async function runViaCloud(args, prompt, id, onComplete, cwd, env, cloudTarget,
3035
3034
  [worker] timed out waiting for the ${CLOUD_DONE_LABEL} label after ${CLOUD_TASK_TIMEOUT_MS / 1e3 / 60} minutes. Possible causes: the session stopped on AskUserQuestion, the cloud VM crashed, the plugin was not installed, or label assignment itself failed.`
3036
3035
  };
3037
3036
  } else {
3038
- await flagOrphanedCloudSession(cloudTarget, id, "shutdown", cloudSessionId);
3037
+ await flagOrphanedCloudSession(cloudTarget, "shutdown", cloudSessionId);
3039
3038
  result = {
3040
3039
  status: "failed",
3041
3040
  output: `${createOutput}
@@ -3049,7 +3048,7 @@ async function runViaCloud(args, prompt, id, onComplete, cwd, env, cloudTarget,
3049
3048
  let orphanNote = "[worker] note: with the 1-command launch, the cloud session may already have started working independently even though this task is being reported as failed locally (orphaned session).";
3050
3049
  if (cloudTarget) {
3051
3050
  const reason = herdrAbortSignal.aborted ? "shutdown" : "session-id";
3052
- await flagOrphanedCloudSession(cloudTarget, id, reason, cloudSessionId);
3051
+ await flagOrphanedCloudSession(cloudTarget, reason, cloudSessionId);
3053
3052
  orphanNote += " added cc-need-human-check so a human can verify whether it completed on its own.";
3054
3053
  }
3055
3054
  result = {
@@ -3985,7 +3984,7 @@ function createIssuePollingWorker(config) {
3985
3984
  buildClaudeEnv(mode, cloud),
3986
3985
  execution.prompt,
3987
3986
  cloud,
3988
- cloud ? "issue" : void 0,
3987
+ cloud ? { type: "issue", number: issue.number } : void 0,
3989
3988
  model
3990
3989
  );
3991
3990
  } catch (err) {
@@ -4242,7 +4241,7 @@ function createPrPollingWorker(config) {
4242
4241
  buildClaudeEnv(mode, isCloud),
4243
4242
  execution.prompt,
4244
4243
  isCloud,
4245
- isCloud ? "pr" : void 0,
4244
+ isCloud ? { type: "pr", number: pr.number, onBranch: true } : void 0,
4246
4245
  model
4247
4246
  );
4248
4247
  } catch (err) {
@@ -4715,7 +4714,7 @@ async function publishLastRunPr(workerName, defaultBranch, at) {
4715
4714
  writeLastRun(cwd, workerName, at);
4716
4715
  if (!hasLastRunChange(await git(cwd, ["status", "--porcelain", CONFIG_FILE]))) {
4717
4716
  console.log(`[${workerName}] lastRun unchanged, skipping PR`);
4718
- return;
4717
+ return null;
4719
4718
  }
4720
4719
  await git(cwd, ["add", CONFIG_FILE]);
4721
4720
  await git(cwd, ["commit", "-m", lastRunPrTitle(workerName)]);
@@ -4723,7 +4722,7 @@ async function publishLastRunPr(workerName, defaultBranch, at) {
4723
4722
  const existing = await findOpenPrNumberByHeadRef(branch);
4724
4723
  if (existing !== null) {
4725
4724
  console.log(`[${workerName}] updated lastRun PR #${existing}`);
4726
- return;
4725
+ return existing;
4727
4726
  }
4728
4727
  const prNumber = await createPullRequest(
4729
4728
  defaultBranch,
@@ -4733,6 +4732,7 @@ async function publishLastRunPr(workerName, defaultBranch, at) {
4733
4732
  { labels: [LABEL_TRIAGE_SCOPE2], assignee: await getCurrentUser() }
4734
4733
  );
4735
4734
  console.log(`[${workerName}] opened lastRun PR #${prNumber}`);
4735
+ return prNumber;
4736
4736
  } finally {
4737
4737
  await removeWorktree(branch).catch((err) => console.error(`[${workerName}] removeWorktree failed: ${err}`));
4738
4738
  }
@@ -4742,6 +4742,7 @@ async function publishLastRunPr(workerName, defaultBranch, at) {
4742
4742
  var SCHEDULE_INTERVAL_HOURS = 24;
4743
4743
  var SCHEDULE_INTERVAL_MS = SCHEDULE_INTERVAL_HOURS * 60 * 60 * 1e3;
4744
4744
  var SCOPE_DAYS = SCHEDULE_INTERVAL_HOURS / 24;
4745
+ var LABEL_IN_PROGRESS2 = "cc-in-progress";
4745
4746
  function createScheduledWorker(config) {
4746
4747
  return async () => {
4747
4748
  const { owner, name: repoName, defaultBranch } = await getRepoInfo();
@@ -4775,9 +4776,23 @@ function createScheduledWorker(config) {
4775
4776
  permissionMode: getPermissionMode(),
4776
4777
  ...cloud ? { cloud: true, baseRef: defaultBranch, remoteEnvId: getRemoteEnvId() ?? "" } : {}
4777
4778
  });
4778
- await publishLastRunPr(config.name, defaultBranch, new Date(now)).catch(
4779
- (err) => console.error(`[${config.name}] publishLastRunPr failed: ${err}`)
4780
- );
4779
+ const lastRunPr = await publishLastRunPr(config.name, defaultBranch, new Date(now)).catch((err) => {
4780
+ console.error(`[${config.name}] publishLastRunPr failed: ${err}`);
4781
+ return null;
4782
+ });
4783
+ if (cloud && lastRunPr === null) {
4784
+ console.warn(
4785
+ `[${config.name}] no lastRun PR to carry the cc-cloud-done label; the cloud session will be reported as completed as soon as it is created`
4786
+ );
4787
+ }
4788
+ if (cloud && lastRunPr !== null) {
4789
+ await removeLabel("pr", lastRunPr, CLOUD_DONE_LABEL).catch(
4790
+ (err) => console.error(`[${config.name}] removeLabel ${CLOUD_DONE_LABEL} failed for PR #${lastRunPr}: ${err}`)
4791
+ );
4792
+ await addLabel("pr", lastRunPr, LABEL_IN_PROGRESS2).catch(
4793
+ (err) => console.error(`[${config.name}] addLabel ${LABEL_IN_PROGRESS2} failed for PR #${lastRunPr}: ${err}`)
4794
+ );
4795
+ }
4781
4796
  let cwd;
4782
4797
  if (cloud) {
4783
4798
  console.log(`[${config.name}] cloud execution, running without worktree on ${defaultBranch}`);
@@ -4804,6 +4819,13 @@ function createScheduledWorker(config) {
4804
4819
  } catch (err) {
4805
4820
  console.error(`[${config.name}] post-task error: ${err}`);
4806
4821
  } finally {
4822
+ if (cloud && lastRunPr !== null) {
4823
+ await removeLabel("pr", lastRunPr, LABEL_IN_PROGRESS2).catch(
4824
+ (err) => console.error(
4825
+ `[${config.name}] removeLabel ${LABEL_IN_PROGRESS2} failed for PR #${lastRunPr}: ${err}`
4826
+ )
4827
+ );
4828
+ }
4807
4829
  if (!cloud) {
4808
4830
  await removeWorktree(worktreeId).catch(
4809
4831
  (err) => console.error(`[${config.name}] removeWorktree failed: ${err}`)
@@ -4815,7 +4837,7 @@ function createScheduledWorker(config) {
4815
4837
  buildClaudeEnv(mode, cloud),
4816
4838
  execution.prompt,
4817
4839
  cloud,
4818
- void 0,
4840
+ cloud && lastRunPr !== null ? { type: "pr", number: lastRunPr } : void 0,
4819
4841
  model
4820
4842
  );
4821
4843
  } catch (err) {
@@ -4861,7 +4883,7 @@ var updateDesignMdWorker = createScheduledWorker({
4861
4883
  init_table();
4862
4884
 
4863
4885
  // src/commands/init.ts
4864
- import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2, access } from "node:fs/promises";
4886
+ import { mkdir as mkdir2, readFile as readFile2, rm as rm2, writeFile as writeFile2, access } from "node:fs/promises";
4865
4887
  import { basename as basename3 } from "node:path";
4866
4888
 
4867
4889
  // src/commands/codegraph.ts
@@ -4984,14 +5006,20 @@ var LABELS = [
4984
5006
  // vivid bronze (H46 S100 L29 / L*50 C*56)
4985
5007
  { name: "cc-ui-design-ready", color: "0c73e9" },
4986
5008
  // vivid azure (H212 S90 L48 / L*50 C*69)
4987
- { name: CLOUD_DONE_LABEL, color: "33cfff" }
5009
+ { name: CLOUD_DONE_LABEL, color: "33cfff" },
4988
5010
  // vivid sky blue (H194 S100 L60 / L*78 C*42)
5011
+ // 追加時点で有彩色ラベルが色相環をほぼ埋めており、上記6点を全て満たす色は残っていない。
5012
+ // 最寄り色相との差は27°が上限(H185 が最大)で、その相手は cc-cloud-done(クラウド実行中だけ
5013
+ // 現れる短命なマーカー・L*78 と明度が倍近く違う)=見分けたい相手ではない側に倒してある。
5014
+ { name: "cc-issue-request", color: "03656d" }
5015
+ // vivid deep teal (H185 S95 L22 / L*39 C*24)
4989
5016
  ];
4990
5017
  var ISSUE_TEMPLATE = `name: "[claude-task-worker] Issue\u4F5C\u6210\u4F9D\u983C"
4991
5018
  description: claude-task-worker\u3067GitHub Issue\u3092\u4F5C\u6210\u3059\u308B
4992
5019
  title: "[claude-task-worker] Issue\u4F5C\u6210\u4F9D\u983C"
4993
5020
  labels:
4994
5021
  - cc-triage-scope
5022
+ - cc-issue-request
4995
5023
  body:
4996
5024
  - type: textarea
4997
5025
  id: request
@@ -5001,7 +5029,7 @@ body:
5001
5029
  validations:
5002
5030
  required: true
5003
5031
  `;
5004
- var ASSIGN_CREATOR_WORKFLOW = `name: Assign creator on cc-triage-scope
5032
+ var ASSIGN_CREATOR_WORKFLOW = `name: Assign creator on issue request
5005
5033
 
5006
5034
  on:
5007
5035
  issues:
@@ -5009,7 +5037,7 @@ on:
5009
5037
 
5010
5038
  jobs:
5011
5039
  assign:
5012
- if: contains(github.event.issue.labels.*.name, 'cc-triage-scope')
5040
+ if: contains(github.event.issue.labels.*.name, 'cc-issue-request')
5013
5041
  runs-on: ubuntu-latest
5014
5042
  permissions:
5015
5043
  issues: write
@@ -5067,6 +5095,25 @@ async function ensureLocalConfigGitIgnore() {
5067
5095
  await writeFile2(path2, next, "utf-8");
5068
5096
  console.log(`[init] Added ${entry} to ${path2}`);
5069
5097
  }
5098
+ var LEGACY_PATHS = [
5099
+ ".github/ISSUE_TEMPLATE/cc-triage-scope.yml",
5100
+ ".github/workflows/assign-creator-on-cc-triage-scope.yml"
5101
+ ];
5102
+ function isContentMismatch(result, expected, actual) {
5103
+ return result === "skipped" && actual !== expected;
5104
+ }
5105
+ async function removeLegacyIssueRequestFiles() {
5106
+ for (const path2 of LEGACY_PATHS) {
5107
+ try {
5108
+ await rm2(path2);
5109
+ console.log(`[init] Removed legacy file: ${path2}`);
5110
+ } catch (err) {
5111
+ if (err.code !== "ENOENT") {
5112
+ throw err;
5113
+ }
5114
+ }
5115
+ }
5116
+ }
5070
5117
  async function init(options = {}) {
5071
5118
  const force = options.force ?? false;
5072
5119
  console.log(`[init] Creating labels...${force ? " (force mode)" : ""}`);
@@ -5080,12 +5127,25 @@ async function init(options = {}) {
5080
5127
  }
5081
5128
  console.log("[init] Creating issue template...");
5082
5129
  await mkdir2(".github/ISSUE_TEMPLATE", { recursive: true });
5083
- const templatePath = ".github/ISSUE_TEMPLATE/cc-triage-scope.yml";
5084
- logWriteResult(await writeFileWithMode(templatePath, ISSUE_TEMPLATE, force), templatePath);
5130
+ const templatePath = ".github/ISSUE_TEMPLATE/cc-issue-request.yml";
5131
+ const templateResult = await writeFileWithMode(templatePath, ISSUE_TEMPLATE, force);
5132
+ logWriteResult(templateResult, templatePath);
5085
5133
  console.log("[init] Creating GitHub Actions workflow...");
5086
5134
  await mkdir2(".github/workflows", { recursive: true });
5087
- const workflowPath = ".github/workflows/assign-creator-on-cc-triage-scope.yml";
5088
- logWriteResult(await writeFileWithMode(workflowPath, ASSIGN_CREATOR_WORKFLOW, force), workflowPath);
5135
+ const workflowPath = ".github/workflows/assign-creator-on-issue-request.yml";
5136
+ const workflowResult = await writeFileWithMode(workflowPath, ASSIGN_CREATOR_WORKFLOW, force);
5137
+ logWriteResult(workflowResult, workflowPath);
5138
+ if (isContentMismatch(templateResult, ISSUE_TEMPLATE, await readFile2(templatePath, "utf-8"))) {
5139
+ throw new Error(
5140
+ `[init] ${templatePath} \u306F\u65E2\u5B58\u306E\u5185\u5BB9\u304C\u6700\u65B0\u306E\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u3068\u4E00\u81F4\u3057\u307E\u305B\u3093\u3002--force \u3067\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u65E7\u30D5\u30A1\u30A4\u30EB\u306F\u524A\u9664\u3057\u3066\u3044\u307E\u305B\u3093\u3002`
5141
+ );
5142
+ }
5143
+ if (isContentMismatch(workflowResult, ASSIGN_CREATOR_WORKFLOW, await readFile2(workflowPath, "utf-8"))) {
5144
+ throw new Error(
5145
+ `[init] ${workflowPath} \u306F\u65E2\u5B58\u306E\u5185\u5BB9\u304C\u6700\u65B0\u306E\u30EF\u30FC\u30AF\u30D5\u30ED\u30FC\u3068\u4E00\u81F4\u3057\u307E\u305B\u3093\u3002--force \u3067\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u65E7\u30D5\u30A1\u30A4\u30EB\u306F\u524A\u9664\u3057\u3066\u3044\u307E\u305B\u3093\u3002`
5146
+ );
5147
+ }
5148
+ await removeLegacyIssueRequestFiles();
5089
5149
  console.log("[init] Creating config file...");
5090
5150
  await createConfig(force);
5091
5151
  await ensureLocalConfigGitIgnore();
@@ -5259,6 +5319,9 @@ var CLOUD_SETTINGS_DEFAULTS = {
5259
5319
  outputStyle: "Proactive",
5260
5320
  language: "Japanese"
5261
5321
  };
5322
+ var CLOUD_SETTINGS_ENV = {
5323
+ CLAUDE_CODE_DISABLE_BACKGROUND_TASKS: "1"
5324
+ };
5262
5325
  function claudeSettingsPath() {
5263
5326
  const dir = process.env.CLAUDE_CONFIG_DIR;
5264
5327
  return join8(dir && dir.length > 0 ? dir : join8(homedir6(), ".claude"), "settings.json");
@@ -5274,6 +5337,11 @@ function withCloudDefaults(existing, force) {
5274
5337
  throw new Error("`permissions` is not an object");
5275
5338
  }
5276
5339
  const permissions = { ...current };
5340
+ const currentEnv = settings["env"] ?? {};
5341
+ if (typeof currentEnv !== "object" || currentEnv === null || Array.isArray(currentEnv)) {
5342
+ throw new Error("`env` is not an object");
5343
+ }
5344
+ const env = { ...currentEnv };
5277
5345
  let changed = false;
5278
5346
  const set = (target, key, value) => {
5279
5347
  if (key in target && !force) return;
@@ -5283,8 +5351,9 @@ function withCloudDefaults(existing, force) {
5283
5351
  };
5284
5352
  set(permissions, "defaultMode", CLOUD_DEFAULT_PERMISSION_MODE);
5285
5353
  for (const [key, value] of Object.entries(CLOUD_SETTINGS_DEFAULTS)) set(settings, key, value);
5354
+ for (const [key, value] of Object.entries(CLOUD_SETTINGS_ENV)) set(env, key, value);
5286
5355
  if (!changed) return null;
5287
- return `${JSON.stringify({ ...settings, permissions }, null, 2)}
5356
+ return `${JSON.stringify({ ...settings, permissions, env }, null, 2)}
5288
5357
  `;
5289
5358
  }
5290
5359
  async function writeClaudeSettings(force) {
@@ -5612,9 +5681,7 @@ async function assertCloudAvailable() {
5612
5681
  process.exit(1);
5613
5682
  }
5614
5683
  if (cloud) {
5615
- console.log(
5616
- `[worker] cloud execution enabled (--cloud); only these workers run in the cloud: ${CLOUD_ALLOWED_WORKERS.join(", ")} (all others stay local)`
5617
- );
5684
+ console.log("[worker] cloud execution enabled (--cloud); every worker started by this process runs in the cloud");
5618
5685
  }
5619
5686
  }
5620
5687
  async function assertRunPrerequisites() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-task-worker",
3
- "version": "0.105.0",
3
+ "version": "0.107.0",
4
4
  "description": "CLI tool that polls GitHub Issues/PRs and delegates work to Claude CLI",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",