claude-task-worker 0.111.0 → 0.113.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 (2) hide show
  1. package/dist/index.js +72 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1486,6 +1486,27 @@ async function fetchPrRef(owner, name, prNumber) {
1486
1486
  return null;
1487
1487
  }
1488
1488
  }
1489
+ async function getPrDetail(prNumber) {
1490
+ const { owner, name } = await getRepoInfo();
1491
+ return fetchPrRef(owner, name, prNumber);
1492
+ }
1493
+ async function closeIssue(issueNumber, reason = "completed") {
1494
+ const { owner, name } = await getRepoInfo();
1495
+ await execGh([
1496
+ "api",
1497
+ "-X",
1498
+ "PATCH",
1499
+ `repos/${owner}/${name}/issues/${issueNumber}`,
1500
+ "-f",
1501
+ "state=closed",
1502
+ "-f",
1503
+ `state_reason=${reason}`
1504
+ ]);
1505
+ }
1506
+ function parseClosingIssueNumbers(body) {
1507
+ const pattern = /\b(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s*:?\s*#(\d+)\b(?!\d)/gi;
1508
+ return [...new Set([...body.matchAll(pattern)].map((m) => Number(m[1])))];
1509
+ }
1489
1510
  function bodyClosesIssue(body, issueNumber) {
1490
1511
  const pattern = new RegExp(`\\b(close[sd]?|fix(?:e[sd])?|resolve[sd]?)\\s*:?\\s*#${issueNumber}\\b(?!\\d)`, "i");
1491
1512
  return pattern.test(body);
@@ -4389,11 +4410,27 @@ var triageCreatedIssueWorker = (opts = {}) => createIssuePollingWorker({
4389
4410
  })();
4390
4411
 
4391
4412
  // src/workers/triage-pr.ts
4413
+ function shouldCloseLinkedIssues(pr, defaultBranch) {
4414
+ return pr !== null && pr.state === "MERGED" && pr.baseRefName !== defaultBranch;
4415
+ }
4392
4416
  var triagePrWorker = createPrPollingWorker({
4393
4417
  name: "triage-pr",
4394
4418
  command: "/claude-task-worker:triage-pr",
4395
4419
  triggerLabel: "cc-triage-scope",
4396
- excludeLabels: ["cc-fix-onetime", "cc-resolve-conflict", "cc-release-ready", "cc-need-human-check"]
4420
+ excludeLabels: ["cc-fix-onetime", "cc-resolve-conflict", "cc-release-ready", "cc-need-human-check"],
4421
+ onCompleted: async (pr) => {
4422
+ const detail = await getPrDetail(pr.number);
4423
+ const { defaultBranch } = await getRepoInfo();
4424
+ if (!shouldCloseLinkedIssues(detail, defaultBranch)) return;
4425
+ for (const issueNumber of parseClosingIssueNumbers(detail.body)) {
4426
+ try {
4427
+ await closeIssue(issueNumber);
4428
+ console.log(`[triage-pr] closed issue #${issueNumber} (PR #${pr.number} merged into ${detail.baseRefName})`);
4429
+ } catch (err) {
4430
+ console.error(`[triage-pr] failed to close issue #${issueNumber} for PR #${pr.number}: ${err}`);
4431
+ }
4432
+ }
4433
+ }
4397
4434
  });
4398
4435
 
4399
4436
  // src/workers/resolve-conflict.ts
@@ -4503,6 +4540,9 @@ function extractDesignFilePath(body) {
4503
4540
  if (path2.length === 0 || path2.includes("<") || path2.includes(">") || !path2.endsWith(".pen")) return null;
4504
4541
  return path2;
4505
4542
  }
4543
+ function shouldVerifyDesignFileExists(cloud) {
4544
+ return !cloud;
4545
+ }
4506
4546
  function classifyDesignPr(pr) {
4507
4547
  if (pr === null) return "needs-human";
4508
4548
  if (pr.state === "MERGED" || pr.mergedAt !== null) return "proceed";
@@ -4537,10 +4577,10 @@ function designPrNotCreatedComment(issueNumber) {
4537
4577
  "- \u30C7\u30B6\u30A4\u30F3\u3092\u8AE6\u3081\u3066\u305D\u306E\u307E\u307E\u5B9F\u88C5\u3078\u9032\u3081\u308B\u5834\u5408: `cc-need-human-check` \u30E9\u30D9\u30EB\u3092\u5916\u3057\u3001`cc-exec-issue` \u30E9\u30D9\u30EB\u306E\u307F\u4ED8\u3051\u3066\u304F\u3060\u3055\u3044"
4538
4578
  ].join("\n");
4539
4579
  }
4540
- function designReferenceMissingComment(issueNumber) {
4580
+ function designReferenceFailureComment(heading, cause) {
4541
4581
  return [
4542
- "## \u30C7\u30B6\u30A4\u30F3\u53C2\u7167\u306E\u66F8\u304D\u623B\u3057\u3092\u78BA\u8A8D\u3067\u304D\u307E\u305B\u3093\uFF08\u8981\u4EBA\u624B\u78BA\u8A8D\uFF09",
4543
- `apply-ui-design \u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u6B63\u5E38\u7D42\u4E86\uFF08exit 0\uFF09\u3057\u307E\u3057\u305F\u304C\u3001Issue #${issueNumber} \u306E description \u306B \`${DESIGN_REFERENCE_HEADING}\` \u30BB\u30AF\u30B7\u30E7\u30F3\uFF08\`.pen\` \u306E\u30D1\u30B9\u3092\u542B\u3080\uFF09\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002`,
4582
+ heading,
4583
+ cause,
4544
4584
  "",
4545
4585
  "## \u306A\u305C\u6B62\u3081\u3066\u3044\u308B\u304B",
4546
4586
  "- \u30C7\u30B6\u30A4\u30F3\u53C2\u7167\u304C description \u306B\u7121\u3044\u3068\u3001`exec-issue` \u306F\u30C7\u30B6\u30A4\u30F3\u3092\u5165\u529B\u306B\u3067\u304D\u305A\u3001\u5408\u610F\u6E08\u307F\u306E\u30C7\u30B6\u30A4\u30F3\u3068\u7121\u95A2\u4FC2\u306A\u5B9F\u88C5\u306B\u306A\u308A\u307E\u3059",
@@ -4550,6 +4590,18 @@ function designReferenceMissingComment(issueNumber) {
4550
4590
  "- \u624B\u52D5\u3067 description \u306B\u53C2\u7167\u3092\u8FFD\u8A18\u3057\u305F\u5834\u5408: `cc-need-human-check` \u30E9\u30D9\u30EB\u3092\u5916\u3057\u3001`cc-ui-design-ready` \u3068 `cc-exec-issue` \u30E9\u30D9\u30EB\u3092\u4ED8\u3051\u3066\u304F\u3060\u3055\u3044"
4551
4591
  ].join("\n");
4552
4592
  }
4593
+ function designReferenceMissingComment(issueNumber) {
4594
+ return designReferenceFailureComment(
4595
+ "## \u30C7\u30B6\u30A4\u30F3\u53C2\u7167\u306E\u66F8\u304D\u623B\u3057\u3092\u78BA\u8A8D\u3067\u304D\u307E\u305B\u3093\uFF08\u8981\u4EBA\u624B\u78BA\u8A8D\uFF09",
4596
+ `apply-ui-design \u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u6B63\u5E38\u7D42\u4E86\uFF08exit 0\uFF09\u3057\u307E\u3057\u305F\u304C\u3001Issue #${issueNumber} \u306E description \u306B \`${DESIGN_REFERENCE_HEADING}\` \u30BB\u30AF\u30B7\u30E7\u30F3\uFF08\`.pen\` \u306E\u30D1\u30B9\u3092\u542B\u3080\uFF09\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u30BB\u30C3\u30B7\u30E7\u30F3\u304C\u66F8\u304D\u623B\u3057\u524D\u306B\u4E2D\u65AD\u3057\u305F\u304B\u3001\u66F8\u304D\u623B\u3057\u306B\u5931\u6557\u3057\u305F\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002`
4597
+ );
4598
+ }
4599
+ function designFileMissingComment(issueNumber, designFilePath) {
4600
+ return designReferenceFailureComment(
4601
+ "## \u30C7\u30B6\u30A4\u30F3\u53C2\u7167\u306E\u30D1\u30B9\u304C\u5B9F\u5728\u3057\u307E\u305B\u3093\uFF08\u8981\u4EBA\u624B\u78BA\u8A8D\uFF09",
4602
+ `apply-ui-design \u306F Issue #${issueNumber} \u306E description \u306B \`${DESIGN_REFERENCE_HEADING}\` \u30BB\u30AF\u30B7\u30E7\u30F3\u3092\u66F8\u304D\u623B\u3057\u307E\u3057\u305F\u304C\u3001\u305D\u3053\u304C\u6307\u3059 \`${designFilePath}\` \u304C\u30D9\u30FC\u30B9\u30D6\u30E9\u30F3\u30C1\u306E\u4F5C\u696D\u30C4\u30EA\u30FC\u306B\u5B58\u5728\u3057\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u30C7\u30B6\u30A4\u30F3PR\u306E\u30DE\u30FC\u30B8\u5148\u3068\u672CIssue\u306E\u30D9\u30FC\u30B9\u30D6\u30E9\u30F3\u30C1\u304C\u98DF\u3044\u9055\u3063\u3066\u3044\u308B\u304B\u3001\u30D1\u30B9\u306E\u7DB4\u308A\u304C\u8AA4\u3063\u3066\u3044\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002`
4603
+ );
4604
+ }
4553
4605
 
4554
4606
  // src/workers/create-ui-design.ts
4555
4607
  function designPrLabelingFailedComment(issueNumber, prNumber, error, yolo = false) {
@@ -4636,12 +4688,12 @@ import { join as join6 } from "node:path";
4636
4688
  function designFileExistsInWorktree(worktreeId, designFilePath) {
4637
4689
  return existsSync2(join6(getWorktreePath(worktreeId), designFilePath));
4638
4690
  }
4639
- async function markDesignReferenceMissing(issueNumber, logMessage) {
4691
+ async function markDesignReferenceMissing(issueNumber, logMessage, comment) {
4640
4692
  console.error(logMessage);
4641
4693
  await addLabel("issue", issueNumber, "cc-need-human-check").catch(
4642
4694
  (err) => console.error(`[apply-ui-design] addLabel cc-need-human-check failed for #${issueNumber}: ${err}`)
4643
4695
  );
4644
- await commentOnIssue(issueNumber, designReferenceMissingComment(issueNumber)).catch(
4696
+ await commentOnIssue(issueNumber, comment).catch(
4645
4697
  (err) => console.error(`[apply-ui-design] commentOnIssue failed for #${issueNumber}: ${err}`)
4646
4698
  );
4647
4699
  }
@@ -4683,7 +4735,7 @@ var applyUiDesignWorker = async (opts = {}) => {
4683
4735
  }
4684
4736
  return "skip";
4685
4737
  },
4686
- onCompleted: async (issueNumber, worktreeId) => {
4738
+ onCompleted: async (issueNumber, worktreeId, _output, ctx) => {
4687
4739
  let body;
4688
4740
  try {
4689
4741
  body = await getIssueBody(issueNumber);
@@ -4695,14 +4747,16 @@ var applyUiDesignWorker = async (opts = {}) => {
4695
4747
  if (designFilePath === null) {
4696
4748
  await markDesignReferenceMissing(
4697
4749
  issueNumber,
4698
- `[apply-ui-design] #${issueNumber}: session exited without a design reference section; marking cc-need-human-check`
4750
+ `[apply-ui-design] #${issueNumber}: session exited without a design reference section; marking cc-need-human-check`,
4751
+ designReferenceMissingComment(issueNumber)
4699
4752
  );
4700
4753
  return false;
4701
4754
  }
4702
- if (!designFileExistsInWorktree(worktreeId, designFilePath)) {
4755
+ if (shouldVerifyDesignFileExists(ctx.cloud) && !designFileExistsInWorktree(worktreeId, designFilePath)) {
4703
4756
  await markDesignReferenceMissing(
4704
4757
  issueNumber,
4705
- `[apply-ui-design] #${issueNumber}: design reference points to ${designFilePath}, which does not exist in worktree ${worktreeId}; marking cc-need-human-check`
4758
+ `[apply-ui-design] #${issueNumber}: design reference points to ${designFilePath}, which does not exist in worktree ${worktreeId}; marking cc-need-human-check`,
4759
+ designFileMissingComment(issueNumber, designFilePath)
4706
4760
  );
4707
4761
  return false;
4708
4762
  }
@@ -5353,6 +5407,7 @@ import { homedir as homedir6 } from "node:os";
5353
5407
  import { join as join8 } from "node:path";
5354
5408
  var LOG_PREFIX = "cloud-setup";
5355
5409
  var CLOUD_DEFAULT_PERMISSION_MODE = "auto";
5410
+ var CLOUD_PERMISSION_ALLOW = ["Bash(gh *)"];
5356
5411
  var CLOUD_SETTINGS_DEFAULTS = {
5357
5412
  outputStyle: "Proactive",
5358
5413
  language: "Japanese"
@@ -5388,6 +5443,13 @@ function withCloudDefaults(existing, force) {
5388
5443
  changed = true;
5389
5444
  };
5390
5445
  set(permissions, "defaultMode", CLOUD_DEFAULT_PERMISSION_MODE);
5446
+ const allow = permissions["allow"] ?? [];
5447
+ if (!Array.isArray(allow)) throw new Error("`permissions.allow` is not an array");
5448
+ const missing = CLOUD_PERMISSION_ALLOW.filter((rule) => !allow.includes(rule));
5449
+ if (missing.length > 0) {
5450
+ permissions["allow"] = [...allow, ...missing];
5451
+ changed = true;
5452
+ }
5391
5453
  for (const [key, value] of Object.entries(CLOUD_SETTINGS_DEFAULTS)) set(settings, key, value);
5392
5454
  for (const [key, value] of Object.entries(CLOUD_SETTINGS_ENV)) set(env, key, value);
5393
5455
  if (!changed) return null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-task-worker",
3
- "version": "0.111.0",
3
+ "version": "0.113.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",