claude-task-worker 0.121.0 → 0.122.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.
- package/dist/{chunk-Z2IEIKI3.js → chunk-NS334FXZ.js} +36 -2
- package/dist/gh.d.ts +9 -1
- package/dist/index.js +156 -109
- package/dist/lib.js +1 -1
- package/dist/workers/create-ui-design.d.ts +4 -0
- package/package.json +1 -1
|
@@ -191,6 +191,9 @@ async function fetchPrRef(owner, name, prNumber) {
|
|
|
191
191
|
headRefName: parsed?.head?.ref ?? "",
|
|
192
192
|
baseRefName: parsed?.base?.ref ?? "",
|
|
193
193
|
createdAt: parsed?.created_at ?? "",
|
|
194
|
+
headRepo: parsed?.head?.repo?.full_name ?? "",
|
|
195
|
+
headSha: parsed?.head?.sha ?? "",
|
|
196
|
+
title: parsed?.title ?? "",
|
|
194
197
|
body: typeof parsed?.body === "string" ? parsed.body : ""
|
|
195
198
|
};
|
|
196
199
|
} catch (err) {
|
|
@@ -223,7 +226,10 @@ function bodyClosesIssue(body, issueNumber) {
|
|
|
223
226
|
const pattern = new RegExp(`\\b(close[sd]?|fix(?:e[sd])?|resolve[sd]?)\\s*:?\\s*#${issueNumber}\\b(?!\\d)`, "i");
|
|
224
227
|
return pattern.test(body);
|
|
225
228
|
}
|
|
226
|
-
|
|
229
|
+
function bodyMentionsIssue(body, issueNumber) {
|
|
230
|
+
return new RegExp(`#${issueNumber}(?!\\d)`).test(body);
|
|
231
|
+
}
|
|
232
|
+
async function listPrsCrossReferencingIssue(issueNumber, bodyFilter = bodyClosesIssue) {
|
|
227
233
|
const { owner, name } = await getRepoInfo();
|
|
228
234
|
const output = await execGh(["api", `repos/${owner}/${name}/issues/${issueNumber}/timeline`, "--paginate"]);
|
|
229
235
|
const events = JSON.parse(output);
|
|
@@ -235,7 +241,30 @@ async function listPrsCrossReferencingIssue(issueNumber) {
|
|
|
235
241
|
)
|
|
236
242
|
];
|
|
237
243
|
const refs = await Promise.all(numbers.map((number) => fetchPrRef(owner, name, number)));
|
|
238
|
-
return refs.filter(
|
|
244
|
+
return refs.filter(
|
|
245
|
+
(ref) => ref !== null && bodyFilter(ref.body, issueNumber)
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
async function createRemoteBranch(branch, sha) {
|
|
249
|
+
const { owner, name } = await getRepoInfo();
|
|
250
|
+
await execGh([
|
|
251
|
+
"api",
|
|
252
|
+
"-X",
|
|
253
|
+
"POST",
|
|
254
|
+
`repos/${owner}/${name}/git/refs`,
|
|
255
|
+
"-f",
|
|
256
|
+
`ref=refs/heads/${branch}`,
|
|
257
|
+
"-f",
|
|
258
|
+
`sha=${sha}`
|
|
259
|
+
]);
|
|
260
|
+
}
|
|
261
|
+
async function closePullRequest(prNumber) {
|
|
262
|
+
const { owner, name } = await getRepoInfo();
|
|
263
|
+
await execGh(["api", "-X", "PATCH", `repos/${owner}/${name}/pulls/${prNumber}`, "-f", "state=closed"]);
|
|
264
|
+
}
|
|
265
|
+
async function deleteRemoteBranch(branch) {
|
|
266
|
+
const { owner, name } = await getRepoInfo();
|
|
267
|
+
await execGh(["api", "-X", "DELETE", `repos/${owner}/${name}/git/refs/heads/${branch}`]);
|
|
239
268
|
}
|
|
240
269
|
var ADD_CLOSE_ISSUE_REFERENCES = `mutation($issueId: ID!, $prId: ID!) {
|
|
241
270
|
addCloseIssueReferences(input: { issueId: $issueId, pullRequestIds: [$prId] }) { issue { number } }
|
|
@@ -3341,7 +3370,11 @@ export {
|
|
|
3341
3370
|
getPrDetail,
|
|
3342
3371
|
closeIssue,
|
|
3343
3372
|
parseClosingIssueNumbers,
|
|
3373
|
+
bodyMentionsIssue,
|
|
3344
3374
|
listPrsCrossReferencingIssue,
|
|
3375
|
+
createRemoteBranch,
|
|
3376
|
+
closePullRequest,
|
|
3377
|
+
deleteRemoteBranch,
|
|
3345
3378
|
linkClosingPr,
|
|
3346
3379
|
getIssueSubIssuesSummary,
|
|
3347
3380
|
listPullRequestsWithChecks,
|
|
@@ -3352,6 +3385,7 @@ export {
|
|
|
3352
3385
|
removeLabel,
|
|
3353
3386
|
commentOnPR,
|
|
3354
3387
|
commentOnIssue,
|
|
3388
|
+
createPullRequest,
|
|
3355
3389
|
createLabel,
|
|
3356
3390
|
parseProjectFilters,
|
|
3357
3391
|
hasProjectFilter,
|
package/dist/gh.d.ts
CHANGED
|
@@ -51,6 +51,10 @@ export interface ClosingPrRef {
|
|
|
51
51
|
headRefName: string;
|
|
52
52
|
baseRefName: string;
|
|
53
53
|
createdAt: string;
|
|
54
|
+
headRepo?: string;
|
|
55
|
+
headSha?: string;
|
|
56
|
+
title?: string;
|
|
57
|
+
body?: string;
|
|
54
58
|
}
|
|
55
59
|
export declare function listPrsClosingIssue(issueNumber: number): Promise<ClosingPrRef[]>;
|
|
56
60
|
export declare function getPrDetail(prNumber: number): Promise<(ClosingPrRef & {
|
|
@@ -59,7 +63,11 @@ export declare function getPrDetail(prNumber: number): Promise<(ClosingPrRef & {
|
|
|
59
63
|
export declare function closeIssue(issueNumber: number, reason?: "completed" | "not_planned"): Promise<void>;
|
|
60
64
|
export declare function parseClosingIssueNumbers(body: string): number[];
|
|
61
65
|
export declare function bodyClosesIssue(body: string, issueNumber: number): boolean;
|
|
62
|
-
export declare function
|
|
66
|
+
export declare function bodyMentionsIssue(body: string, issueNumber: number): boolean;
|
|
67
|
+
export declare function listPrsCrossReferencingIssue(issueNumber: number, bodyFilter?: (body: string, issueNumber: number) => boolean): Promise<ClosingPrRef[]>;
|
|
68
|
+
export declare function createRemoteBranch(branch: string, sha: string): Promise<void>;
|
|
69
|
+
export declare function closePullRequest(prNumber: number): Promise<void>;
|
|
70
|
+
export declare function deleteRemoteBranch(branch: string): Promise<void>;
|
|
63
71
|
export declare function linkClosingPr(issueNumber: number, prNumber: number): Promise<void>;
|
|
64
72
|
export declare function findPrNumberClosingIssue(issueNumber: number, expectedHeadRefName: string): Promise<number | null>;
|
|
65
73
|
export declare function getIssueSubIssuesSummary(issueNumber: number): Promise<SubIssuesSummary>;
|
package/dist/index.js
CHANGED
|
@@ -12,18 +12,23 @@ import {
|
|
|
12
12
|
addLabel,
|
|
13
13
|
assertCloudCompatibleCommand,
|
|
14
14
|
assertProjectCompatibleCommand,
|
|
15
|
+
bodyMentionsIssue,
|
|
15
16
|
buildForwardedCommand,
|
|
16
17
|
buildScriptCommand,
|
|
17
18
|
buildTokenLimitText,
|
|
18
19
|
checkCloudConfig,
|
|
19
20
|
closeIssue,
|
|
21
|
+
closePullRequest,
|
|
20
22
|
commentOnIssue,
|
|
21
23
|
commentOnPR,
|
|
22
24
|
createIssuePollingWorker,
|
|
23
25
|
createLabel,
|
|
24
26
|
createPrPollingWorker,
|
|
27
|
+
createPullRequest,
|
|
28
|
+
createRemoteBranch,
|
|
25
29
|
createScheduledWorker,
|
|
26
30
|
defineWorker,
|
|
31
|
+
deleteRemoteBranch,
|
|
27
32
|
disabledWorkerMessage,
|
|
28
33
|
ensureRenderInterval,
|
|
29
34
|
findOpenPrNumberByHeadRef,
|
|
@@ -65,7 +70,7 @@ import {
|
|
|
65
70
|
shutdown,
|
|
66
71
|
waitForAllProcesses,
|
|
67
72
|
writeLastRun
|
|
68
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-NS334FXZ.js";
|
|
69
74
|
import {
|
|
70
75
|
captureConsole
|
|
71
76
|
} from "./chunk-N42YU3GJ.js";
|
|
@@ -289,6 +294,112 @@ var createIssueWorker = createIssuePollingWorker({
|
|
|
289
294
|
}
|
|
290
295
|
});
|
|
291
296
|
|
|
297
|
+
// src/workers/exec-issue.ts
|
|
298
|
+
var REPORT_TAIL_LIMIT = 3e3;
|
|
299
|
+
function formatSessionReport(output) {
|
|
300
|
+
const trimmed = output.trim();
|
|
301
|
+
if (trimmed === "") return "\uFF08\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u51FA\u529B\u306F\u3042\u308A\u307E\u305B\u3093\u3067\u3057\u305F\uFF09";
|
|
302
|
+
const tail = trimmed.length > REPORT_TAIL_LIMIT ? `\u2026\uFF08\u5148\u982D\u3092\u7701\u7565\uFF09
|
|
303
|
+
${trimmed.slice(-REPORT_TAIL_LIMIT)}` : trimmed;
|
|
304
|
+
return ["```", tail, "```"].join("\n");
|
|
305
|
+
}
|
|
306
|
+
function selectOwnedClosingPr(candidates, ctx) {
|
|
307
|
+
const open = candidates.filter((c) => c.state === "MERGED" || c.state === "OPEN");
|
|
308
|
+
if (!ctx.cloud) {
|
|
309
|
+
const found2 = open.find((c) => c.headRefName === ctx.expectedHeadRefName);
|
|
310
|
+
return found2 ? found2.number : null;
|
|
311
|
+
}
|
|
312
|
+
const found = open.find((c) => {
|
|
313
|
+
if (c.baseRefName !== ctx.baseBranch) return false;
|
|
314
|
+
const createdAt = Date.parse(c.createdAt);
|
|
315
|
+
return !Number.isNaN(createdAt) && createdAt >= ctx.startedAt && createdAt <= ctx.now;
|
|
316
|
+
});
|
|
317
|
+
return found ? found.number : null;
|
|
318
|
+
}
|
|
319
|
+
function prMissingComment(worktreeId, output, cloud) {
|
|
320
|
+
const stateSection = cloud ? [
|
|
321
|
+
"## \u72B6\u614B\u306E\u78BA\u8A8D",
|
|
322
|
+
"- \u30AF\u30E9\u30A6\u30C9\u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u4F5C\u696D\u30D6\u30E9\u30F3\u30C1\u540D\u3092\u81EA\u8EAB\u3067\u6C7A\u3081\u308B\u305F\u3081\u3001\u30ED\u30FC\u30AB\u30EB\u304B\u3089\u306F\u540D\u524D\u304C\u5206\u304B\u308A\u307E\u305B\u3093\u3002claude.ai \u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u753B\u9762\u3067\u4F5C\u696D\u30D6\u30E9\u30F3\u30C1\u3068 push \u72B6\u6CC1\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044"
|
|
323
|
+
] : [
|
|
324
|
+
"## \u72B6\u614B\u306E\u78BA\u8A8D",
|
|
325
|
+
`- \u5909\u66F4\u304C push \u6E08\u307F\u306E\u5834\u5408\u306F\u30EA\u30E2\u30FC\u30C8\u30D6\u30E9\u30F3\u30C1 \`${worktreeId}\` \u304C\u6B8B\u3063\u3066\u3044\u307E\u3059\u3002\u5185\u5BB9\u3092\u78BA\u8A8D\u3057\u3001\u5FC5\u8981\u306A\u3089\u624B\u52D5\u3067PR\u3092\u4F5C\u6210\u3057\u3066\u304F\u3060\u3055\u3044`
|
|
326
|
+
];
|
|
327
|
+
return [
|
|
328
|
+
"## PR\u672A\u4F5C\u6210\u306E\u307E\u307E\u81EA\u52D5\u5B9F\u884C\u304C\u7D42\u4E86\u3057\u307E\u3057\u305F\uFF08\u8981\u4EBA\u624B\u78BA\u8A8D\uFF09",
|
|
329
|
+
cloud ? "exec-issue \u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u6B63\u5E38\u7D42\u4E86\uFF08exit 0\uFF09\u3057\u307E\u3057\u305F\u304C\u3001\u672CIssue\u3092 closing \u53C2\u7167\u3059\u308BPR\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002PR\u4F5C\u6210\u524D\u306B\u30BB\u30C3\u30B7\u30E7\u30F3\u304C\u7D42\u4E86\u3057\u305F\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002" : `exec-issue \u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u6B63\u5E38\u7D42\u4E86\uFF08exit 0\uFF09\u3057\u307E\u3057\u305F\u304C\u3001\u3053\u306E\u5B9F\u884C\u306E\u4F5C\u696D\u30D6\u30E9\u30F3\u30C1\uFF08\`${worktreeId}\`\uFF09\u3092 head \u3068\u3059\u308BPR\u3082\u3001\u672CIssue\u3092 closing \u53C2\u7167\u3059\u308BPR\u3082\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002PR\u4F5C\u6210\u524D\u306B\u30BB\u30C3\u30B7\u30E7\u30F3\u304C\u7D42\u4E86\u3057\u305F\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002`,
|
|
330
|
+
"",
|
|
331
|
+
"## PR\u3092\u4F5C\u6210\u3057\u306A\u304B\u3063\u305F\u7406\u7531\uFF08\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u6700\u7D42\u5831\u544A\uFF09",
|
|
332
|
+
formatSessionReport(output),
|
|
333
|
+
"",
|
|
334
|
+
...stateSection,
|
|
335
|
+
"",
|
|
336
|
+
"## \u5BFE\u5FDC\u5F8C\u306E\u9032\u3081\u65B9",
|
|
337
|
+
"- \u81EA\u52D5\u5B9F\u884C\u3092\u3084\u308A\u76F4\u3059\u5834\u5408: `cc-need-human-check` \u30E9\u30D9\u30EB\u3092\u5916\u3057\u3001`cc-exec-issue` \u30E9\u30D9\u30EB\u3092\u4ED8\u3051\u76F4\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
338
|
+
"- \u624B\u52D5\u3067PR\u3092\u4F5C\u6210\u3057\u305F\u5834\u5408\u306A\u3069\u5BFE\u5FDC\u6E08\u307F\u306E\u5834\u5408: `cc-need-human-check` \u30E9\u30D9\u30EB\u3092\u5916\u3057\u3066\u304F\u3060\u3055\u3044"
|
|
339
|
+
].join("\n");
|
|
340
|
+
}
|
|
341
|
+
async function ensurePrTriageMetadata(prNumber) {
|
|
342
|
+
await addLabel("pr", prNumber, "cc-triage-scope").catch(
|
|
343
|
+
(err) => console.error(`[exec-issue] addLabel cc-triage-scope failed for PR #${prNumber}: ${err}`)
|
|
344
|
+
);
|
|
345
|
+
await getCurrentUser().then((user) => addAssignee("pr", prNumber, user)).catch((err) => console.error(`[exec-issue] addAssignee failed for PR #${prNumber}: ${err}`));
|
|
346
|
+
}
|
|
347
|
+
async function verifyPrCreated(issueNumber, worktreeId, output, ctx) {
|
|
348
|
+
if (await hasLabel("issue", issueNumber, "cc-need-human-check")) {
|
|
349
|
+
console.log(`[exec-issue] #${issueNumber}: cc-need-human-check present, skip cc-pr-created`);
|
|
350
|
+
return false;
|
|
351
|
+
}
|
|
352
|
+
if (await getIssueState(issueNumber) === "CLOSED") {
|
|
353
|
+
console.log(`[exec-issue] #${issueNumber}: issue closed by skill (no-change path), skip cc-pr-created`);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
const ownership = {
|
|
357
|
+
cloud: ctx.cloud,
|
|
358
|
+
expectedHeadRefName: worktreeId,
|
|
359
|
+
baseBranch: ctx.baseBranch,
|
|
360
|
+
startedAt: ctx.startedAt,
|
|
361
|
+
now: Date.now()
|
|
362
|
+
};
|
|
363
|
+
let prNumber = null;
|
|
364
|
+
if (!ctx.cloud) {
|
|
365
|
+
prNumber = await findPrNumberByHeadRef(worktreeId, "all");
|
|
366
|
+
}
|
|
367
|
+
if (prNumber === null) {
|
|
368
|
+
prNumber = selectOwnedClosingPr(await listPrsClosingIssue(issueNumber), ownership);
|
|
369
|
+
}
|
|
370
|
+
if (prNumber === null) {
|
|
371
|
+
const candidates = await listPrsCrossReferencingIssue(issueNumber).catch((err) => {
|
|
372
|
+
console.error(`[exec-issue] listPrsCrossReferencingIssue failed for #${issueNumber}: ${err}`);
|
|
373
|
+
return [];
|
|
374
|
+
});
|
|
375
|
+
prNumber = selectOwnedClosingPr(candidates, ownership);
|
|
376
|
+
if (prNumber !== null) {
|
|
377
|
+
await linkClosingPr(issueNumber, prNumber).catch(
|
|
378
|
+
(err) => console.error(`[exec-issue] linkClosingPr failed for #${issueNumber} -> #${prNumber}: ${err}`)
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
if (prNumber !== null) {
|
|
383
|
+
await addLabel("issue", issueNumber, "cc-pr-created");
|
|
384
|
+
await ensurePrTriageMetadata(prNumber);
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
console.error(
|
|
388
|
+
`[exec-issue] #${issueNumber}: session exited without a PR (branch: ${worktreeId}); marking cc-need-human-check`
|
|
389
|
+
);
|
|
390
|
+
await addLabel("issue", issueNumber, "cc-need-human-check");
|
|
391
|
+
await commentOnIssue(issueNumber, prMissingComment(worktreeId, output, ctx.cloud)).catch(
|
|
392
|
+
(err) => console.error(`[exec-issue] commentOnIssue failed for #${issueNumber}: ${err}`)
|
|
393
|
+
);
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
var execIssueWorker = createIssuePollingWorker({
|
|
397
|
+
name: "exec-issue",
|
|
398
|
+
command: "/claude-task-worker:exec-issue",
|
|
399
|
+
triggerLabels: ["cc-exec-issue"],
|
|
400
|
+
onCompleted: verifyPrCreated
|
|
401
|
+
});
|
|
402
|
+
|
|
292
403
|
// src/workers/create-ui-design.ts
|
|
293
404
|
function designPrLabelingFailedComment(issueNumber, prNumber, error, yolo = false) {
|
|
294
405
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -309,6 +420,42 @@ function designPrLabelingFailedComment(issueNumber, prNumber, error, yolo = fals
|
|
|
309
420
|
`- \u30E9\u30D9\u30EB\u4F5C\u6210\u5F8C\u306B\u3084\u308A\u76F4\u3059\u5834\u5408: \`cc-need-human-check\` \u30E9\u30D9\u30EB\u3092\u5916\u3057\u3001${yolo ? "`cc-ui-design`\u30FB`cc-triage-scope`" : "`cc-ui-design`"}\uFF08PR\u5074\uFF09\u3068 \`cc-ui-design-pr-created\`\uFF08Issue\u5074\uFF09\u3092\u624B\u52D5\u3067\u4ED8\u3051\u3066\u304F\u3060\u3055\u3044`
|
|
310
421
|
].join("\n");
|
|
311
422
|
}
|
|
423
|
+
async function adoptCloudDesignPr(issueNumber, branch, ctx) {
|
|
424
|
+
const { owner, name } = await getRepoInfo();
|
|
425
|
+
const candidates = (await listPrsCrossReferencingIssue(issueNumber, bodyMentionsIssue)).filter(
|
|
426
|
+
(c) => c.state === "OPEN" && c.headRepo === `${owner}/${name}`
|
|
427
|
+
);
|
|
428
|
+
const prNumber = selectOwnedClosingPr(candidates, {
|
|
429
|
+
cloud: true,
|
|
430
|
+
expectedHeadRefName: branch,
|
|
431
|
+
baseBranch: ctx.baseBranch,
|
|
432
|
+
startedAt: ctx.startedAt,
|
|
433
|
+
now: Date.now()
|
|
434
|
+
});
|
|
435
|
+
if (prNumber === null) return null;
|
|
436
|
+
const pr = candidates.find((c) => c.number === prNumber);
|
|
437
|
+
if (!pr || pr.headRefName === branch) return prNumber;
|
|
438
|
+
if (!pr.headSha) throw new Error(`design PR #${prNumber} has no head sha`);
|
|
439
|
+
await deleteRemoteBranch(branch).catch(() => {
|
|
440
|
+
});
|
|
441
|
+
await createRemoteBranch(branch, pr.headSha);
|
|
442
|
+
const newPr = await createPullRequest(
|
|
443
|
+
pr.baseRefName,
|
|
444
|
+
branch,
|
|
445
|
+
pr.title || `UI design for #${issueNumber}`,
|
|
446
|
+
pr.body ?? ""
|
|
447
|
+
);
|
|
448
|
+
await commentOnPR(
|
|
449
|
+
prNumber,
|
|
450
|
+
`\u30D6\u30E9\u30F3\u30C1 \`${branch}\` \u304B\u3089\u4F5C\u308A\u76F4\u3057\u305F #${newPr} \u3078\u79FB\u884C\u3057\u305F\u305F\u3081\u3001\u3053\u306EPR\u3092\u9589\u3058\u307E\u3059\u3002`
|
|
451
|
+
).catch(() => {
|
|
452
|
+
});
|
|
453
|
+
await closePullRequest(prNumber);
|
|
454
|
+
console.log(
|
|
455
|
+
`[create-ui-design] #${issueNumber}: recreated design PR #${prNumber} (${pr.headRefName}) as #${newPr} (${branch})`
|
|
456
|
+
);
|
|
457
|
+
return newPr;
|
|
458
|
+
}
|
|
312
459
|
var createUiDesignWorker = defineWorker({
|
|
313
460
|
name: "create-ui-design",
|
|
314
461
|
kind: "issue",
|
|
@@ -324,7 +471,7 @@ var createUiDesignWorker = defineWorker({
|
|
|
324
471
|
command: "/claude-task-worker:create-ui-design",
|
|
325
472
|
triggerLabels: ["cc-create-ui-design"],
|
|
326
473
|
excludeLabels: ["cc-ui-design-pr-created", "cc-ui-design-ready", "cc-exec-issue", "cc-pr-created"],
|
|
327
|
-
onCompleted: async (issueNumber) => {
|
|
474
|
+
onCompleted: async (issueNumber, _worktreeId, _output, ctx) => {
|
|
328
475
|
if (await hasLabel("issue", issueNumber, "cc-need-human-check")) {
|
|
329
476
|
console.log(`[create-ui-design] #${issueNumber}: cc-need-human-check present, skip cc-ui-design-pr-created`);
|
|
330
477
|
return false;
|
|
@@ -336,7 +483,13 @@ var createUiDesignWorker = defineWorker({
|
|
|
336
483
|
}
|
|
337
484
|
}
|
|
338
485
|
const branch = designBranchName(issueNumber);
|
|
339
|
-
|
|
486
|
+
let prNumber = await findPrNumberByHeadRef(branch, "open");
|
|
487
|
+
if (prNumber === null && ctx.cloud) {
|
|
488
|
+
prNumber = await adoptCloudDesignPr(issueNumber, branch, ctx).catch((err) => {
|
|
489
|
+
console.error(`[create-ui-design] #${issueNumber}: adoptCloudDesignPr failed: ${err}`);
|
|
490
|
+
return null;
|
|
491
|
+
});
|
|
492
|
+
}
|
|
340
493
|
if (prNumber === null) {
|
|
341
494
|
console.error(
|
|
342
495
|
`[create-ui-design] #${issueNumber}: session exited without an open design PR (branch: ${branch}); marking cc-need-human-check`
|
|
@@ -416,112 +569,6 @@ var epicIssueWorker = createIssuePollingWorker({
|
|
|
416
569
|
}
|
|
417
570
|
});
|
|
418
571
|
|
|
419
|
-
// src/workers/exec-issue.ts
|
|
420
|
-
var REPORT_TAIL_LIMIT = 3e3;
|
|
421
|
-
function formatSessionReport(output) {
|
|
422
|
-
const trimmed = output.trim();
|
|
423
|
-
if (trimmed === "") return "\uFF08\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u51FA\u529B\u306F\u3042\u308A\u307E\u305B\u3093\u3067\u3057\u305F\uFF09";
|
|
424
|
-
const tail = trimmed.length > REPORT_TAIL_LIMIT ? `\u2026\uFF08\u5148\u982D\u3092\u7701\u7565\uFF09
|
|
425
|
-
${trimmed.slice(-REPORT_TAIL_LIMIT)}` : trimmed;
|
|
426
|
-
return ["```", tail, "```"].join("\n");
|
|
427
|
-
}
|
|
428
|
-
function selectOwnedClosingPr(candidates, ctx) {
|
|
429
|
-
const open = candidates.filter((c) => c.state === "MERGED" || c.state === "OPEN");
|
|
430
|
-
if (!ctx.cloud) {
|
|
431
|
-
const found2 = open.find((c) => c.headRefName === ctx.expectedHeadRefName);
|
|
432
|
-
return found2 ? found2.number : null;
|
|
433
|
-
}
|
|
434
|
-
const found = open.find((c) => {
|
|
435
|
-
if (c.baseRefName !== ctx.baseBranch) return false;
|
|
436
|
-
const createdAt = Date.parse(c.createdAt);
|
|
437
|
-
return !Number.isNaN(createdAt) && createdAt >= ctx.startedAt && createdAt <= ctx.now;
|
|
438
|
-
});
|
|
439
|
-
return found ? found.number : null;
|
|
440
|
-
}
|
|
441
|
-
function prMissingComment(worktreeId, output, cloud) {
|
|
442
|
-
const stateSection = cloud ? [
|
|
443
|
-
"## \u72B6\u614B\u306E\u78BA\u8A8D",
|
|
444
|
-
"- \u30AF\u30E9\u30A6\u30C9\u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u4F5C\u696D\u30D6\u30E9\u30F3\u30C1\u540D\u3092\u81EA\u8EAB\u3067\u6C7A\u3081\u308B\u305F\u3081\u3001\u30ED\u30FC\u30AB\u30EB\u304B\u3089\u306F\u540D\u524D\u304C\u5206\u304B\u308A\u307E\u305B\u3093\u3002claude.ai \u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u753B\u9762\u3067\u4F5C\u696D\u30D6\u30E9\u30F3\u30C1\u3068 push \u72B6\u6CC1\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044"
|
|
445
|
-
] : [
|
|
446
|
-
"## \u72B6\u614B\u306E\u78BA\u8A8D",
|
|
447
|
-
`- \u5909\u66F4\u304C push \u6E08\u307F\u306E\u5834\u5408\u306F\u30EA\u30E2\u30FC\u30C8\u30D6\u30E9\u30F3\u30C1 \`${worktreeId}\` \u304C\u6B8B\u3063\u3066\u3044\u307E\u3059\u3002\u5185\u5BB9\u3092\u78BA\u8A8D\u3057\u3001\u5FC5\u8981\u306A\u3089\u624B\u52D5\u3067PR\u3092\u4F5C\u6210\u3057\u3066\u304F\u3060\u3055\u3044`
|
|
448
|
-
];
|
|
449
|
-
return [
|
|
450
|
-
"## PR\u672A\u4F5C\u6210\u306E\u307E\u307E\u81EA\u52D5\u5B9F\u884C\u304C\u7D42\u4E86\u3057\u307E\u3057\u305F\uFF08\u8981\u4EBA\u624B\u78BA\u8A8D\uFF09",
|
|
451
|
-
cloud ? "exec-issue \u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u6B63\u5E38\u7D42\u4E86\uFF08exit 0\uFF09\u3057\u307E\u3057\u305F\u304C\u3001\u672CIssue\u3092 closing \u53C2\u7167\u3059\u308BPR\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002PR\u4F5C\u6210\u524D\u306B\u30BB\u30C3\u30B7\u30E7\u30F3\u304C\u7D42\u4E86\u3057\u305F\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002" : `exec-issue \u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u6B63\u5E38\u7D42\u4E86\uFF08exit 0\uFF09\u3057\u307E\u3057\u305F\u304C\u3001\u3053\u306E\u5B9F\u884C\u306E\u4F5C\u696D\u30D6\u30E9\u30F3\u30C1\uFF08\`${worktreeId}\`\uFF09\u3092 head \u3068\u3059\u308BPR\u3082\u3001\u672CIssue\u3092 closing \u53C2\u7167\u3059\u308BPR\u3082\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002PR\u4F5C\u6210\u524D\u306B\u30BB\u30C3\u30B7\u30E7\u30F3\u304C\u7D42\u4E86\u3057\u305F\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002`,
|
|
452
|
-
"",
|
|
453
|
-
"## PR\u3092\u4F5C\u6210\u3057\u306A\u304B\u3063\u305F\u7406\u7531\uFF08\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u6700\u7D42\u5831\u544A\uFF09",
|
|
454
|
-
formatSessionReport(output),
|
|
455
|
-
"",
|
|
456
|
-
...stateSection,
|
|
457
|
-
"",
|
|
458
|
-
"## \u5BFE\u5FDC\u5F8C\u306E\u9032\u3081\u65B9",
|
|
459
|
-
"- \u81EA\u52D5\u5B9F\u884C\u3092\u3084\u308A\u76F4\u3059\u5834\u5408: `cc-need-human-check` \u30E9\u30D9\u30EB\u3092\u5916\u3057\u3001`cc-exec-issue` \u30E9\u30D9\u30EB\u3092\u4ED8\u3051\u76F4\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
460
|
-
"- \u624B\u52D5\u3067PR\u3092\u4F5C\u6210\u3057\u305F\u5834\u5408\u306A\u3069\u5BFE\u5FDC\u6E08\u307F\u306E\u5834\u5408: `cc-need-human-check` \u30E9\u30D9\u30EB\u3092\u5916\u3057\u3066\u304F\u3060\u3055\u3044"
|
|
461
|
-
].join("\n");
|
|
462
|
-
}
|
|
463
|
-
async function ensurePrTriageMetadata(prNumber) {
|
|
464
|
-
await addLabel("pr", prNumber, "cc-triage-scope").catch(
|
|
465
|
-
(err) => console.error(`[exec-issue] addLabel cc-triage-scope failed for PR #${prNumber}: ${err}`)
|
|
466
|
-
);
|
|
467
|
-
await getCurrentUser().then((user) => addAssignee("pr", prNumber, user)).catch((err) => console.error(`[exec-issue] addAssignee failed for PR #${prNumber}: ${err}`));
|
|
468
|
-
}
|
|
469
|
-
async function verifyPrCreated(issueNumber, worktreeId, output, ctx) {
|
|
470
|
-
if (await hasLabel("issue", issueNumber, "cc-need-human-check")) {
|
|
471
|
-
console.log(`[exec-issue] #${issueNumber}: cc-need-human-check present, skip cc-pr-created`);
|
|
472
|
-
return false;
|
|
473
|
-
}
|
|
474
|
-
if (await getIssueState(issueNumber) === "CLOSED") {
|
|
475
|
-
console.log(`[exec-issue] #${issueNumber}: issue closed by skill (no-change path), skip cc-pr-created`);
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
const ownership = {
|
|
479
|
-
cloud: ctx.cloud,
|
|
480
|
-
expectedHeadRefName: worktreeId,
|
|
481
|
-
baseBranch: ctx.baseBranch,
|
|
482
|
-
startedAt: ctx.startedAt,
|
|
483
|
-
now: Date.now()
|
|
484
|
-
};
|
|
485
|
-
let prNumber = null;
|
|
486
|
-
if (!ctx.cloud) {
|
|
487
|
-
prNumber = await findPrNumberByHeadRef(worktreeId, "all");
|
|
488
|
-
}
|
|
489
|
-
if (prNumber === null) {
|
|
490
|
-
prNumber = selectOwnedClosingPr(await listPrsClosingIssue(issueNumber), ownership);
|
|
491
|
-
}
|
|
492
|
-
if (prNumber === null) {
|
|
493
|
-
const candidates = await listPrsCrossReferencingIssue(issueNumber).catch((err) => {
|
|
494
|
-
console.error(`[exec-issue] listPrsCrossReferencingIssue failed for #${issueNumber}: ${err}`);
|
|
495
|
-
return [];
|
|
496
|
-
});
|
|
497
|
-
prNumber = selectOwnedClosingPr(candidates, ownership);
|
|
498
|
-
if (prNumber !== null) {
|
|
499
|
-
await linkClosingPr(issueNumber, prNumber).catch(
|
|
500
|
-
(err) => console.error(`[exec-issue] linkClosingPr failed for #${issueNumber} -> #${prNumber}: ${err}`)
|
|
501
|
-
);
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
if (prNumber !== null) {
|
|
505
|
-
await addLabel("issue", issueNumber, "cc-pr-created");
|
|
506
|
-
await ensurePrTriageMetadata(prNumber);
|
|
507
|
-
return;
|
|
508
|
-
}
|
|
509
|
-
console.error(
|
|
510
|
-
`[exec-issue] #${issueNumber}: session exited without a PR (branch: ${worktreeId}); marking cc-need-human-check`
|
|
511
|
-
);
|
|
512
|
-
await addLabel("issue", issueNumber, "cc-need-human-check");
|
|
513
|
-
await commentOnIssue(issueNumber, prMissingComment(worktreeId, output, ctx.cloud)).catch(
|
|
514
|
-
(err) => console.error(`[exec-issue] commentOnIssue failed for #${issueNumber}: ${err}`)
|
|
515
|
-
);
|
|
516
|
-
return false;
|
|
517
|
-
}
|
|
518
|
-
var execIssueWorker = createIssuePollingWorker({
|
|
519
|
-
name: "exec-issue",
|
|
520
|
-
command: "/claude-task-worker:exec-issue",
|
|
521
|
-
triggerLabels: ["cc-exec-issue"],
|
|
522
|
-
onCompleted: verifyPrCreated
|
|
523
|
-
});
|
|
524
|
-
|
|
525
572
|
// src/workers/fix-review-point.ts
|
|
526
573
|
var fixReviewPointWorker = createPrPollingWorker({
|
|
527
574
|
name: "fix-review-point",
|
package/dist/lib.js
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
export declare function designPrLabelingFailedComment(issueNumber: number, prNumber: number, error: unknown, yolo?: boolean): string;
|
|
2
|
+
export declare function adoptCloudDesignPr(issueNumber: number, branch: string, ctx: {
|
|
3
|
+
baseBranch: string;
|
|
4
|
+
startedAt: number;
|
|
5
|
+
}): Promise<number | null>;
|
|
2
6
|
export declare const createUiDesignWorker: import("./worker-definition").WorkerDefinition;
|