claude-task-worker 0.31.0 → 0.32.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 +26 -1
- package/dist/index.js +120 -37
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -274,7 +274,7 @@ claude-task-worker yolo --epic 100 --epic 200 --label priority-high
|
|
|
274
274
|
}
|
|
275
275
|
```
|
|
276
276
|
|
|
277
|
-
`mode` については [`mode`(タスクの実行形態)](#modeタスクの実行形態) を参照。
|
|
277
|
+
`mode` については [`mode`(タスクの実行形態)](#modeタスクの実行形態) を、`headroom` については [`headroom`(Headroom 経由でのタスク実行)](#headroomheadroom-経由でのタスク実行) を参照。
|
|
278
278
|
|
|
279
279
|
`--project` は繰り返し指定可能で、複数指定した場合は解決後のプロジェクト集合の和集合が対象になる(重複は一意化される)。`--epic` / `--label` と併用でき、ディスパッチ先の各プロジェクトで実行されるコマンドにそのまま引き継がれる。
|
|
280
280
|
|
|
@@ -331,6 +331,31 @@ claude-task-worker exec-issue --project app-a --epic 100 --label priority-high
|
|
|
331
331
|
|
|
332
332
|
適用は `herdr server reload-config`。この設定は herdr サーバー全体に効くため、ワーカー以外の対話セッションの完了音も鳴らなくなる(`[ui.sound.agents] claude = "off"` でも実質同じ範囲)。ワーカーだけを無音にしたい場合は、`HERDR_DISABLE_SOUND=1 herdr --session <name>` で別セッションを起動し、その中でディスパッチャーを動かす
|
|
333
333
|
|
|
334
|
+
### `headroom`(Headroom 経由でのタスク実行)
|
|
335
|
+
|
|
336
|
+
`config.json` のトップレベルに `"headroom": true` を書くと、ワーカーは各タスクの claude を [Headroom](https://github.com/headroom-ai/headroom) 経由(`headroom wrap claude`)で起動する。Headroom がローカルプロキシを立ててコンテキストを圧縮し、`ANTHROPIC_BASE_URL` を差し替えた状態で claude を起動する。既定は `false`(`claude` を直接起動する)。
|
|
337
|
+
|
|
338
|
+
`mode` と同じくトップレベル一括の設定で、プロジェクト単位・ワーカー単位の指定はできない。
|
|
339
|
+
|
|
340
|
+
```json
|
|
341
|
+
{
|
|
342
|
+
"headroom": true,
|
|
343
|
+
"projects": { "app-a": "/Users/me/repos/app-a" }
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
| `headroom` | 実行されるコマンド |
|
|
348
|
+
|-----------|------------------|
|
|
349
|
+
| `false`(既定) | `claude <引数>` |
|
|
350
|
+
| `true` | `headroom wrap claude -- <引数>` |
|
|
351
|
+
|
|
352
|
+
補足:
|
|
353
|
+
|
|
354
|
+
- `mode` とは独立して組み合わせられる(`mode: "herdr"` の TUI 起動も `headroom wrap claude` になる)
|
|
355
|
+
- claude へ渡す引数はすべて `--` の後ろに置かれる。`headroom wrap claude` 自身も `--port` / `--memory` などのオプションを持ち、`-p` のように衝突しうるフラグは `--` の後ろでないと claude に届かないため
|
|
356
|
+
- `headroom: true` で headroom コマンドが PATH に無い場合、ワーカーは起動時にエラー終了する(`mode: "herdr"` と同じく、サイレントに直接起動へフォールバックはしない)
|
|
357
|
+
- `headroom wrap claude` は claude を起動する前に起動バナー(枠線・`ANTHROPIC_BASE_URL=...` など)を stdout へ出力し、これを抑止するオプションは無い。ワーカーは空振りセッション検知(exit 0 かつ無出力を失敗とみなす判定)の前にこのバナーを取り除くため、検知は `headroom: true` でも従来どおり機能する。ただし Slack 通知の本文にはバナーがそのまま含まれる
|
|
358
|
+
|
|
334
359
|
### exec-issue
|
|
335
360
|
|
|
336
361
|
`cc-exec-issue` ラベルが付いた自分にアサインされたIssueを定期取得し、Claude Codeで処理を実行する。(デフォルト1分間隔)
|
package/dist/index.js
CHANGED
|
@@ -132,6 +132,38 @@ var init_table = __esm({
|
|
|
132
132
|
}
|
|
133
133
|
});
|
|
134
134
|
|
|
135
|
+
// src/task-result.ts
|
|
136
|
+
function stripHeadroomBanner(stdout) {
|
|
137
|
+
const lines = stdout.split("\n");
|
|
138
|
+
let i = 0;
|
|
139
|
+
while (i < lines.length && (lines[i].trim() === "" || lines[i].startsWith(" "))) i++;
|
|
140
|
+
return lines.slice(i).join("\n");
|
|
141
|
+
}
|
|
142
|
+
function buildTaskResult(code, stdout, stderrTail, options) {
|
|
143
|
+
const meaningful = options?.headroom ? stripHeadroomBanner(stdout) : stdout;
|
|
144
|
+
const emptyOutput = meaningful.trim() === "";
|
|
145
|
+
const completed = code === 0 && !emptyOutput;
|
|
146
|
+
let output = stdout;
|
|
147
|
+
if (code === 0 && emptyOutput) {
|
|
148
|
+
output += "[worker] claude exited with code 0 but produced no output (session aborted before the model ran; e.g. a skill preamble command failed)";
|
|
149
|
+
} else if (!completed) {
|
|
150
|
+
output += `
|
|
151
|
+
[worker] claude exited with code ${code}`;
|
|
152
|
+
}
|
|
153
|
+
if (!completed && stderrTail.trim() !== "") {
|
|
154
|
+
output += `
|
|
155
|
+
[stderr] ${stderrTail.trim()}`;
|
|
156
|
+
}
|
|
157
|
+
return { status: completed ? "completed" : "failed", output };
|
|
158
|
+
}
|
|
159
|
+
var STDERR_TAIL_LIMIT;
|
|
160
|
+
var init_task_result = __esm({
|
|
161
|
+
"src/task-result.ts"() {
|
|
162
|
+
"use strict";
|
|
163
|
+
STDERR_TAIL_LIMIT = 8 * 1024;
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
135
167
|
// src/herdr.ts
|
|
136
168
|
var herdr_exports = {};
|
|
137
169
|
__export(herdr_exports, {
|
|
@@ -490,8 +522,9 @@ function observeAgentStatus(tracker, status) {
|
|
|
490
522
|
}
|
|
491
523
|
return { tracker, decision: "running" };
|
|
492
524
|
}
|
|
493
|
-
function buildHerdrTaskResult(paneOutput) {
|
|
494
|
-
|
|
525
|
+
function buildHerdrTaskResult(paneOutput, options) {
|
|
526
|
+
const meaningful = options?.headroom ? stripHeadroomBanner(paneOutput) : paneOutput;
|
|
527
|
+
if (meaningful.trim() === "") {
|
|
495
528
|
return {
|
|
496
529
|
status: "failed",
|
|
497
530
|
output: "[worker] the claude session became idle but its pane produced no output (session aborted before the model ran; e.g. a skill preamble command failed)"
|
|
@@ -549,7 +582,7 @@ async function waitForHerdrTask(paneId, options) {
|
|
|
549
582
|
tracker = observed.tracker;
|
|
550
583
|
if (observed.decision === "completed") {
|
|
551
584
|
const output = await readPaneOutput(paneId, mod);
|
|
552
|
-
return buildHerdrTaskResult(output);
|
|
585
|
+
return buildHerdrTaskResult(output, { headroom: options?.headroom });
|
|
553
586
|
}
|
|
554
587
|
if (observed.decision === "blocked-first-seen") {
|
|
555
588
|
options?.onBlocked?.();
|
|
@@ -609,6 +642,7 @@ var AGENT_POLL_INTERVAL_MS, PANE_OUTPUT_LINES, CLAUDE_EXIT_TIMEOUT_MS, CLAUDE_EX
|
|
|
609
642
|
var init_herdr_runner = __esm({
|
|
610
643
|
"src/herdr-runner.ts"() {
|
|
611
644
|
"use strict";
|
|
645
|
+
init_task_result();
|
|
612
646
|
AGENT_POLL_INTERVAL_MS = 3 * 1e3;
|
|
613
647
|
PANE_OUTPUT_LINES = 300;
|
|
614
648
|
CLAUDE_EXIT_TIMEOUT_MS = 15 * 1e3;
|
|
@@ -1378,6 +1412,8 @@ var SYSTEM_PROMPT = `\u3053\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306F \`claude-t
|
|
|
1378
1412
|
- CodeGraph \u304C\u8FD4\u3057\u305F\u30BD\u30FC\u30B9\u306F\u300C\u8AAD\u307F\u7D42\u3048\u305F\u3082\u306E\u300D\u3068\u3057\u3066\u6271\u3044\u3001\u540C\u3058\u7B87\u6240\u3092 \`Grep\`/\`Read\` \u3067\u88CF\u53D6\u308A\u3057\u76F4\u3055\u306A\u3044\u3002\u305F\u3060\u3057\u51FA\u529B\u306B staleness\uFF08\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u304C\u53E4\u3044\u65E8\uFF09\u306E\u8B66\u544A\u304C\u51FA\u3066\u3044\u308B\u5834\u5408\u306F\u8A72\u5F53\u30D5\u30A1\u30A4\u30EB\u3092 \`Read\` \u3057\u3066\u73FE\u7269\u3092\u78BA\u8A8D\u3059\u308B
|
|
1379
1413
|
- \u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u30FB\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u30FB\u30B3\u30E1\u30F3\u30C8/\u6587\u5B57\u5217\u30EA\u30C6\u30E9\u30EB\u30FB\u672A\u5BFE\u5FDC\u8A00\u8A9E\u306A\u3069 CodeGraph \u304C\u6271\u308F\u306A\u3044\u5BFE\u8C61\u306F\u3001\u5F93\u6765\u3069\u304A\u308A\u30C6\u30AD\u30B9\u30C8\u691C\u7D22\u3067\u88DC\u3046
|
|
1380
1414
|
- \u63A2\u7D22\u3092\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u3078\u59D4\u8B72\u3059\u308B\u5834\u5408\u306F\u3001\u3053\u306E\u65B9\u91DD\u3082\u59D4\u8B72\u30D7\u30ED\u30F3\u30D7\u30C8\u306B\u660E\u8A18\u3057\u3066\u4F1D\u3048\u308B`;
|
|
1415
|
+
var CLAUDE_COMMAND = "claude";
|
|
1416
|
+
var HEADROOM_COMMAND = "headroom";
|
|
1381
1417
|
function buildClaudeArgs({ mode, prompt, model, effort }) {
|
|
1382
1418
|
return [
|
|
1383
1419
|
...mode === "herdr" ? [] : ["-p"],
|
|
@@ -1394,6 +1430,13 @@ function buildClaudeArgs({ mode, prompt, model, effort }) {
|
|
|
1394
1430
|
effort
|
|
1395
1431
|
];
|
|
1396
1432
|
}
|
|
1433
|
+
function buildClaudeExecution(invocation) {
|
|
1434
|
+
const args = buildClaudeArgs(invocation);
|
|
1435
|
+
if (!invocation.headroom) {
|
|
1436
|
+
return { command: CLAUDE_COMMAND, args };
|
|
1437
|
+
}
|
|
1438
|
+
return { command: HEADROOM_COMMAND, args: ["wrap", CLAUDE_COMMAND, "--", ...args] };
|
|
1439
|
+
}
|
|
1397
1440
|
function buildClaudeEnv(mode) {
|
|
1398
1441
|
if (mode === "herdr") {
|
|
1399
1442
|
return {
|
|
@@ -1648,25 +1691,7 @@ async function assertRemoteTrackingExists(epicBranch) {
|
|
|
1648
1691
|
import { spawn } from "node:child_process";
|
|
1649
1692
|
import { basename } from "node:path";
|
|
1650
1693
|
init_table();
|
|
1651
|
-
|
|
1652
|
-
// src/task-result.ts
|
|
1653
|
-
var STDERR_TAIL_LIMIT = 8 * 1024;
|
|
1654
|
-
function buildTaskResult(code, stdout, stderrTail) {
|
|
1655
|
-
const emptyOutput = stdout.trim() === "";
|
|
1656
|
-
const completed = code === 0 && !emptyOutput;
|
|
1657
|
-
let output = stdout;
|
|
1658
|
-
if (code === 0 && emptyOutput) {
|
|
1659
|
-
output += "[worker] claude exited with code 0 but produced no output (session aborted before the model ran; e.g. a skill preamble command failed)";
|
|
1660
|
-
} else if (!completed) {
|
|
1661
|
-
output += `
|
|
1662
|
-
[worker] claude exited with code ${code}`;
|
|
1663
|
-
}
|
|
1664
|
-
if (!completed && stderrTail.trim() !== "") {
|
|
1665
|
-
output += `
|
|
1666
|
-
[stderr] ${stderrTail.trim()}`;
|
|
1667
|
-
}
|
|
1668
|
-
return { status: completed ? "completed" : "failed", output };
|
|
1669
|
-
}
|
|
1694
|
+
init_task_result();
|
|
1670
1695
|
|
|
1671
1696
|
// src/user-config.ts
|
|
1672
1697
|
import { readFileSync as readFileSync2, statSync } from "node:fs";
|
|
@@ -1674,6 +1699,7 @@ import { homedir } from "node:os";
|
|
|
1674
1699
|
import { isAbsolute, join as join2, resolve } from "node:path";
|
|
1675
1700
|
var RESERVED_ALL = "all";
|
|
1676
1701
|
var DEFAULT_RUN_MODE = "default";
|
|
1702
|
+
var DEFAULT_HEADROOM = false;
|
|
1677
1703
|
var UserConfigError = class extends Error {
|
|
1678
1704
|
constructor(message) {
|
|
1679
1705
|
super(message);
|
|
@@ -1722,6 +1748,13 @@ function parseMode(raw, path) {
|
|
|
1722
1748
|
console.warn(`[config] invalid mode: ${JSON.stringify(value)} in ${path}, using "${DEFAULT_RUN_MODE}"`);
|
|
1723
1749
|
return DEFAULT_RUN_MODE;
|
|
1724
1750
|
}
|
|
1751
|
+
function parseHeadroom(raw, path) {
|
|
1752
|
+
if (!("headroom" in raw)) return DEFAULT_HEADROOM;
|
|
1753
|
+
const value = raw["headroom"];
|
|
1754
|
+
if (typeof value === "boolean") return value;
|
|
1755
|
+
console.warn(`[config] invalid headroom: ${JSON.stringify(value)} in ${path}, using ${DEFAULT_HEADROOM}`);
|
|
1756
|
+
return DEFAULT_HEADROOM;
|
|
1757
|
+
}
|
|
1725
1758
|
function loadUserConfig() {
|
|
1726
1759
|
const path = getUserConfigPath();
|
|
1727
1760
|
const raw = readRawConfig();
|
|
@@ -1738,6 +1771,7 @@ function loadUserConfig() {
|
|
|
1738
1771
|
throw new UserConfigError(`config.json "projectGroups" must be an object: ${path}`);
|
|
1739
1772
|
}
|
|
1740
1773
|
const mode = parseMode(raw, path);
|
|
1774
|
+
const headroom = parseHeadroom(raw, path);
|
|
1741
1775
|
const rawProjects = raw["projects"];
|
|
1742
1776
|
const rawProjectGroups = "projectGroups" in raw ? raw["projectGroups"] : {};
|
|
1743
1777
|
const projectKeys = Object.keys(rawProjects);
|
|
@@ -1788,7 +1822,7 @@ function loadUserConfig() {
|
|
|
1788
1822
|
}
|
|
1789
1823
|
projectGroups[groupName] = members;
|
|
1790
1824
|
}
|
|
1791
|
-
return { mode, projects, projectGroups };
|
|
1825
|
+
return { mode, headroom, projects, projectGroups };
|
|
1792
1826
|
}
|
|
1793
1827
|
var cachedRunMode;
|
|
1794
1828
|
function getRunMode() {
|
|
@@ -1798,18 +1832,35 @@ function getRunMode() {
|
|
|
1798
1832
|
return cachedRunMode;
|
|
1799
1833
|
}
|
|
1800
1834
|
function readRunMode() {
|
|
1835
|
+
const raw = readTopLevelConfig(`using "${DEFAULT_RUN_MODE}" mode`);
|
|
1836
|
+
if (raw === void 0) return DEFAULT_RUN_MODE;
|
|
1837
|
+
return parseMode(raw, getUserConfigPath());
|
|
1838
|
+
}
|
|
1839
|
+
var cachedHeadroom;
|
|
1840
|
+
function getHeadroomEnabled() {
|
|
1841
|
+
if (cachedHeadroom === void 0) {
|
|
1842
|
+
cachedHeadroom = readHeadroom();
|
|
1843
|
+
}
|
|
1844
|
+
return cachedHeadroom;
|
|
1845
|
+
}
|
|
1846
|
+
function readHeadroom() {
|
|
1847
|
+
const raw = readTopLevelConfig(`using headroom=${DEFAULT_HEADROOM}`);
|
|
1848
|
+
if (raw === void 0) return DEFAULT_HEADROOM;
|
|
1849
|
+
return parseHeadroom(raw, getUserConfigPath());
|
|
1850
|
+
}
|
|
1851
|
+
function readTopLevelConfig(fallbackDescription) {
|
|
1801
1852
|
let raw;
|
|
1802
1853
|
try {
|
|
1803
1854
|
raw = readRawConfig();
|
|
1804
1855
|
} catch (err) {
|
|
1805
|
-
console.warn(`[config] failed to read config file,
|
|
1806
|
-
return
|
|
1856
|
+
console.warn(`[config] failed to read config file, ${fallbackDescription}: ${err}`);
|
|
1857
|
+
return void 0;
|
|
1807
1858
|
}
|
|
1808
|
-
if (raw === void 0) return
|
|
1859
|
+
if (raw === void 0) return void 0;
|
|
1809
1860
|
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
1810
|
-
return
|
|
1861
|
+
return void 0;
|
|
1811
1862
|
}
|
|
1812
|
-
return
|
|
1863
|
+
return raw;
|
|
1813
1864
|
}
|
|
1814
1865
|
function findProjectNameByPath(path) {
|
|
1815
1866
|
let config;
|
|
@@ -1945,6 +1996,7 @@ async function runViaHerdr(command, args, id, onComplete, cwd, env) {
|
|
|
1945
1996
|
herdrTasks.set(id, task);
|
|
1946
1997
|
result = await waitForHerdrTask2(task.paneId, {
|
|
1947
1998
|
signal: herdrAbortSignal,
|
|
1999
|
+
headroom: getHeadroomEnabled(),
|
|
1948
2000
|
onBlocked: () => console.warn(`[worker] #${id} is blocked and waiting for input in herdr tab "${label}"`),
|
|
1949
2001
|
onStatus: (status) => {
|
|
1950
2002
|
const task2 = tasks.get(id);
|
|
@@ -2002,7 +2054,8 @@ function run(command, args, id, title, workerName, path, onComplete, cwd, env) {
|
|
|
2002
2054
|
const result = buildTaskResult(
|
|
2003
2055
|
code,
|
|
2004
2056
|
Buffer.concat(outputChunks).toString("utf-8"),
|
|
2005
|
-
Buffer.concat(stderrChunks).toString("utf-8").slice(-STDERR_TAIL_LIMIT)
|
|
2057
|
+
Buffer.concat(stderrChunks).toString("utf-8").slice(-STDERR_TAIL_LIMIT),
|
|
2058
|
+
{ headroom: getHeadroomEnabled() }
|
|
2006
2059
|
);
|
|
2007
2060
|
await finishTask(id, result, onComplete);
|
|
2008
2061
|
childProcesses.delete(id);
|
|
@@ -2711,7 +2764,13 @@ function createIssuePollingWorker(config) {
|
|
|
2711
2764
|
const command = skill || config.command;
|
|
2712
2765
|
const parentNumber = issue.parent?.number;
|
|
2713
2766
|
const mode = getRunMode();
|
|
2714
|
-
const
|
|
2767
|
+
const execution = buildClaudeExecution({
|
|
2768
|
+
mode,
|
|
2769
|
+
prompt: `${command} ${issue.number}`,
|
|
2770
|
+
model,
|
|
2771
|
+
effort,
|
|
2772
|
+
headroom: getHeadroomEnabled()
|
|
2773
|
+
});
|
|
2715
2774
|
let baseBranch = defaultBranch;
|
|
2716
2775
|
if (parentNumber !== void 0) {
|
|
2717
2776
|
baseBranch = `cc-epic-${parentNumber}`;
|
|
@@ -2721,8 +2780,8 @@ function createIssuePollingWorker(config) {
|
|
|
2721
2780
|
const cwd = getWorktreePath(worktreeId);
|
|
2722
2781
|
console.log(`[${config.name}] #${issue.number}: created worktree ${worktreeId} from ${baseBranch}`);
|
|
2723
2782
|
run(
|
|
2724
|
-
|
|
2725
|
-
|
|
2783
|
+
execution.command,
|
|
2784
|
+
execution.args,
|
|
2726
2785
|
issue.number,
|
|
2727
2786
|
issue.title,
|
|
2728
2787
|
config.name,
|
|
@@ -2877,9 +2936,16 @@ function createPrPollingWorker(config) {
|
|
|
2877
2936
|
const { model, effort, skill } = getWorkerConfig(config.name);
|
|
2878
2937
|
const command = skill || config.command;
|
|
2879
2938
|
const mode = getRunMode();
|
|
2939
|
+
const execution = buildClaudeExecution({
|
|
2940
|
+
mode,
|
|
2941
|
+
prompt: `${command} ${pr.number}`,
|
|
2942
|
+
model,
|
|
2943
|
+
effort,
|
|
2944
|
+
headroom: getHeadroomEnabled()
|
|
2945
|
+
});
|
|
2880
2946
|
run(
|
|
2881
|
-
|
|
2882
|
-
|
|
2947
|
+
execution.command,
|
|
2948
|
+
execution.args,
|
|
2883
2949
|
pr.number,
|
|
2884
2950
|
`PR #${pr.number} (${pr.headRefName})`,
|
|
2885
2951
|
config.name,
|
|
@@ -3543,6 +3609,23 @@ async function assertRunModeAvailable() {
|
|
|
3543
3609
|
}
|
|
3544
3610
|
console.log("[worker] run mode: herdr (each task runs as a TUI session in its own herdr tab)");
|
|
3545
3611
|
}
|
|
3612
|
+
async function assertHeadroomAvailable() {
|
|
3613
|
+
if (!getHeadroomEnabled()) return;
|
|
3614
|
+
const { execFile: execFile3 } = await import("node:child_process");
|
|
3615
|
+
const { promisify: promisify4 } = await import("node:util");
|
|
3616
|
+
try {
|
|
3617
|
+
await promisify4(execFile3)(HEADROOM_COMMAND, ["--version"]);
|
|
3618
|
+
} catch (err) {
|
|
3619
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3620
|
+
console.error(`[worker] config.json has headroom: true but the headroom CLI is unavailable: ${message}`);
|
|
3621
|
+
process.exit(1);
|
|
3622
|
+
}
|
|
3623
|
+
console.log("[worker] headroom: enabled (each task runs as `headroom wrap claude`)");
|
|
3624
|
+
}
|
|
3625
|
+
async function assertRunPrerequisites() {
|
|
3626
|
+
await assertRunModeAvailable();
|
|
3627
|
+
await assertHeadroomAvailable();
|
|
3628
|
+
}
|
|
3546
3629
|
if (!hasProjectFilter()) {
|
|
3547
3630
|
process.on("SIGTERM", async () => {
|
|
3548
3631
|
if (isShuttingDown()) return;
|
|
@@ -3631,7 +3714,7 @@ if (hasProjectFilter()) {
|
|
|
3631
3714
|
const epicFilters = parseEpicFilters();
|
|
3632
3715
|
const labelFilters = parseLabelFilters();
|
|
3633
3716
|
(async () => {
|
|
3634
|
-
await
|
|
3717
|
+
await assertRunPrerequisites();
|
|
3635
3718
|
await removeStaleWorktrees();
|
|
3636
3719
|
await Promise.all([
|
|
3637
3720
|
execIssueWorker({ epicFilters, labelFilters }),
|
|
@@ -3647,7 +3730,7 @@ if (hasProjectFilter()) {
|
|
|
3647
3730
|
const epicFilters = parseEpicFilters();
|
|
3648
3731
|
const labelFilters = parseLabelFilters();
|
|
3649
3732
|
(async () => {
|
|
3650
|
-
await
|
|
3733
|
+
await assertRunPrerequisites();
|
|
3651
3734
|
await removeStaleWorktrees();
|
|
3652
3735
|
await Promise.all([
|
|
3653
3736
|
execIssueWorker({ epicFilters, labelFilters }),
|
|
@@ -3666,7 +3749,7 @@ if (hasProjectFilter()) {
|
|
|
3666
3749
|
const epicFilters = parseEpicFilters();
|
|
3667
3750
|
const labelFilters = parseLabelFilters();
|
|
3668
3751
|
(async () => {
|
|
3669
|
-
await
|
|
3752
|
+
await assertRunPrerequisites();
|
|
3670
3753
|
await removeStaleWorktrees();
|
|
3671
3754
|
await WORKERS[workerType]({ epicFilters, labelFilters });
|
|
3672
3755
|
})();
|