claude-task-worker 0.140.0 → 0.142.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/README.md +18 -7
- package/dist/{chunk-D4BPQ3K3.js → chunk-725IRSKF.js} +37 -40
- package/dist/{chunk-HFU27QHT.js → chunk-BA2CE3L6.js} +39 -2
- package/dist/commands/open-code-review.d.ts +16 -0
- package/dist/{dispatcher-UTBV3L5Z.js → dispatcher-M7ELTAHV.js} +1 -1
- package/dist/gh.d.ts +1 -1
- package/dist/{herdr-runner-TNX2W4G6.js → herdr-runner-S5X5NTFR.js} +1 -1
- package/dist/index.js +91 -25
- package/dist/lib.js +2 -2
- package/dist/random-name.d.ts +0 -1
- package/dist/{table-OOKBQVW5.js → table-EENSXIIT.js} +1 -1
- package/dist/user-config.d.ts +6 -0
- package/dist/workers/exec-issue.d.ts +1 -0
- package/dist/workers/issue-worker.d.ts +2 -0
- package/dist/workers/worker-definition.d.ts +1 -0
- package/dist/worktree.d.ts +0 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -62,6 +62,7 @@ CLI が GitHub ラベルを検知してタスクを起動し、プラグイン
|
|
|
62
62
|
| [CodeGraph](https://www.npmjs.com/package/@colbymchenry/codegraph) | コード探索用インデックス(任意。未導入ならテキスト検索に落ちる) |
|
|
63
63
|
| [Playwright](https://playwright.dev/) のブラウザ(Google Chrome) | Playwright MCP でのブラウザ確認(起動済みの Chrome に CDP `http://localhost:9222` で接続する。Chrome を `--remote-debugging-port=9222 --user-data-dir=<任意のディレクトリ>` 付きで起動しておく)、`.pen` のスナップショット描画 |
|
|
64
64
|
| [DESIGN.md CLI](https://github.com/google-labs-code/design.md) | `DESIGN.md` の lint。`update-design-md` 使用時のみ(未導入でも動く) |
|
|
65
|
+
| [OpenCodeReview](https://github.com/alibaba/open-code-review)(CLI `ocr` と Claude Code プラグイン) | `triage-pr` の PR 差分レビュー(`/open-code-review:delegate-review`。未導入でも動く) |
|
|
65
66
|
| [herdr](https://herdr.dev) | `--project` / `mode: "herdr"` 使用時のみ(`--cloud` は herdr に依存しない) |
|
|
66
67
|
| [GitHub MCP](https://github.com/github/github-mcp-server) | GitHub アクセスの高速化・クラウド実行時のプロキシ制限回避(任意。Claude 側のコネクタで有効化) |
|
|
67
68
|
|
|
@@ -73,7 +74,7 @@ CLI 本体に npm の実行時依存はない(Node.js 標準モジュールの
|
|
|
73
74
|
npx claude-task-worker install
|
|
74
75
|
```
|
|
75
76
|
|
|
76
|
-
マーケットプレイス追加・プラグイン導入・CLI 本体のグローバルインストール・各種 CLI(CodeGraph / DESIGN.md /
|
|
77
|
+
マーケットプレイス追加・プラグイン導入・CLI 本体のグローバルインストール・各種 CLI(CodeGraph / DESIGN.md / OpenCodeReview)・OpenCodeReview プラグインの導入と Playwright ブラウザの取得を一括で行う。いずれかが失敗しても処理は継続する。インストール後、Claude Code のセッションを再起動するとプラグインが有効になる。
|
|
77
78
|
|
|
78
79
|
個別にやる場合:
|
|
79
80
|
|
|
@@ -126,7 +127,7 @@ claude-task-worker apply-labels # ラベルだけを作成(冪等)
|
|
|
126
127
|
## コマンド
|
|
127
128
|
|
|
128
129
|
```bash
|
|
129
|
-
claude-task-worker <command> [--epic <issue-number>]... [--label <label>]... [--project <name>]... [--cloud] [--debug]
|
|
130
|
+
claude-task-worker <command> [--epic <issue-number>]... [--label <label>]... [--exclude-label <label>]... [--project <name>]... [--cloud] [--debug]
|
|
130
131
|
```
|
|
131
132
|
|
|
132
133
|
| コマンド | 内容 |
|
|
@@ -154,12 +155,22 @@ claude-task-worker all --epic 100 --epic 200
|
|
|
154
155
|
|
|
155
156
|
### `--label <label>`
|
|
156
157
|
|
|
157
|
-
トリガーラベルに加えて指定ラベルが付いた Issue
|
|
158
|
+
トリガーラベルに加えて指定ラベルが付いた Issue・PR のみに絞る(Issue 系・PR 系ワーカーの両方に効く)。`exec-issue` / `epic-issue` / `create-ui-design` が Issue から作った PR にも同じラベルを付けるので、後続の PR 系ワーカーが拾える。複数指定は AND。`--epic` と併用可能。
|
|
158
159
|
|
|
159
160
|
```bash
|
|
160
161
|
claude-task-worker all --label priority-high --label needs-design
|
|
161
162
|
```
|
|
162
163
|
|
|
164
|
+
### `--exclude-label <label>`
|
|
165
|
+
|
|
166
|
+
指定ラベルが付いた Issue・PR を対象から外す(Issue 系・PR 系ワーカーの両方に効く。定期ワーカーは対象を持たないため無関係)。複数指定は AND で、どれか1つでも付いていれば外れる。
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
claude-task-worker all --exclude-label wip --exclude-label on-hold
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
`--label` / `--exclude-label` は `config.json` の `projects` にプロジェクトごとの既定を書ける(下記)。`--project` 経由の起動でだけ CLI の指定に足し込まれる。
|
|
173
|
+
|
|
163
174
|
### `--project <name>`
|
|
164
175
|
|
|
165
176
|
指定したプロジェクト(またはグループ、`all`)へ [herdr](https://herdr.dev) 経由でコマンドをディスパッチする。CLI はワーカーを直接実行せず、プロジェクトごとに独立した herdr ワークスペースを作ってそこでコマンドを実行し、稼働状況をステータステーブルに表示する。SIGTERM/SIGINT で全セッションを一括停止する。
|
|
@@ -272,7 +283,7 @@ node plugin/scripts/pen.mjs render design.pen --out out/ # Chrome で描画し
|
|
|
272
283
|
"permission": "bypassPermissions",
|
|
273
284
|
"projects": {
|
|
274
285
|
"app-a": "/Users/me/repos/app-a",
|
|
275
|
-
"app-b": "/Users/me/repos/app-b"
|
|
286
|
+
"app-b": { "path": "/Users/me/repos/app-b", "label": ["priority-high"], "excludeLabel": ["wip"] }
|
|
276
287
|
},
|
|
277
288
|
"projectGroups": {
|
|
278
289
|
"frontend": ["app-a", "app-b"]
|
|
@@ -282,13 +293,13 @@ node plugin/scripts/pen.mjs render design.pen --out out/ # Chrome で描画し
|
|
|
282
293
|
|
|
283
294
|
| キー | 既定 | 説明 |
|
|
284
295
|
|---|---|---|
|
|
285
|
-
| `projects` | - | プロジェクト名 →
|
|
296
|
+
| `projects` | - | プロジェクト名 → 絶対パス、または `{ path, label, excludeLabel }`。`label` / `excludeLabel` は `--label` / `--exclude-label` と同じ意味で、`--project` でそのプロジェクトを指定して起動したワーカーにだけ足し込まれる(`--project` なしの起動には適用しない)。`path` の重複は可 |
|
|
286
297
|
| `projectGroups` | `{}` | グループ名 → プロジェクト名配列 |
|
|
287
298
|
| `mode` | `"default"` | `"default"`: `claude -p` の子プロセスとして実行 / `"herdr"`: herdr のタブ内で TUI 起動し、実行中の様子を覗ける(`--project` はこちらが必要) |
|
|
288
299
|
| `advisor` | `false` | `true` で `--advisor <model>` を渡す。モデルは `claude-task-worker.json` の `advisorModel` |
|
|
289
300
|
| `permission` | `"bypassPermissions"` | Claude CLI の[権限モード](https://code.claude.com/docs/ja/permission-modes)(`bypassPermissions` / `dontAsk` / `auto` / `acceptEdits` / `manual` / `plan`) |
|
|
290
301
|
|
|
291
|
-
|
|
302
|
+
`projects` 以外はいずれもトップレベル一括で、プロジェクト単位・ワーカー単位の指定はできない。`permission` はワーカーに承認するユーザーがいないため、`bypassPermissions` / `dontAsk` 以外ではタスクが承認待ちで止まりうる。
|
|
292
303
|
|
|
293
304
|
> ℹ️ `mode: "herdr"` の完了通知音はワーカー側から止められない。無音にするには `~/.config/herdr/config.toml` に `[ui.sound] enabled = false` を書いて `herdr server reload-config` する(herdr サーバー全体に効く)。
|
|
294
305
|
|
|
@@ -423,7 +434,7 @@ claude-task-worker all
|
|
|
423
434
|
|
|
424
435
|
## プロセス管理
|
|
425
436
|
|
|
426
|
-
実行中のタスクはリアルタイムのステータステーブルで表示される(タスクID・タイトル・ステータス・開始時刻・経過時間)。SIGTERM/SIGINT で graceful shutdown し、もう一度送ると強制終了してラベル・worktree の後片付けを試みる。前回の異常終了で残った worktree
|
|
437
|
+
実行中のタスクはリアルタイムのステータステーブルで表示される(タスクID・タイトル・ステータス・開始時刻・経過時間)。SIGTERM/SIGINT で graceful shutdown し、もう一度送ると強制終了してラベル・worktree の後片付けを試みる。前回の異常終了で残った worktree は自動回収しない(同じ path のプロジェクトを並走させたとき他プロセスの作業中 worktree を消さないため)。不要なら `.claude/worktrees/` 配下を `git worktree remove` で手動削除する。
|
|
427
438
|
|
|
428
439
|
ワーカーは応答するユーザーがいない状態でスキルを起動するため、処理が未完のままラベルだけ進む事故を防ぐガードを持つ(バックグラウンド実行と対話系ツールの無効化、自律実行原則のシステムプロンプト注入、PR 実在の完了検証、空出力セッションの失敗扱い、`Stop` フックによる残留プロセスの停止)。
|
|
429
440
|
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
pushLogLine,
|
|
17
17
|
selectRecentTasks,
|
|
18
18
|
writeScreen
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-BA2CE3L6.js";
|
|
20
20
|
|
|
21
21
|
// src/gh.ts
|
|
22
22
|
import { createRequire } from "node:module";
|
|
@@ -365,7 +365,7 @@ function excludePrsByLabels(prs, excludeLabels) {
|
|
|
365
365
|
return prs.filter((pr) => !pr.labels.some((l) => excludeLabels.includes(l.name)));
|
|
366
366
|
}
|
|
367
367
|
var PR_LIST_FETCH_LIMIT = 50;
|
|
368
|
-
async function listPullRequestsWithChecks(assignee, label, excludeLabels = [], limit = 5) {
|
|
368
|
+
async function listPullRequestsWithChecks(assignee, label, excludeLabels = [], limit = 5, searchExcludeLabels = []) {
|
|
369
369
|
const args = [
|
|
370
370
|
"pr",
|
|
371
371
|
"list",
|
|
@@ -374,18 +374,22 @@ async function listPullRequestsWithChecks(assignee, label, excludeLabels = [], l
|
|
|
374
374
|
"--json",
|
|
375
375
|
"number,title,labels,headRefName",
|
|
376
376
|
"--search",
|
|
377
|
-
"sort:created-asc",
|
|
377
|
+
["sort:created-asc", ...searchExcludeLabels.map((l) => `-label:"${l}"`)].join(" "),
|
|
378
378
|
"--limit",
|
|
379
379
|
String(PR_LIST_FETCH_LIMIT)
|
|
380
380
|
];
|
|
381
381
|
if (assignee) {
|
|
382
382
|
args.push("--assignee", assignee);
|
|
383
383
|
}
|
|
384
|
-
|
|
385
|
-
|
|
384
|
+
for (const l of [label ?? []].flat()) {
|
|
385
|
+
if (!l) continue;
|
|
386
|
+
args.push("--label", l);
|
|
386
387
|
}
|
|
387
388
|
const output = await execGh(args);
|
|
388
|
-
const prs = excludePrsByLabels(JSON.parse(output), excludeLabels).slice(
|
|
389
|
+
const prs = excludePrsByLabels(JSON.parse(output), [...excludeLabels, ...searchExcludeLabels]).slice(
|
|
390
|
+
0,
|
|
391
|
+
limit
|
|
392
|
+
);
|
|
389
393
|
const withChecks = await Promise.all(prs.map(async (pr) => ({ ...pr, checks: await fetchPRChecks(pr.number) })));
|
|
390
394
|
return withChecks.filter((pr) => isCICompleted(pr.checks));
|
|
391
395
|
}
|
|
@@ -1552,7 +1556,7 @@ function resolveProjectName(cwd = process.cwd()) {
|
|
|
1552
1556
|
return findProjectNameByPath(cwd) ?? basename(cwd);
|
|
1553
1557
|
}
|
|
1554
1558
|
async function runViaHerdr(args, prompt, id, onComplete, cwd, env) {
|
|
1555
|
-
const { startHerdrTask, stopHerdrTask, taskTabLabel, waitForHerdrTask } = await import("./herdr-runner-
|
|
1559
|
+
const { startHerdrTask, stopHerdrTask, taskTabLabel, waitForHerdrTask } = await import("./herdr-runner-S5X5NTFR.js");
|
|
1556
1560
|
const { getCurrentWorkspaceId } = await import("./herdr-NDLUM6JF.js");
|
|
1557
1561
|
const label = taskTabLabel(resolveProjectName(), id);
|
|
1558
1562
|
let task;
|
|
@@ -1678,7 +1682,7 @@ async function flagOrphanedCloudSession(target, reason, cloudSessionId) {
|
|
|
1678
1682
|
});
|
|
1679
1683
|
}
|
|
1680
1684
|
async function createCloudSession(args, initialPrompt, cwd, env) {
|
|
1681
|
-
const { extractCloudSessionId, normalizePtyOutput } = await import("./herdr-runner-
|
|
1685
|
+
const { extractCloudSessionId, normalizePtyOutput } = await import("./herdr-runner-S5X5NTFR.js");
|
|
1682
1686
|
const spec = buildScriptCommand("claude", buildCloudCreateArgs(args, initialPrompt));
|
|
1683
1687
|
const child = spawn(spec.command, spec.args, {
|
|
1684
1688
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -2134,9 +2138,6 @@ function generateWorktreeName() {
|
|
|
2134
2138
|
const suffix = String(randomInt(1e4)).padStart(4, "0");
|
|
2135
2139
|
return `${pick(ADJECTIVES)}-${pick(NOUNS)}-${suffix}`;
|
|
2136
2140
|
}
|
|
2137
|
-
function isGeneratedWorktreeName(name) {
|
|
2138
|
-
return /^[a-z]+-[a-z]+-\d{4}$/.test(name);
|
|
2139
|
-
}
|
|
2140
2141
|
|
|
2141
2142
|
// src/slack.ts
|
|
2142
2143
|
import { exec } from "node:child_process";
|
|
@@ -2409,7 +2410,7 @@ async function notifyError(workerName, repoName, error) {
|
|
|
2409
2410
|
// src/worktree.ts
|
|
2410
2411
|
import { createRequire as createRequire2 } from "node:module";
|
|
2411
2412
|
import { promisify as promisify3 } from "node:util";
|
|
2412
|
-
import {
|
|
2413
|
+
import { rm, stat } from "node:fs/promises";
|
|
2413
2414
|
import { basename as basename2, resolve as resolve2, sep } from "node:path";
|
|
2414
2415
|
var childProcess2 = createRequire2(import.meta.url)("node:child_process");
|
|
2415
2416
|
var execFileAsync2 = (command, args) => promisify3(childProcess2.execFile)(command, args);
|
|
@@ -2549,29 +2550,6 @@ async function removeWorktreeByBranch(branchName) {
|
|
|
2549
2550
|
console.error(`[worktree] Failed to remove worktree for branch ${branchName}:`, error);
|
|
2550
2551
|
}
|
|
2551
2552
|
}
|
|
2552
|
-
async function removeStaleWorktrees() {
|
|
2553
|
-
const worktreeIds = /* @__PURE__ */ new Set();
|
|
2554
|
-
try {
|
|
2555
|
-
for (const name of await readdir(WORKTREES_DIR)) {
|
|
2556
|
-
if (isGeneratedWorktreeName(name)) worktreeIds.add(name);
|
|
2557
|
-
}
|
|
2558
|
-
} catch {
|
|
2559
|
-
}
|
|
2560
|
-
try {
|
|
2561
|
-
for (const entry of await listWorktreeEntries()) {
|
|
2562
|
-
if (!isManagedWorktreePath(entry.path)) continue;
|
|
2563
|
-
const worktreeId = basename2(entry.path);
|
|
2564
|
-
if (isGeneratedWorktreeName(worktreeId)) worktreeIds.add(worktreeId);
|
|
2565
|
-
}
|
|
2566
|
-
} catch (error) {
|
|
2567
|
-
console.error(`[worktree] Failed to list worktrees:`, error);
|
|
2568
|
-
}
|
|
2569
|
-
for (const worktreeId of worktreeIds) {
|
|
2570
|
-
if (isWorktreeInUse(worktreeId)) continue;
|
|
2571
|
-
console.log(`[worktree] Removing stale worktree: ${worktreeId}`);
|
|
2572
|
-
await removeWorktree(worktreeId);
|
|
2573
|
-
}
|
|
2574
|
-
}
|
|
2575
2553
|
|
|
2576
2554
|
// src/workers/worker-definition.ts
|
|
2577
2555
|
var WORKER_DEFINITION = /* @__PURE__ */ Symbol.for("claude-task-worker.worker-definition");
|
|
@@ -2587,6 +2565,13 @@ function isWorkerDefinition(value) {
|
|
|
2587
2565
|
|
|
2588
2566
|
// src/workers/issue-worker.ts
|
|
2589
2567
|
var STICKY_LABELS = ["cc-triage-scope", "cc-issue-created"];
|
|
2568
|
+
async function carryLabelFiltersToPr(workerName, prNumber, labelFilters = []) {
|
|
2569
|
+
for (const label of labelFilters) {
|
|
2570
|
+
await addLabel("pr", prNumber, label).catch(
|
|
2571
|
+
(err) => console.error(`[${workerName}] addLabel ${label} failed for PR #${prNumber}: ${err}`)
|
|
2572
|
+
);
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2590
2575
|
var consumableTriggerLabels = (triggerLabels) => triggerLabels.filter((label) => !STICKY_LABELS.includes(label));
|
|
2591
2576
|
var PREFLIGHT_SEARCH_LIMIT = 5;
|
|
2592
2577
|
function createIssuePollingWorker(config) {
|
|
@@ -2607,7 +2592,12 @@ function createIssuePollingWorker(config) {
|
|
|
2607
2592
|
if (isShuttingDown()) return;
|
|
2608
2593
|
if (cooldownMs > 0 && lastCompletionAt > 0 && Date.now() - lastCompletionAt < cooldownMs) return;
|
|
2609
2594
|
try {
|
|
2610
|
-
const excludeLabels = [
|
|
2595
|
+
const excludeLabels = [
|
|
2596
|
+
"cc-in-progress",
|
|
2597
|
+
"cc-need-human-check",
|
|
2598
|
+
...config.excludeLabels ?? [],
|
|
2599
|
+
...opts.excludeLabelFilters ?? []
|
|
2600
|
+
];
|
|
2611
2601
|
const epicFilter = config.epicFilterTarget !== "self" && epicFilters && epicFilters.length > 0 ? { owner, repo: name, numbers: epicFilters } : void 0;
|
|
2612
2602
|
const labels = labelFilters && labelFilters.length > 0 ? [...config.triggerLabels, ...labelFilters] : config.triggerLabels;
|
|
2613
2603
|
const { maxConcurrentTasks } = getWorkerConfig(config.name);
|
|
@@ -2701,7 +2691,8 @@ function createIssuePollingWorker(config) {
|
|
|
2701
2691
|
const verified = await config.onCompleted?.(issue.number, worktreeId, output, {
|
|
2702
2692
|
cloud,
|
|
2703
2693
|
baseBranch,
|
|
2704
|
-
startedAt
|
|
2694
|
+
startedAt,
|
|
2695
|
+
labelFilters: labelFilters ?? []
|
|
2705
2696
|
}) ?? true;
|
|
2706
2697
|
if (verified === false) {
|
|
2707
2698
|
await notifyTaskFailed(
|
|
@@ -2794,7 +2785,7 @@ function createIssuePollingWorker(config) {
|
|
|
2794
2785
|
var LABEL_IN_PROGRESS = "cc-in-progress";
|
|
2795
2786
|
var LABEL_TRIAGE_SCOPE = "cc-triage-scope";
|
|
2796
2787
|
function createPrPollingWorker(config) {
|
|
2797
|
-
const start = async () => {
|
|
2788
|
+
const start = async (opts = {}) => {
|
|
2798
2789
|
const { owner, name, defaultBranch } = await getRepoInfo();
|
|
2799
2790
|
const user = await getCurrentUser();
|
|
2800
2791
|
const { pollingIntervalSeconds, cooldownSeconds } = getWorkerConfig(config.name);
|
|
@@ -2809,7 +2800,13 @@ function createPrPollingWorker(config) {
|
|
|
2809
2800
|
if (cooldownMs > 0 && lastCompletionAt > 0 && Date.now() - lastCompletionAt < cooldownMs) return;
|
|
2810
2801
|
try {
|
|
2811
2802
|
const excludeLabels = [LABEL_IN_PROGRESS, ...config.excludeLabels ?? []];
|
|
2812
|
-
const candidates = await listPullRequestsWithChecks(
|
|
2803
|
+
const candidates = await listPullRequestsWithChecks(
|
|
2804
|
+
user,
|
|
2805
|
+
[config.triggerLabel, ...opts.labelFilters ?? []],
|
|
2806
|
+
excludeLabels,
|
|
2807
|
+
void 0,
|
|
2808
|
+
opts.excludeLabelFilters ?? []
|
|
2809
|
+
);
|
|
2813
2810
|
for (const pr of candidates) {
|
|
2814
2811
|
if (isRunning(pr.number)) continue;
|
|
2815
2812
|
if (isWorkerAtCapacity(config.name)) break;
|
|
@@ -3211,9 +3208,9 @@ export {
|
|
|
3211
3208
|
createWorktreeFromBranch,
|
|
3212
3209
|
removeWorktree,
|
|
3213
3210
|
removeWorktreeByBranch,
|
|
3214
|
-
removeStaleWorktrees,
|
|
3215
3211
|
defineWorker,
|
|
3216
3212
|
isWorkerDefinition,
|
|
3213
|
+
carryLabelFiltersToPr,
|
|
3217
3214
|
createIssuePollingWorker,
|
|
3218
3215
|
createPrPollingWorker,
|
|
3219
3216
|
publishLastRunPr,
|
|
@@ -203,10 +203,13 @@ function loadUserConfig() {
|
|
|
203
203
|
);
|
|
204
204
|
}
|
|
205
205
|
const projects = {};
|
|
206
|
-
|
|
206
|
+
const projectLabelFilters = {};
|
|
207
|
+
for (const [name, entry] of Object.entries(rawProjects)) {
|
|
207
208
|
if (name === "__proto__") {
|
|
208
209
|
throw new UserConfigError(`"__proto__" cannot be used as a key in "projects": ${path}`);
|
|
209
210
|
}
|
|
211
|
+
const isObjectEntry = typeof entry === "object" && entry !== null && !Array.isArray(entry);
|
|
212
|
+
const value = isObjectEntry ? entry["path"] : entry;
|
|
210
213
|
if (typeof value !== "string" || !isAbsolute(value)) {
|
|
211
214
|
console.warn(`[config] invalid projects.${name}: expected an absolute path, skipping`);
|
|
212
215
|
continue;
|
|
@@ -216,6 +219,18 @@ function loadUserConfig() {
|
|
|
216
219
|
continue;
|
|
217
220
|
}
|
|
218
221
|
projects[name] = value;
|
|
222
|
+
if (isObjectEntry) {
|
|
223
|
+
const obj = entry;
|
|
224
|
+
for (const key of Object.keys(obj)) {
|
|
225
|
+
if (!PROJECT_ENTRY_KEYS.includes(key)) {
|
|
226
|
+
console.warn(`[config] unknown key "${key}" in projects.${name}, ignoring`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
projectLabelFilters[name] = {
|
|
230
|
+
label: parseLabelList(obj["label"], `projects.${name}.label`),
|
|
231
|
+
excludeLabel: parseLabelList(obj["excludeLabel"], `projects.${name}.excludeLabel`)
|
|
232
|
+
};
|
|
233
|
+
}
|
|
219
234
|
}
|
|
220
235
|
const projectGroups = {};
|
|
221
236
|
for (const [groupName, value] of Object.entries(rawProjectGroups)) {
|
|
@@ -236,7 +251,16 @@ function loadUserConfig() {
|
|
|
236
251
|
}
|
|
237
252
|
projectGroups[groupName] = members;
|
|
238
253
|
}
|
|
239
|
-
return { mode, advisor, permission, projects, projectGroups };
|
|
254
|
+
return { mode, advisor, permission, projects, projectGroups, projectLabelFilters };
|
|
255
|
+
}
|
|
256
|
+
var PROJECT_ENTRY_KEYS = ["path", "label", "excludeLabel"];
|
|
257
|
+
function parseLabelList(value, key) {
|
|
258
|
+
if (value === void 0) return [];
|
|
259
|
+
if (Array.isArray(value) && value.every((v) => typeof v === "string" && v.length > 0)) return value;
|
|
260
|
+
console.warn(
|
|
261
|
+
`[config] invalid ${key}: expected an array of non-empty strings, got ${JSON.stringify(value)}, ignoring`
|
|
262
|
+
);
|
|
263
|
+
return [];
|
|
240
264
|
}
|
|
241
265
|
var cachedRunMode;
|
|
242
266
|
function getRunMode() {
|
|
@@ -292,6 +316,18 @@ function findProjectNameByPath(path) {
|
|
|
292
316
|
}
|
|
293
317
|
return void 0;
|
|
294
318
|
}
|
|
319
|
+
function findProjectLabelFilters(projectName = process.env.CTW_PROJECT_NAME) {
|
|
320
|
+
const empty = { label: [], excludeLabel: [] };
|
|
321
|
+
if (!projectName) return empty;
|
|
322
|
+
let config;
|
|
323
|
+
try {
|
|
324
|
+
config = loadUserConfig();
|
|
325
|
+
} catch (err) {
|
|
326
|
+
console.warn(`[config] failed to read config file, project label filters are not applied: ${err}`);
|
|
327
|
+
return empty;
|
|
328
|
+
}
|
|
329
|
+
return Object.prototype.hasOwnProperty.call(config.projectLabelFilters, projectName) ? config.projectLabelFilters[projectName] : empty;
|
|
330
|
+
}
|
|
295
331
|
function resolveTargetProjects(requested, config) {
|
|
296
332
|
const resolved = /* @__PURE__ */ new Map();
|
|
297
333
|
for (const name of requested) {
|
|
@@ -558,6 +594,7 @@ export {
|
|
|
558
594
|
isAdvisorEnabled,
|
|
559
595
|
getPermissionMode,
|
|
560
596
|
findProjectNameByPath,
|
|
597
|
+
findProjectLabelFilters,
|
|
561
598
|
resolveTargetProjects,
|
|
562
599
|
getDisplayWidth,
|
|
563
600
|
truncateToWidth,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const OCR_PACKAGE = "@alibaba-group/open-code-review";
|
|
2
|
+
export declare const OCR_MARKETPLACE_SOURCE = "alibaba/open-code-review";
|
|
3
|
+
export declare const OCR_MARKETPLACE_NAME = "open-code-review";
|
|
4
|
+
export declare const OCR_PLUGIN = "open-code-review@open-code-review";
|
|
5
|
+
/**
|
|
6
|
+
* OpenCodeReview(OCR)の CLI と Claude Code プラグインを導入/更新する。
|
|
7
|
+
*
|
|
8
|
+
* `triage-pr` スキルが `/open-code-review:delegate-review`(OCR はファイル選定とルール解決だけを行い、
|
|
9
|
+
* レビュー自体はホストの claude が行う)でPRをレビューするため、CLI(`ocr`)とプラグインの両方が要る。
|
|
10
|
+
* delegate モードは OCR 側で LLM を呼ばないので、`ocr config provider` 等の LLM 設定は不要。
|
|
11
|
+
*
|
|
12
|
+
* CLI は self-upgrade 機構を持たないため install / update とも `npm install -g <pkg>@latest`。
|
|
13
|
+
* プラグインは install ならマーケットプレイス追加 → インストール、update ならマーケットプレイス更新 →
|
|
14
|
+
* プラグイン更新(未導入で更新に失敗した場合はインストールへフォールバック)。
|
|
15
|
+
*/
|
|
16
|
+
export declare function installOpenCodeReview(logPrefix: "install" | "update"): Promise<boolean>;
|
|
@@ -3,7 +3,7 @@ async function loadHerdr() {
|
|
|
3
3
|
return await import("./herdr-NDLUM6JF.js");
|
|
4
4
|
}
|
|
5
5
|
async function loadTable() {
|
|
6
|
-
return await import("./table-
|
|
6
|
+
return await import("./table-EENSXIIT.js");
|
|
7
7
|
}
|
|
8
8
|
var { getDisplayWidth, truncateToWidth, padToWidth, buildLogTableLines, logLines, writeScreen } = await loadTable();
|
|
9
9
|
var POLL_INTERVAL_MS = 7 * 1e3;
|
package/dist/gh.d.ts
CHANGED
|
@@ -90,7 +90,7 @@ export declare function excludePrsByLabels<T extends {
|
|
|
90
90
|
name: string;
|
|
91
91
|
}[];
|
|
92
92
|
}>(prs: T[], excludeLabels: string[]): T[];
|
|
93
|
-
export declare function listPullRequestsWithChecks(assignee?: string, label?: string, excludeLabels?: string[], limit?: number): Promise<PullRequestWithChecks[]>;
|
|
93
|
+
export declare function listPullRequestsWithChecks(assignee?: string, label?: string | string[], excludeLabels?: string[], limit?: number, searchExcludeLabels?: string[]): Promise<PullRequestWithChecks[]>;
|
|
94
94
|
export declare function addLabel(type: "issue" | "pr", number: number, label: string): Promise<void>;
|
|
95
95
|
export declare function addAssignee(type: "issue" | "pr", number: number, login: string): Promise<void>;
|
|
96
96
|
export declare function hasLabel(type: "issue" | "pr", number: number, label: string): Promise<boolean>;
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
bodyMentionsIssue,
|
|
14
14
|
buildScriptCommand,
|
|
15
15
|
buildTokenLimitText,
|
|
16
|
+
carryLabelFiltersToPr,
|
|
16
17
|
checkCloudConfig,
|
|
17
18
|
closeIssue,
|
|
18
19
|
closePullRequest,
|
|
@@ -55,7 +56,6 @@ import {
|
|
|
55
56
|
parseClosingIssueNumbers,
|
|
56
57
|
partitionEnabledWorkers,
|
|
57
58
|
remoteTrackingSha,
|
|
58
|
-
removeStaleWorktrees,
|
|
59
59
|
renderTable,
|
|
60
60
|
resolveInheritConfigSource,
|
|
61
61
|
resolveWorkerFilePath,
|
|
@@ -65,13 +65,14 @@ import {
|
|
|
65
65
|
shutdown,
|
|
66
66
|
waitForAllProcesses,
|
|
67
67
|
writeLastRun
|
|
68
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-725IRSKF.js";
|
|
69
69
|
import {
|
|
70
70
|
UserConfigError,
|
|
71
71
|
assertCloudCompatibleCommand,
|
|
72
72
|
assertProjectCompatibleCommand,
|
|
73
73
|
buildForwardedCommand,
|
|
74
74
|
captureConsole,
|
|
75
|
+
findProjectLabelFilters,
|
|
75
76
|
getInheritConfigPath,
|
|
76
77
|
getRunMode,
|
|
77
78
|
hasCloudFlag,
|
|
@@ -79,7 +80,7 @@ import {
|
|
|
79
80
|
loadUserConfig,
|
|
80
81
|
parseProjectFilters,
|
|
81
82
|
resolveTargetProjects
|
|
82
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-BA2CE3L6.js";
|
|
83
84
|
import {
|
|
84
85
|
npmInstallGlobalLatest,
|
|
85
86
|
runCommand
|
|
@@ -355,7 +356,8 @@ function prMissingComment(worktreeId, output, cloud) {
|
|
|
355
356
|
"- \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"
|
|
356
357
|
].join("\n");
|
|
357
358
|
}
|
|
358
|
-
async function ensurePrTriageMetadata(prNumber) {
|
|
359
|
+
async function ensurePrTriageMetadata(prNumber, labelFilters) {
|
|
360
|
+
await carryLabelFiltersToPr("exec-issue", prNumber, labelFilters);
|
|
359
361
|
await addLabel("pr", prNumber, "cc-triage-scope").catch(
|
|
360
362
|
(err) => console.error(`[exec-issue] addLabel cc-triage-scope failed for PR #${prNumber}: ${err}`)
|
|
361
363
|
);
|
|
@@ -398,7 +400,7 @@ async function verifyPrCreated(issueNumber, worktreeId, output, ctx) {
|
|
|
398
400
|
}
|
|
399
401
|
if (prNumber !== null) {
|
|
400
402
|
await addLabel("issue", issueNumber, "cc-pr-created");
|
|
401
|
-
await ensurePrTriageMetadata(prNumber);
|
|
403
|
+
await ensurePrTriageMetadata(prNumber, ctx.labelFilters);
|
|
402
404
|
return;
|
|
403
405
|
}
|
|
404
406
|
console.error(
|
|
@@ -534,6 +536,7 @@ var createUiDesignWorker = defineWorker({
|
|
|
534
536
|
}
|
|
535
537
|
try {
|
|
536
538
|
await addLabel("pr", prNumber, "cc-ui-design");
|
|
539
|
+
await carryLabelFiltersToPr("create-ui-design", prNumber, ctx.labelFilters);
|
|
537
540
|
if (yolo) {
|
|
538
541
|
await addLabel("pr", prNumber, "cc-triage-scope");
|
|
539
542
|
} else {
|
|
@@ -584,7 +587,7 @@ var epicIssueWorker = createIssuePollingWorker({
|
|
|
584
587
|
if (summary.completed !== summary.total) return "skip";
|
|
585
588
|
return "proceed";
|
|
586
589
|
},
|
|
587
|
-
onCompleted: async (issueNumber) => {
|
|
590
|
+
onCompleted: async (issueNumber, _worktreeId, _output, ctx) => {
|
|
588
591
|
const prNumber = await findOpenPrNumberByHeadRef(`cc-epic-${issueNumber}`);
|
|
589
592
|
if (prNumber === null) {
|
|
590
593
|
console.error(`[epic-issue] Epic PR for branch cc-epic-${issueNumber} not found; skip cc-pr-created`);
|
|
@@ -597,6 +600,7 @@ var epicIssueWorker = createIssuePollingWorker({
|
|
|
597
600
|
await addLabel("issue", issueNumber, "cc-pr-created");
|
|
598
601
|
await addLabel("pr", prNumber, "cc-epic-issue");
|
|
599
602
|
await addLabel("pr", prNumber, "cc-triage-scope");
|
|
603
|
+
await carryLabelFiltersToPr("epic-issue", prNumber, ctx.labelFilters);
|
|
600
604
|
await getCurrentUser().then((user) => addAssignee("pr", prNumber, user)).catch((err) => console.error(`[epic-issue] addAssignee failed for PR #${prNumber}: ${err}`));
|
|
601
605
|
}
|
|
602
606
|
});
|
|
@@ -1113,10 +1117,60 @@ async function installDesignMdCli(logPrefix) {
|
|
|
1113
1117
|
}
|
|
1114
1118
|
}
|
|
1115
1119
|
|
|
1116
|
-
// src/commands/
|
|
1120
|
+
// src/commands/open-code-review.ts
|
|
1117
1121
|
async function loadRunCommand3() {
|
|
1118
1122
|
return await import("./run-command-O2TMRPZK.js");
|
|
1119
1123
|
}
|
|
1124
|
+
var OCR_PACKAGE = "@alibaba-group/open-code-review";
|
|
1125
|
+
var OCR_MARKETPLACE_SOURCE = "alibaba/open-code-review";
|
|
1126
|
+
var OCR_MARKETPLACE_NAME = "open-code-review";
|
|
1127
|
+
var OCR_PLUGIN = "open-code-review@open-code-review";
|
|
1128
|
+
async function installOpenCodeReview(logPrefix) {
|
|
1129
|
+
const { npmInstallGlobalLatest: npmInstallGlobalLatest2, runCommand: runCommand2 } = await loadRunCommand3();
|
|
1130
|
+
let ok = true;
|
|
1131
|
+
console.log(`[${logPrefix}] Installing OpenCodeReview CLI (npm install -g ${OCR_PACKAGE}@latest)...`);
|
|
1132
|
+
try {
|
|
1133
|
+
await npmInstallGlobalLatest2(OCR_PACKAGE);
|
|
1134
|
+
console.log(`[${logPrefix}] OpenCodeReview CLI installed.`);
|
|
1135
|
+
} catch (err) {
|
|
1136
|
+
console.error(`[${logPrefix}] Failed to install OpenCodeReview CLI: ${err.message}`);
|
|
1137
|
+
ok = false;
|
|
1138
|
+
}
|
|
1139
|
+
const addAndInstall = async () => {
|
|
1140
|
+
try {
|
|
1141
|
+
await runCommand2("claude", ["plugin", "marketplace", "add", OCR_MARKETPLACE_SOURCE]);
|
|
1142
|
+
} catch (err) {
|
|
1143
|
+
console.error(
|
|
1144
|
+
`[${logPrefix}] Failed to add marketplace ${OCR_MARKETPLACE_SOURCE} (already added is expected and safe to ignore): ${err.message}`
|
|
1145
|
+
);
|
|
1146
|
+
}
|
|
1147
|
+
await runCommand2("claude", ["plugin", "install", OCR_PLUGIN]);
|
|
1148
|
+
};
|
|
1149
|
+
console.log(`[${logPrefix}] ${logPrefix === "install" ? "Installing" : "Updating"} plugin: ${OCR_PLUGIN}...`);
|
|
1150
|
+
try {
|
|
1151
|
+
if (logPrefix === "install") {
|
|
1152
|
+
await addAndInstall();
|
|
1153
|
+
} else {
|
|
1154
|
+
try {
|
|
1155
|
+
await runCommand2("claude", ["plugin", "marketplace", "update", OCR_MARKETPLACE_NAME]);
|
|
1156
|
+
await runCommand2("claude", ["plugin", "update", OCR_PLUGIN]);
|
|
1157
|
+
} catch (err) {
|
|
1158
|
+
console.error(`[${logPrefix}] Failed to update ${OCR_PLUGIN}, trying install: ${err.message}`);
|
|
1159
|
+
await addAndInstall();
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
console.log(`[${logPrefix}] Plugin ${OCR_PLUGIN} ready.`);
|
|
1163
|
+
} catch (err) {
|
|
1164
|
+
console.error(`[${logPrefix}] Failed to set up plugin ${OCR_PLUGIN}: ${err.message}`);
|
|
1165
|
+
ok = false;
|
|
1166
|
+
}
|
|
1167
|
+
return ok;
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
// src/commands/playwright.ts
|
|
1171
|
+
async function loadRunCommand4() {
|
|
1172
|
+
return await import("./run-command-O2TMRPZK.js");
|
|
1173
|
+
}
|
|
1120
1174
|
var PLAYWRIGHT_CORE_PACKAGE = "playwright-core";
|
|
1121
1175
|
var PLAYWRIGHT_MCP_PACKAGE = "@playwright/mcp";
|
|
1122
1176
|
var INSTALL_BROWSER_ARGS = ["-y", `${PLAYWRIGHT_MCP_PACKAGE}@latest`, "install-browser", "chrome"];
|
|
@@ -1125,7 +1179,7 @@ function buildInstallDepsCommand(uid) {
|
|
|
1125
1179
|
return uid === 0 ? { command: "npx", args: npxArgs } : { command: "sudo", args: ["npx", ...npxArgs] };
|
|
1126
1180
|
}
|
|
1127
1181
|
async function installPlaywrightBrowsers(logPrefix) {
|
|
1128
|
-
const { runCommand: runCommand2 } = await
|
|
1182
|
+
const { runCommand: runCommand2 } = await loadRunCommand4();
|
|
1129
1183
|
console.log(`[${logPrefix}] Installing Playwright browsers (npx ${INSTALL_BROWSER_ARGS.join(" ")})...`);
|
|
1130
1184
|
try {
|
|
1131
1185
|
await runCommand2("npx", INSTALL_BROWSER_ARGS);
|
|
@@ -1154,7 +1208,7 @@ async function installPlaywrightBrowsers(logPrefix) {
|
|
|
1154
1208
|
var PLUGIN_NAME = "claude-task-worker";
|
|
1155
1209
|
var MARKETPLACE_NAME = "claude-task-worker";
|
|
1156
1210
|
var MARKETPLACE_SOURCE = "getty104/claude-task-worker";
|
|
1157
|
-
var GLOBAL_NPM_PACKAGES = [PLUGIN_NAME, CODEGRAPH_PACKAGE, DESIGN_MD_PACKAGE];
|
|
1211
|
+
var GLOBAL_NPM_PACKAGES = [PLUGIN_NAME, CODEGRAPH_PACKAGE, DESIGN_MD_PACKAGE, OCR_PACKAGE];
|
|
1158
1212
|
async function printGlobalPackageVersions(logPrefix) {
|
|
1159
1213
|
console.log(`[${logPrefix}] Installed versions:`);
|
|
1160
1214
|
try {
|
|
@@ -1204,8 +1258,9 @@ async function install() {
|
|
|
1204
1258
|
const codegraphOk = await installCodegraphCli("install");
|
|
1205
1259
|
const designMdOk = await installDesignMdCli("install");
|
|
1206
1260
|
const playwrightOk = await installPlaywrightBrowsers("install");
|
|
1261
|
+
const ocrOk = await installOpenCodeReview("install");
|
|
1207
1262
|
await printGlobalPackageVersions("install");
|
|
1208
|
-
if (!pluginOk || !cliOk || !codegraphOk || !designMdOk || !playwrightOk) {
|
|
1263
|
+
if (!pluginOk || !cliOk || !codegraphOk || !designMdOk || !playwrightOk || !ocrOk) {
|
|
1209
1264
|
process.exitCode = 1;
|
|
1210
1265
|
}
|
|
1211
1266
|
console.log("[install] Done.");
|
|
@@ -1344,8 +1399,9 @@ async function update() {
|
|
|
1344
1399
|
const codegraphOk = await upgradeCodegraphCli("update");
|
|
1345
1400
|
const designMdOk = await installDesignMdCli("update");
|
|
1346
1401
|
const playwrightOk = await installPlaywrightBrowsers("update");
|
|
1402
|
+
const ocrOk = await installOpenCodeReview("update");
|
|
1347
1403
|
await printGlobalPackageVersions("update");
|
|
1348
|
-
if (!marketplaceOk || !pluginOk || !cliOk || !codegraphOk || !designMdOk || !playwrightOk) {
|
|
1404
|
+
if (!marketplaceOk || !pluginOk || !cliOk || !codegraphOk || !designMdOk || !playwrightOk || !ocrOk) {
|
|
1349
1405
|
process.exitCode = 1;
|
|
1350
1406
|
}
|
|
1351
1407
|
console.log("[update] Done.");
|
|
@@ -1536,7 +1592,7 @@ async function loadCustomWorkersOrExit() {
|
|
|
1536
1592
|
return workers;
|
|
1537
1593
|
}
|
|
1538
1594
|
function printUsage() {
|
|
1539
|
-
console.log(`Usage: claude-task-worker <command> [--project <name>] [--epic <issue-number>] [--label <label-name>]
|
|
1595
|
+
console.log(`Usage: claude-task-worker <command> [--project <name>] [--epic <issue-number>] [--label <label-name>] [--exclude-label <label-name>]
|
|
1540
1596
|
|
|
1541
1597
|
Commands:
|
|
1542
1598
|
init [--force] Create required GitHub labels and config file (use --force to overwrite existing files)
|
|
@@ -1560,7 +1616,9 @@ Options:
|
|
|
1560
1616
|
--inherit-config <path> Use the given config file as the base. claude-task-worker.json and claude-task-worker.local.json in the current directory are layered on top (their keys win). Relative paths inside the file resolve from its own directory. With init, the config file is generated at this path.
|
|
1561
1617
|
--debug Post each task's final report as a comment on the target Issue/PR (off by default; the report is only sent to Slack). Works in both local and --cloud runs.
|
|
1562
1618
|
--epic <number> Limit issue-based workers to sub-issues of the specified epic issue. Repeatable: any matching parent (OR).
|
|
1563
|
-
--label <name> Limit issue-based workers to issues that also carry the specified label. Repeatable: all must be present (AND).
|
|
1619
|
+
--label <name> Limit issue- and PR-based workers to issues/PRs that also carry the specified label. Repeatable: all must be present (AND).
|
|
1620
|
+
--exclude-label <name> Skip issues and PRs that carry the specified label. Repeatable: each is applied (AND), so any listed label excludes the item.
|
|
1621
|
+
Per-project defaults: write a project in config.json as { "path": "...", "label": [...], "excludeLabel": [...] }; they are added to the flags only when started via --project.
|
|
1564
1622
|
|
|
1565
1623
|
Example:
|
|
1566
1624
|
claude-task-worker init
|
|
@@ -1569,6 +1627,7 @@ Example:
|
|
|
1569
1627
|
claude-task-worker all --epic 100 --epic 200
|
|
1570
1628
|
claude-task-worker all --label priority-high
|
|
1571
1629
|
claude-task-worker all --label priority-high --label needs-design
|
|
1630
|
+
claude-task-worker all --exclude-label wip
|
|
1572
1631
|
claude-task-worker yolo --epic 100 --epic 200 --label priority-high
|
|
1573
1632
|
claude-task-worker all --project all
|
|
1574
1633
|
claude-task-worker all --project web
|
|
@@ -1637,8 +1696,18 @@ function parseEpicFilters() {
|
|
|
1637
1696
|
return num;
|
|
1638
1697
|
});
|
|
1639
1698
|
}
|
|
1640
|
-
function
|
|
1641
|
-
|
|
1699
|
+
function parseLabelOptions() {
|
|
1700
|
+
const project = findProjectLabelFilters();
|
|
1701
|
+
const uniq = (values) => [...new Set(values)];
|
|
1702
|
+
const labelFilters = uniq([...collectFlagValues("--label"), ...project.label]);
|
|
1703
|
+
const excludeLabelFilters = uniq([...collectFlagValues("--exclude-label"), ...project.excludeLabel]);
|
|
1704
|
+
const overlapped = labelFilters.filter((l) => excludeLabelFilters.includes(l));
|
|
1705
|
+
if (overlapped.length > 0) {
|
|
1706
|
+
console.warn(
|
|
1707
|
+
`[worker] label(s) in both --label and --exclude-label, no issue/PR will match: ${overlapped.join(", ")}`
|
|
1708
|
+
);
|
|
1709
|
+
}
|
|
1710
|
+
return { labelFilters, excludeLabelFilters };
|
|
1642
1711
|
}
|
|
1643
1712
|
process.on("unhandledRejection", (err) => {
|
|
1644
1713
|
console.error("[worker] unhandled rejection:", err);
|
|
@@ -1774,7 +1843,7 @@ if (hasProjectFilter()) {
|
|
|
1774
1843
|
let sessions = /* @__PURE__ */ new Map();
|
|
1775
1844
|
let monitorHandle;
|
|
1776
1845
|
const herdr = await import("./herdr-NDLUM6JF.js");
|
|
1777
|
-
const dispatcher = await import("./dispatcher-
|
|
1846
|
+
const dispatcher = await import("./dispatcher-M7ELTAHV.js");
|
|
1778
1847
|
captureConsole();
|
|
1779
1848
|
const shutdownController = dispatcher.createDispatcherShutdownHandler(
|
|
1780
1849
|
(options) => dispatcher.shutdownDispatcher(sessions, monitorHandle, options)
|
|
@@ -1840,40 +1909,37 @@ if (hasProjectFilter()) {
|
|
|
1840
1909
|
for (const c of customWorkers) printWorkerRow(c.definition.name, "custom", c.source);
|
|
1841
1910
|
} else if (workerType === "all") {
|
|
1842
1911
|
const epicFilters = parseEpicFilters();
|
|
1843
|
-
const
|
|
1912
|
+
const labelOptions = parseLabelOptions();
|
|
1844
1913
|
(async () => {
|
|
1845
1914
|
await assertRunPrerequisites();
|
|
1846
|
-
await removeStaleWorktrees();
|
|
1847
1915
|
await Promise.all(
|
|
1848
1916
|
startEnabledWorkers(
|
|
1849
1917
|
candidateNames((e) => e.inAll),
|
|
1850
|
-
{ epicFilters,
|
|
1918
|
+
{ epicFilters, ...labelOptions }
|
|
1851
1919
|
)
|
|
1852
1920
|
);
|
|
1853
1921
|
})();
|
|
1854
1922
|
} else if (workerType === "yolo") {
|
|
1855
1923
|
const epicFilters = parseEpicFilters();
|
|
1856
|
-
const
|
|
1924
|
+
const labelOptions = parseLabelOptions();
|
|
1857
1925
|
(async () => {
|
|
1858
1926
|
await assertRunPrerequisites();
|
|
1859
|
-
await removeStaleWorktrees();
|
|
1860
1927
|
await Promise.all(
|
|
1861
1928
|
startEnabledWorkers(
|
|
1862
1929
|
candidateNames((e) => e.inYolo),
|
|
1863
|
-
{ epicFilters,
|
|
1930
|
+
{ epicFilters, ...labelOptions }
|
|
1864
1931
|
)
|
|
1865
1932
|
);
|
|
1866
1933
|
})();
|
|
1867
1934
|
} else {
|
|
1868
1935
|
const epicFilters = parseEpicFilters();
|
|
1869
|
-
const
|
|
1936
|
+
const labelOptions = parseLabelOptions();
|
|
1870
1937
|
(async () => {
|
|
1871
1938
|
if (!isWorkerEnabled(workerType)) {
|
|
1872
1939
|
console.error(`[worker] ${disabledWorkerMessage(workerType)}`);
|
|
1873
1940
|
process.exit(1);
|
|
1874
1941
|
}
|
|
1875
1942
|
await assertRunPrerequisites();
|
|
1876
|
-
await
|
|
1877
|
-
await WORKERS[workerType].start({ epicFilters, labelFilters });
|
|
1943
|
+
await WORKERS[workerType].start({ epicFilters, ...labelOptions });
|
|
1878
1944
|
})();
|
|
1879
1945
|
}
|
package/dist/lib.js
CHANGED
|
@@ -55,12 +55,12 @@ import {
|
|
|
55
55
|
removeWorktreeByBranch,
|
|
56
56
|
run,
|
|
57
57
|
syncDefaultBranch
|
|
58
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-725IRSKF.js";
|
|
59
59
|
import {
|
|
60
60
|
getPermissionMode,
|
|
61
61
|
getRunMode,
|
|
62
62
|
isAdvisorEnabled
|
|
63
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-BA2CE3L6.js";
|
|
64
64
|
export {
|
|
65
65
|
CLOUD_DONE_LABEL,
|
|
66
66
|
addAssignee,
|
package/dist/random-name.d.ts
CHANGED
package/dist/user-config.d.ts
CHANGED
|
@@ -10,6 +10,11 @@ export interface UserConfig {
|
|
|
10
10
|
permission: PermissionMode;
|
|
11
11
|
projects: Record<string, string>;
|
|
12
12
|
projectGroups: Record<string, string[]>;
|
|
13
|
+
projectLabelFilters: Record<string, ProjectLabelFilters>;
|
|
14
|
+
}
|
|
15
|
+
export interface ProjectLabelFilters {
|
|
16
|
+
label: string[];
|
|
17
|
+
excludeLabel: string[];
|
|
13
18
|
}
|
|
14
19
|
export interface ResolvedProject {
|
|
15
20
|
name: string;
|
|
@@ -28,4 +33,5 @@ export declare function resetAdvisorCache(): void;
|
|
|
28
33
|
export declare function getPermissionMode(): PermissionMode;
|
|
29
34
|
export declare function resetPermissionModeCache(): void;
|
|
30
35
|
export declare function findProjectNameByPath(path: string): string | undefined;
|
|
36
|
+
export declare function findProjectLabelFilters(projectName?: string | undefined): ProjectLabelFilters;
|
|
31
37
|
export declare function resolveTargetProjects(requested: string[], config: UserConfig): ResolvedProject[];
|
|
@@ -11,5 +11,6 @@ export declare function verifyPrCreated(issueNumber: number, worktreeId: string,
|
|
|
11
11
|
cloud: boolean;
|
|
12
12
|
baseBranch: string;
|
|
13
13
|
startedAt: number;
|
|
14
|
+
labelFilters?: string[];
|
|
14
15
|
}): Promise<boolean | void>;
|
|
15
16
|
export declare const execIssueWorker: import("./worker-definition").WorkerDefinition;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Issue } from "../gh";
|
|
2
2
|
import type { WorkerDefinition } from "./worker-definition";
|
|
3
|
+
export declare function carryLabelFiltersToPr(workerName: string, prNumber: number, labelFilters?: string[]): Promise<void>;
|
|
3
4
|
export declare const consumableTriggerLabels: (triggerLabels: string[]) => string[];
|
|
4
5
|
export type PreflightResult = "proceed" | "skip" | "mark-pr-created";
|
|
5
6
|
export interface IssueWorkerConfig {
|
|
@@ -13,6 +14,7 @@ export interface IssueWorkerConfig {
|
|
|
13
14
|
cloud: boolean;
|
|
14
15
|
baseBranch: string;
|
|
15
16
|
startedAt: number;
|
|
17
|
+
labelFilters?: string[];
|
|
16
18
|
}) => Promise<boolean | void>;
|
|
17
19
|
cloudOnBranch?: (issue: Issue, baseBranch: string) => Promise<string>;
|
|
18
20
|
}
|
|
@@ -2,6 +2,7 @@ export type WorkerKind = "issue" | "pr" | "scheduled";
|
|
|
2
2
|
export interface WorkerStartOptions {
|
|
3
3
|
epicFilters?: number[];
|
|
4
4
|
labelFilters?: string[];
|
|
5
|
+
excludeLabelFilters?: string[];
|
|
5
6
|
}
|
|
6
7
|
export declare const WORKER_DEFINITION: unique symbol;
|
|
7
8
|
export interface WorkerDefinition {
|
package/dist/worktree.d.ts
CHANGED
|
@@ -13,9 +13,3 @@ export declare function getWorktreePath(worktreeId: string): string;
|
|
|
13
13
|
export declare function createWorktreeFromBranch(worktreeId: string, baseBranch: string): Promise<void>;
|
|
14
14
|
export declare function removeWorktree(worktreeId: string): Promise<void>;
|
|
15
15
|
export declare function removeWorktreeByBranch(branchName: string): Promise<void>;
|
|
16
|
-
/**
|
|
17
|
-
* 前回のクラッシュ・強制終了などで残った worktree を起動時に一括回収する。
|
|
18
|
-
* generateWorktreeName() 形式(adj-noun-4桁)の名前だけを対象にすることで、
|
|
19
|
-
* ユーザーが対話セッションで使用中の claude worktree を誤って削除しない。
|
|
20
|
-
*/
|
|
21
|
-
export declare function removeStaleWorktrees(): Promise<void>;
|