claude-task-worker 0.121.0 → 0.123.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-HZHIQMAQ.js} +58 -9
- package/dist/gh.d.ts +12 -1
- package/dist/index.js +157 -109
- package/dist/lib.js +1 -1
- package/dist/workers/create-ui-design.d.ts +4 -0
- package/package.json +1 -1
|
@@ -184,20 +184,37 @@ async function listPrsClosingIssue(issueNumber) {
|
|
|
184
184
|
}
|
|
185
185
|
async function fetchPrRef(owner, name, prNumber) {
|
|
186
186
|
try {
|
|
187
|
-
const parsed = JSON.parse(await execGh(["api", `repos/${owner}/${name}/pulls/${prNumber}`]));
|
|
188
187
|
return {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
headRefName: parsed?.head?.ref ?? "",
|
|
192
|
-
baseRefName: parsed?.base?.ref ?? "",
|
|
193
|
-
createdAt: parsed?.created_at ?? "",
|
|
194
|
-
body: typeof parsed?.body === "string" ? parsed.body : ""
|
|
188
|
+
...toPrRef(JSON.parse(await execGh(["api", `repos/${owner}/${name}/pulls/${prNumber}`]))),
|
|
189
|
+
number: prNumber
|
|
195
190
|
};
|
|
196
191
|
} catch (err) {
|
|
197
192
|
console.error(`[gh] failed to read PR #${prNumber}: ${err}`);
|
|
198
193
|
return null;
|
|
199
194
|
}
|
|
200
195
|
}
|
|
196
|
+
function toPrRef(parsed) {
|
|
197
|
+
return {
|
|
198
|
+
number: Number(parsed?.number),
|
|
199
|
+
state: parsed?.merged_at ? "MERGED" : String(parsed?.state ?? "").toUpperCase(),
|
|
200
|
+
headRefName: parsed?.head?.ref ?? "",
|
|
201
|
+
baseRefName: parsed?.base?.ref ?? "",
|
|
202
|
+
createdAt: parsed?.created_at ?? "",
|
|
203
|
+
headRepo: parsed?.head?.repo?.full_name ?? "",
|
|
204
|
+
headSha: parsed?.head?.sha ?? "",
|
|
205
|
+
title: parsed?.title ?? "",
|
|
206
|
+
body: typeof parsed?.body === "string" ? parsed.body : ""
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
async function listOpenPrsByBase(base) {
|
|
210
|
+
const { owner, name } = await getRepoInfo();
|
|
211
|
+
const output = await execGh([
|
|
212
|
+
"api",
|
|
213
|
+
`repos/${owner}/${name}/pulls?state=open&base=${encodeURIComponent(base)}&per_page=100`,
|
|
214
|
+
"--paginate"
|
|
215
|
+
]);
|
|
216
|
+
return JSON.parse(output).map(toPrRef);
|
|
217
|
+
}
|
|
201
218
|
async function getPrDetail(prNumber) {
|
|
202
219
|
const { owner, name } = await getRepoInfo();
|
|
203
220
|
return fetchPrRef(owner, name, prNumber);
|
|
@@ -223,7 +240,10 @@ function bodyClosesIssue(body, issueNumber) {
|
|
|
223
240
|
const pattern = new RegExp(`\\b(close[sd]?|fix(?:e[sd])?|resolve[sd]?)\\s*:?\\s*#${issueNumber}\\b(?!\\d)`, "i");
|
|
224
241
|
return pattern.test(body);
|
|
225
242
|
}
|
|
226
|
-
|
|
243
|
+
function bodyMentionsIssue(body, issueNumber) {
|
|
244
|
+
return new RegExp(`#${issueNumber}(?!\\d)`).test(body);
|
|
245
|
+
}
|
|
246
|
+
async function listPrsCrossReferencingIssue(issueNumber, bodyFilter = bodyClosesIssue) {
|
|
227
247
|
const { owner, name } = await getRepoInfo();
|
|
228
248
|
const output = await execGh(["api", `repos/${owner}/${name}/issues/${issueNumber}/timeline`, "--paginate"]);
|
|
229
249
|
const events = JSON.parse(output);
|
|
@@ -235,7 +255,30 @@ async function listPrsCrossReferencingIssue(issueNumber) {
|
|
|
235
255
|
)
|
|
236
256
|
];
|
|
237
257
|
const refs = await Promise.all(numbers.map((number) => fetchPrRef(owner, name, number)));
|
|
238
|
-
return refs.filter(
|
|
258
|
+
return refs.filter(
|
|
259
|
+
(ref) => ref !== null && bodyFilter(ref.body, issueNumber)
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
async function createRemoteBranch(branch, sha) {
|
|
263
|
+
const { owner, name } = await getRepoInfo();
|
|
264
|
+
await execGh([
|
|
265
|
+
"api",
|
|
266
|
+
"-X",
|
|
267
|
+
"POST",
|
|
268
|
+
`repos/${owner}/${name}/git/refs`,
|
|
269
|
+
"-f",
|
|
270
|
+
`ref=refs/heads/${branch}`,
|
|
271
|
+
"-f",
|
|
272
|
+
`sha=${sha}`
|
|
273
|
+
]);
|
|
274
|
+
}
|
|
275
|
+
async function closePullRequest(prNumber) {
|
|
276
|
+
const { owner, name } = await getRepoInfo();
|
|
277
|
+
await execGh(["api", "-X", "PATCH", `repos/${owner}/${name}/pulls/${prNumber}`, "-f", "state=closed"]);
|
|
278
|
+
}
|
|
279
|
+
async function deleteRemoteBranch(branch) {
|
|
280
|
+
const { owner, name } = await getRepoInfo();
|
|
281
|
+
await execGh(["api", "-X", "DELETE", `repos/${owner}/${name}/git/refs/heads/${branch}`]);
|
|
239
282
|
}
|
|
240
283
|
var ADD_CLOSE_ISSUE_REFERENCES = `mutation($issueId: ID!, $prId: ID!) {
|
|
241
284
|
addCloseIssueReferences(input: { issueId: $issueId, pullRequestIds: [$prId] }) { issue { number } }
|
|
@@ -3338,10 +3381,15 @@ export {
|
|
|
3338
3381
|
getIssueBody,
|
|
3339
3382
|
getIssueState,
|
|
3340
3383
|
listPrsClosingIssue,
|
|
3384
|
+
listOpenPrsByBase,
|
|
3341
3385
|
getPrDetail,
|
|
3342
3386
|
closeIssue,
|
|
3343
3387
|
parseClosingIssueNumbers,
|
|
3388
|
+
bodyMentionsIssue,
|
|
3344
3389
|
listPrsCrossReferencingIssue,
|
|
3390
|
+
createRemoteBranch,
|
|
3391
|
+
closePullRequest,
|
|
3392
|
+
deleteRemoteBranch,
|
|
3345
3393
|
linkClosingPr,
|
|
3346
3394
|
getIssueSubIssuesSummary,
|
|
3347
3395
|
listPullRequestsWithChecks,
|
|
@@ -3352,6 +3400,7 @@ export {
|
|
|
3352
3400
|
removeLabel,
|
|
3353
3401
|
commentOnPR,
|
|
3354
3402
|
commentOnIssue,
|
|
3403
|
+
createPullRequest,
|
|
3355
3404
|
createLabel,
|
|
3356
3405
|
parseProjectFilters,
|
|
3357
3406
|
hasProjectFilter,
|
package/dist/gh.d.ts
CHANGED
|
@@ -51,15 +51,26 @@ 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[]>;
|
|
60
|
+
export declare function listOpenPrsByBase(base: string): Promise<(ClosingPrRef & {
|
|
61
|
+
body: string;
|
|
62
|
+
})[]>;
|
|
56
63
|
export declare function getPrDetail(prNumber: number): Promise<(ClosingPrRef & {
|
|
57
64
|
body: string;
|
|
58
65
|
}) | null>;
|
|
59
66
|
export declare function closeIssue(issueNumber: number, reason?: "completed" | "not_planned"): Promise<void>;
|
|
60
67
|
export declare function parseClosingIssueNumbers(body: string): number[];
|
|
61
68
|
export declare function bodyClosesIssue(body: string, issueNumber: number): boolean;
|
|
62
|
-
export declare function
|
|
69
|
+
export declare function bodyMentionsIssue(body: string, issueNumber: number): boolean;
|
|
70
|
+
export declare function listPrsCrossReferencingIssue(issueNumber: number, bodyFilter?: (body: string, issueNumber: number) => boolean): Promise<ClosingPrRef[]>;
|
|
71
|
+
export declare function createRemoteBranch(branch: string, sha: string): Promise<void>;
|
|
72
|
+
export declare function closePullRequest(prNumber: number): Promise<void>;
|
|
73
|
+
export declare function deleteRemoteBranch(branch: string): Promise<void>;
|
|
63
74
|
export declare function linkClosingPr(issueNumber: number, prNumber: number): Promise<void>;
|
|
64
75
|
export declare function findPrNumberClosingIssue(issueNumber: number, expectedHeadRefName: string): Promise<number | null>;
|
|
65
76
|
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,
|
|
@@ -48,6 +53,7 @@ import {
|
|
|
48
53
|
isWorkerDefinition,
|
|
49
54
|
isWorkerEnabled,
|
|
50
55
|
linkClosingPr,
|
|
56
|
+
listOpenPrsByBase,
|
|
51
57
|
listPrsClosingIssue,
|
|
52
58
|
listPrsCrossReferencingIssue,
|
|
53
59
|
loadConfig,
|
|
@@ -65,7 +71,7 @@ import {
|
|
|
65
71
|
shutdown,
|
|
66
72
|
waitForAllProcesses,
|
|
67
73
|
writeLastRun
|
|
68
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-HZHIQMAQ.js";
|
|
69
75
|
import {
|
|
70
76
|
captureConsole
|
|
71
77
|
} from "./chunk-N42YU3GJ.js";
|
|
@@ -289,6 +295,112 @@ var createIssueWorker = createIssuePollingWorker({
|
|
|
289
295
|
}
|
|
290
296
|
});
|
|
291
297
|
|
|
298
|
+
// src/workers/exec-issue.ts
|
|
299
|
+
var REPORT_TAIL_LIMIT = 3e3;
|
|
300
|
+
function formatSessionReport(output) {
|
|
301
|
+
const trimmed = output.trim();
|
|
302
|
+
if (trimmed === "") return "\uFF08\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u51FA\u529B\u306F\u3042\u308A\u307E\u305B\u3093\u3067\u3057\u305F\uFF09";
|
|
303
|
+
const tail = trimmed.length > REPORT_TAIL_LIMIT ? `\u2026\uFF08\u5148\u982D\u3092\u7701\u7565\uFF09
|
|
304
|
+
${trimmed.slice(-REPORT_TAIL_LIMIT)}` : trimmed;
|
|
305
|
+
return ["```", tail, "```"].join("\n");
|
|
306
|
+
}
|
|
307
|
+
function selectOwnedClosingPr(candidates, ctx) {
|
|
308
|
+
const open = candidates.filter((c) => c.state === "MERGED" || c.state === "OPEN");
|
|
309
|
+
if (!ctx.cloud) {
|
|
310
|
+
const found2 = open.find((c) => c.headRefName === ctx.expectedHeadRefName);
|
|
311
|
+
return found2 ? found2.number : null;
|
|
312
|
+
}
|
|
313
|
+
const found = open.find((c) => {
|
|
314
|
+
if (c.baseRefName !== ctx.baseBranch) return false;
|
|
315
|
+
const createdAt = Date.parse(c.createdAt);
|
|
316
|
+
return !Number.isNaN(createdAt) && createdAt >= ctx.startedAt && createdAt <= ctx.now;
|
|
317
|
+
});
|
|
318
|
+
return found ? found.number : null;
|
|
319
|
+
}
|
|
320
|
+
function prMissingComment(worktreeId, output, cloud) {
|
|
321
|
+
const stateSection = cloud ? [
|
|
322
|
+
"## \u72B6\u614B\u306E\u78BA\u8A8D",
|
|
323
|
+
"- \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"
|
|
324
|
+
] : [
|
|
325
|
+
"## \u72B6\u614B\u306E\u78BA\u8A8D",
|
|
326
|
+
`- \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`
|
|
327
|
+
];
|
|
328
|
+
return [
|
|
329
|
+
"## 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",
|
|
330
|
+
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`,
|
|
331
|
+
"",
|
|
332
|
+
"## PR\u3092\u4F5C\u6210\u3057\u306A\u304B\u3063\u305F\u7406\u7531\uFF08\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u6700\u7D42\u5831\u544A\uFF09",
|
|
333
|
+
formatSessionReport(output),
|
|
334
|
+
"",
|
|
335
|
+
...stateSection,
|
|
336
|
+
"",
|
|
337
|
+
"## \u5BFE\u5FDC\u5F8C\u306E\u9032\u3081\u65B9",
|
|
338
|
+
"- \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",
|
|
339
|
+
"- \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"
|
|
340
|
+
].join("\n");
|
|
341
|
+
}
|
|
342
|
+
async function ensurePrTriageMetadata(prNumber) {
|
|
343
|
+
await addLabel("pr", prNumber, "cc-triage-scope").catch(
|
|
344
|
+
(err) => console.error(`[exec-issue] addLabel cc-triage-scope failed for PR #${prNumber}: ${err}`)
|
|
345
|
+
);
|
|
346
|
+
await getCurrentUser().then((user) => addAssignee("pr", prNumber, user)).catch((err) => console.error(`[exec-issue] addAssignee failed for PR #${prNumber}: ${err}`));
|
|
347
|
+
}
|
|
348
|
+
async function verifyPrCreated(issueNumber, worktreeId, output, ctx) {
|
|
349
|
+
if (await hasLabel("issue", issueNumber, "cc-need-human-check")) {
|
|
350
|
+
console.log(`[exec-issue] #${issueNumber}: cc-need-human-check present, skip cc-pr-created`);
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
if (await getIssueState(issueNumber) === "CLOSED") {
|
|
354
|
+
console.log(`[exec-issue] #${issueNumber}: issue closed by skill (no-change path), skip cc-pr-created`);
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
const ownership = {
|
|
358
|
+
cloud: ctx.cloud,
|
|
359
|
+
expectedHeadRefName: worktreeId,
|
|
360
|
+
baseBranch: ctx.baseBranch,
|
|
361
|
+
startedAt: ctx.startedAt,
|
|
362
|
+
now: Date.now()
|
|
363
|
+
};
|
|
364
|
+
let prNumber = null;
|
|
365
|
+
if (!ctx.cloud) {
|
|
366
|
+
prNumber = await findPrNumberByHeadRef(worktreeId, "all");
|
|
367
|
+
}
|
|
368
|
+
if (prNumber === null) {
|
|
369
|
+
prNumber = selectOwnedClosingPr(await listPrsClosingIssue(issueNumber), ownership);
|
|
370
|
+
}
|
|
371
|
+
if (prNumber === null) {
|
|
372
|
+
const candidates = await listPrsCrossReferencingIssue(issueNumber).catch((err) => {
|
|
373
|
+
console.error(`[exec-issue] listPrsCrossReferencingIssue failed for #${issueNumber}: ${err}`);
|
|
374
|
+
return [];
|
|
375
|
+
});
|
|
376
|
+
prNumber = selectOwnedClosingPr(candidates, ownership);
|
|
377
|
+
if (prNumber !== null) {
|
|
378
|
+
await linkClosingPr(issueNumber, prNumber).catch(
|
|
379
|
+
(err) => console.error(`[exec-issue] linkClosingPr failed for #${issueNumber} -> #${prNumber}: ${err}`)
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
if (prNumber !== null) {
|
|
384
|
+
await addLabel("issue", issueNumber, "cc-pr-created");
|
|
385
|
+
await ensurePrTriageMetadata(prNumber);
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
console.error(
|
|
389
|
+
`[exec-issue] #${issueNumber}: session exited without a PR (branch: ${worktreeId}); marking cc-need-human-check`
|
|
390
|
+
);
|
|
391
|
+
await addLabel("issue", issueNumber, "cc-need-human-check");
|
|
392
|
+
await commentOnIssue(issueNumber, prMissingComment(worktreeId, output, ctx.cloud)).catch(
|
|
393
|
+
(err) => console.error(`[exec-issue] commentOnIssue failed for #${issueNumber}: ${err}`)
|
|
394
|
+
);
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
397
|
+
var execIssueWorker = createIssuePollingWorker({
|
|
398
|
+
name: "exec-issue",
|
|
399
|
+
command: "/claude-task-worker:exec-issue",
|
|
400
|
+
triggerLabels: ["cc-exec-issue"],
|
|
401
|
+
onCompleted: verifyPrCreated
|
|
402
|
+
});
|
|
403
|
+
|
|
292
404
|
// src/workers/create-ui-design.ts
|
|
293
405
|
function designPrLabelingFailedComment(issueNumber, prNumber, error, yolo = false) {
|
|
294
406
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -309,6 +421,42 @@ function designPrLabelingFailedComment(issueNumber, prNumber, error, yolo = fals
|
|
|
309
421
|
`- \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
422
|
].join("\n");
|
|
311
423
|
}
|
|
424
|
+
async function adoptCloudDesignPr(issueNumber, branch, ctx) {
|
|
425
|
+
const { owner, name } = await getRepoInfo();
|
|
426
|
+
const candidates = (await listOpenPrsByBase(ctx.baseBranch)).filter(
|
|
427
|
+
(c) => c.headRepo === `${owner}/${name}` && bodyMentionsIssue(c.body, issueNumber)
|
|
428
|
+
);
|
|
429
|
+
const prNumber = selectOwnedClosingPr(candidates, {
|
|
430
|
+
cloud: true,
|
|
431
|
+
expectedHeadRefName: branch,
|
|
432
|
+
baseBranch: ctx.baseBranch,
|
|
433
|
+
startedAt: ctx.startedAt,
|
|
434
|
+
now: Date.now()
|
|
435
|
+
});
|
|
436
|
+
if (prNumber === null) return null;
|
|
437
|
+
const pr = candidates.find((c) => c.number === prNumber);
|
|
438
|
+
if (!pr || pr.headRefName === branch) return prNumber;
|
|
439
|
+
if (!pr.headSha) throw new Error(`design PR #${prNumber} has no head sha`);
|
|
440
|
+
await deleteRemoteBranch(branch).catch(() => {
|
|
441
|
+
});
|
|
442
|
+
await createRemoteBranch(branch, pr.headSha);
|
|
443
|
+
const newPr = await createPullRequest(
|
|
444
|
+
pr.baseRefName,
|
|
445
|
+
branch,
|
|
446
|
+
pr.title || `UI design for #${issueNumber}`,
|
|
447
|
+
pr.body ?? ""
|
|
448
|
+
);
|
|
449
|
+
await commentOnPR(
|
|
450
|
+
prNumber,
|
|
451
|
+
`\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`
|
|
452
|
+
).catch(() => {
|
|
453
|
+
});
|
|
454
|
+
await closePullRequest(prNumber);
|
|
455
|
+
console.log(
|
|
456
|
+
`[create-ui-design] #${issueNumber}: recreated design PR #${prNumber} (${pr.headRefName}) as #${newPr} (${branch})`
|
|
457
|
+
);
|
|
458
|
+
return newPr;
|
|
459
|
+
}
|
|
312
460
|
var createUiDesignWorker = defineWorker({
|
|
313
461
|
name: "create-ui-design",
|
|
314
462
|
kind: "issue",
|
|
@@ -324,7 +472,7 @@ var createUiDesignWorker = defineWorker({
|
|
|
324
472
|
command: "/claude-task-worker:create-ui-design",
|
|
325
473
|
triggerLabels: ["cc-create-ui-design"],
|
|
326
474
|
excludeLabels: ["cc-ui-design-pr-created", "cc-ui-design-ready", "cc-exec-issue", "cc-pr-created"],
|
|
327
|
-
onCompleted: async (issueNumber) => {
|
|
475
|
+
onCompleted: async (issueNumber, _worktreeId, _output, ctx) => {
|
|
328
476
|
if (await hasLabel("issue", issueNumber, "cc-need-human-check")) {
|
|
329
477
|
console.log(`[create-ui-design] #${issueNumber}: cc-need-human-check present, skip cc-ui-design-pr-created`);
|
|
330
478
|
return false;
|
|
@@ -336,7 +484,13 @@ var createUiDesignWorker = defineWorker({
|
|
|
336
484
|
}
|
|
337
485
|
}
|
|
338
486
|
const branch = designBranchName(issueNumber);
|
|
339
|
-
|
|
487
|
+
let prNumber = await findPrNumberByHeadRef(branch, "open");
|
|
488
|
+
if (prNumber === null && ctx.cloud) {
|
|
489
|
+
prNumber = await adoptCloudDesignPr(issueNumber, branch, ctx).catch((err) => {
|
|
490
|
+
console.error(`[create-ui-design] #${issueNumber}: adoptCloudDesignPr failed: ${err}`);
|
|
491
|
+
return null;
|
|
492
|
+
});
|
|
493
|
+
}
|
|
340
494
|
if (prNumber === null) {
|
|
341
495
|
console.error(
|
|
342
496
|
`[create-ui-design] #${issueNumber}: session exited without an open design PR (branch: ${branch}); marking cc-need-human-check`
|
|
@@ -416,112 +570,6 @@ var epicIssueWorker = createIssuePollingWorker({
|
|
|
416
570
|
}
|
|
417
571
|
});
|
|
418
572
|
|
|
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
573
|
// src/workers/fix-review-point.ts
|
|
526
574
|
var fixReviewPointWorker = createPrPollingWorker({
|
|
527
575
|
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;
|