@neriros/ralphy 3.0.1 → 3.2.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 +35 -1
- package/dist/shell/index.js +2064 -480
- package/package.json +1 -1
package/dist/shell/index.js
CHANGED
|
@@ -18923,8 +18923,44 @@ var init_node = __esm(() => {
|
|
|
18923
18923
|
};
|
|
18924
18924
|
});
|
|
18925
18925
|
|
|
18926
|
+
// packages/version/src/version.ts
|
|
18927
|
+
import { readFileSync } from "fs";
|
|
18928
|
+
import { resolve } from "path";
|
|
18929
|
+
function getVersion() {
|
|
18930
|
+
try {
|
|
18931
|
+
if ("3.2.0")
|
|
18932
|
+
return "3.2.0";
|
|
18933
|
+
} catch {}
|
|
18934
|
+
const dirsToTry = [];
|
|
18935
|
+
try {
|
|
18936
|
+
dirsToTry.push(import.meta.dir);
|
|
18937
|
+
} catch {}
|
|
18938
|
+
dirsToTry.push(process.cwd());
|
|
18939
|
+
for (const startDir of dirsToTry) {
|
|
18940
|
+
let current = startDir;
|
|
18941
|
+
for (let i = 0;i < 10; i++) {
|
|
18942
|
+
const pkgPath = resolve(current, "package.json");
|
|
18943
|
+
try {
|
|
18944
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
18945
|
+
if (pkg.workspaces && pkg.version && pkg.version !== "0.0.0") {
|
|
18946
|
+
return pkg.version;
|
|
18947
|
+
}
|
|
18948
|
+
} catch {}
|
|
18949
|
+
const parent = resolve(current, "..");
|
|
18950
|
+
if (parent === current)
|
|
18951
|
+
break;
|
|
18952
|
+
current = parent;
|
|
18953
|
+
}
|
|
18954
|
+
}
|
|
18955
|
+
return "unknown";
|
|
18956
|
+
}
|
|
18957
|
+
var VERSION;
|
|
18958
|
+
var init_version = __esm(() => {
|
|
18959
|
+
VERSION = getVersion();
|
|
18960
|
+
});
|
|
18961
|
+
|
|
18926
18962
|
// packages/telemetry/src/index.ts
|
|
18927
|
-
import { homedir } from "os";
|
|
18963
|
+
import { homedir, hostname, platform, arch, release } from "os";
|
|
18928
18964
|
import { join } from "path";
|
|
18929
18965
|
import { randomUUID } from "crypto";
|
|
18930
18966
|
function setDefaultProperties(props) {
|
|
@@ -18946,6 +18982,23 @@ async function init() {
|
|
|
18946
18982
|
flushAt: 20,
|
|
18947
18983
|
flushInterval: 0
|
|
18948
18984
|
});
|
|
18985
|
+
defaultProps = {
|
|
18986
|
+
version: VERSION,
|
|
18987
|
+
machine_name: hostname(),
|
|
18988
|
+
platform: platform(),
|
|
18989
|
+
arch: arch(),
|
|
18990
|
+
os_release: release(),
|
|
18991
|
+
...defaultProps
|
|
18992
|
+
};
|
|
18993
|
+
}
|
|
18994
|
+
function captureError(event, error, properties) {
|
|
18995
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
18996
|
+
capture(event, {
|
|
18997
|
+
...properties,
|
|
18998
|
+
error_message: err.message,
|
|
18999
|
+
error_name: err.name,
|
|
19000
|
+
error_stack: err.stack
|
|
19001
|
+
});
|
|
18949
19002
|
}
|
|
18950
19003
|
function capture(event, properties) {
|
|
18951
19004
|
const merged = { ...defaultProps, ...properties };
|
|
@@ -18958,47 +19011,12 @@ async function shutdown() {
|
|
|
18958
19011
|
var POSTHOG_KEY, HOST = "https://eu.i.posthog.com", enabled, client = null, distinctId = "anonymous", defaultProps;
|
|
18959
19012
|
var init_src = __esm(() => {
|
|
18960
19013
|
init_node();
|
|
19014
|
+
init_version();
|
|
18961
19015
|
POSTHOG_KEY = process.env["RALPH_POSTHOG_KEY"] ?? "phc_Bua8TpmaxSSM8h43htLrm6VUoaB2L9GZgA4kiEcMrpaY";
|
|
18962
19016
|
enabled = process.env["RALPH_TELEMETRY"] !== "0";
|
|
18963
19017
|
defaultProps = {};
|
|
18964
19018
|
});
|
|
18965
19019
|
|
|
18966
|
-
// packages/version/src/version.ts
|
|
18967
|
-
import { readFileSync } from "fs";
|
|
18968
|
-
import { resolve } from "path";
|
|
18969
|
-
function getVersion() {
|
|
18970
|
-
try {
|
|
18971
|
-
if ("3.0.1")
|
|
18972
|
-
return "3.0.1";
|
|
18973
|
-
} catch {}
|
|
18974
|
-
const dirsToTry = [];
|
|
18975
|
-
try {
|
|
18976
|
-
dirsToTry.push(import.meta.dir);
|
|
18977
|
-
} catch {}
|
|
18978
|
-
dirsToTry.push(process.cwd());
|
|
18979
|
-
for (const startDir of dirsToTry) {
|
|
18980
|
-
let current = startDir;
|
|
18981
|
-
for (let i = 0;i < 10; i++) {
|
|
18982
|
-
const pkgPath = resolve(current, "package.json");
|
|
18983
|
-
try {
|
|
18984
|
-
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
18985
|
-
if (pkg.workspaces && pkg.version && pkg.version !== "0.0.0") {
|
|
18986
|
-
return pkg.version;
|
|
18987
|
-
}
|
|
18988
|
-
} catch {}
|
|
18989
|
-
const parent = resolve(current, "..");
|
|
18990
|
-
if (parent === current)
|
|
18991
|
-
break;
|
|
18992
|
-
current = parent;
|
|
18993
|
-
}
|
|
18994
|
-
}
|
|
18995
|
-
return "unknown";
|
|
18996
|
-
}
|
|
18997
|
-
var VERSION;
|
|
18998
|
-
var init_version = __esm(() => {
|
|
18999
|
-
VERSION = getVersion();
|
|
19000
|
-
});
|
|
19001
|
-
|
|
19002
19020
|
// node_modules/.bun/react@18.3.1/node_modules/react/cjs/react.development.js
|
|
19003
19021
|
var require_react_development = __commonJS((exports, module) => {
|
|
19004
19022
|
if (true) {
|
|
@@ -20939,7 +20957,7 @@ var init_compat = __esm(() => {
|
|
|
20939
20957
|
});
|
|
20940
20958
|
|
|
20941
20959
|
// node_modules/.bun/environment@1.1.0/node_modules/environment/index.js
|
|
20942
|
-
var isBrowser, isNode, isBun, isDeno, isElectron, isJsDom, isWebWorker, isDedicatedWorker, isSharedWorker, isServiceWorker,
|
|
20960
|
+
var isBrowser, isNode, isBun, isDeno, isElectron, isJsDom, isWebWorker, isDedicatedWorker, isSharedWorker, isServiceWorker, platform2, isMacOs, isWindows, isLinux, isIos, isAndroid;
|
|
20943
20961
|
var init_environment = __esm(() => {
|
|
20944
20962
|
isBrowser = globalThis.window?.document !== undefined;
|
|
20945
20963
|
isNode = globalThis.process?.versions?.node !== undefined;
|
|
@@ -20951,12 +20969,12 @@ var init_environment = __esm(() => {
|
|
|
20951
20969
|
isDedicatedWorker = typeof DedicatedWorkerGlobalScope !== "undefined" && globalThis instanceof DedicatedWorkerGlobalScope;
|
|
20952
20970
|
isSharedWorker = typeof SharedWorkerGlobalScope !== "undefined" && globalThis instanceof SharedWorkerGlobalScope;
|
|
20953
20971
|
isServiceWorker = typeof ServiceWorkerGlobalScope !== "undefined" && globalThis instanceof ServiceWorkerGlobalScope;
|
|
20954
|
-
|
|
20955
|
-
isMacOs =
|
|
20956
|
-
isWindows =
|
|
20957
|
-
isLinux =
|
|
20958
|
-
isIos =
|
|
20959
|
-
isAndroid =
|
|
20972
|
+
platform2 = globalThis.navigator?.userAgentData?.platform;
|
|
20973
|
+
isMacOs = platform2 === "macOS" || globalThis.navigator?.platform === "MacIntel" || globalThis.navigator?.userAgent?.includes(" Mac ") === true || globalThis.process?.platform === "darwin";
|
|
20974
|
+
isWindows = platform2 === "Windows" || globalThis.navigator?.platform === "Win32" || globalThis.process?.platform === "win32";
|
|
20975
|
+
isLinux = platform2 === "Linux" || globalThis.navigator?.platform?.startsWith("Linux") === true || globalThis.navigator?.userAgent?.includes(" Linux ") === true || globalThis.process?.platform === "linux";
|
|
20976
|
+
isIos = platform2 === "iOS" || globalThis.navigator?.platform === "MacIntel" && globalThis.navigator?.maxTouchPoints > 1 || /iPad|iPhone|iPod/.test(globalThis.navigator?.platform);
|
|
20977
|
+
isAndroid = platform2 === "Android" || globalThis.navigator?.platform === "Android" || globalThis.navigator?.userAgent?.includes(" Android ") === true || globalThis.process?.platform === "android";
|
|
20960
20978
|
});
|
|
20961
20979
|
|
|
20962
20980
|
// node_modules/.bun/ansi-escapes@7.3.0/node_modules/ansi-escapes/base.js
|
|
@@ -68777,6 +68795,41 @@ var init_FeedLine = __esm(async () => {
|
|
|
68777
68795
|
};
|
|
68778
68796
|
});
|
|
68779
68797
|
|
|
68798
|
+
// apps/loop/src/hooks/useTerminalSize.ts
|
|
68799
|
+
function readSize() {
|
|
68800
|
+
return {
|
|
68801
|
+
columns: process.stdout.columns ?? 80,
|
|
68802
|
+
rows: process.stdout.rows ?? 24
|
|
68803
|
+
};
|
|
68804
|
+
}
|
|
68805
|
+
function useTerminalSize() {
|
|
68806
|
+
const [size2, setSize] = import_react53.useState(() => ({
|
|
68807
|
+
...readSize(),
|
|
68808
|
+
resizeKey: 0
|
|
68809
|
+
}));
|
|
68810
|
+
import_react53.useEffect(() => {
|
|
68811
|
+
if (!process.stdout.isTTY)
|
|
68812
|
+
return;
|
|
68813
|
+
const onResize = () => {
|
|
68814
|
+
const { columns, rows } = readSize();
|
|
68815
|
+
setSize((prev) => {
|
|
68816
|
+
if (prev.columns === columns && prev.rows === rows)
|
|
68817
|
+
return prev;
|
|
68818
|
+
return { columns, rows, resizeKey: prev.resizeKey + 1 };
|
|
68819
|
+
});
|
|
68820
|
+
};
|
|
68821
|
+
process.stdout.on("resize", onResize);
|
|
68822
|
+
return () => {
|
|
68823
|
+
process.stdout.off("resize", onResize);
|
|
68824
|
+
};
|
|
68825
|
+
}, []);
|
|
68826
|
+
return size2;
|
|
68827
|
+
}
|
|
68828
|
+
var import_react53;
|
|
68829
|
+
var init_useTerminalSize = __esm(() => {
|
|
68830
|
+
import_react53 = __toESM(require_react(), 1);
|
|
68831
|
+
});
|
|
68832
|
+
|
|
68780
68833
|
// apps/loop/src/components/StatusBar.tsx
|
|
68781
68834
|
function formatElapsed(ms) {
|
|
68782
68835
|
const totalSec = Math.floor(ms / 1000);
|
|
@@ -68803,14 +68856,16 @@ function StatusBar({
|
|
|
68803
68856
|
model,
|
|
68804
68857
|
isRunning
|
|
68805
68858
|
}) {
|
|
68806
|
-
const [elapsed, setElapsed] =
|
|
68807
|
-
|
|
68859
|
+
const [elapsed, setElapsed] = import_react54.useState(0);
|
|
68860
|
+
import_react54.useEffect(() => {
|
|
68808
68861
|
if (!isRunning)
|
|
68809
68862
|
return;
|
|
68810
68863
|
const id = setInterval(() => setElapsed(Date.now() - startedAt), 1000);
|
|
68811
68864
|
return () => clearInterval(id);
|
|
68812
68865
|
}, [isRunning, startedAt]);
|
|
68813
|
-
const
|
|
68866
|
+
const { columns } = useTerminalSize();
|
|
68867
|
+
const barWidth = Math.max(8, columns);
|
|
68868
|
+
const bar = "\u2500".repeat(barWidth);
|
|
68814
68869
|
return /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
|
|
68815
68870
|
flexDirection: "column",
|
|
68816
68871
|
children: [
|
|
@@ -68874,13 +68929,14 @@ function StatusBar({
|
|
|
68874
68929
|
]
|
|
68875
68930
|
}, undefined, true, undefined, this);
|
|
68876
68931
|
}
|
|
68877
|
-
var
|
|
68932
|
+
var import_react54, jsx_dev_runtime5;
|
|
68878
68933
|
var init_StatusBar = __esm(async () => {
|
|
68934
|
+
init_useTerminalSize();
|
|
68879
68935
|
await __promiseAll([
|
|
68880
68936
|
init_build2(),
|
|
68881
68937
|
init_build3()
|
|
68882
68938
|
]);
|
|
68883
|
-
|
|
68939
|
+
import_react54 = __toESM(require_react(), 1);
|
|
68884
68940
|
jsx_dev_runtime5 = __toESM(require_jsx_dev_runtime(), 1);
|
|
68885
68941
|
});
|
|
68886
68942
|
|
|
@@ -69137,7 +69193,7 @@ var init_spawn = __esm(() => {
|
|
|
69137
69193
|
});
|
|
69138
69194
|
|
|
69139
69195
|
// packages/engine/src/formatters/claude-stream.ts
|
|
69140
|
-
function extractToolInputSummary(input) {
|
|
69196
|
+
function extractToolInputSummary(input, maxWidth) {
|
|
69141
69197
|
if (typeof input.file_path === "string") {
|
|
69142
69198
|
return { kind: "file", name: input.file_path.split("/").pop() ?? input.file_path };
|
|
69143
69199
|
}
|
|
@@ -69169,14 +69225,16 @@ function extractToolInputSummary(input) {
|
|
|
69169
69225
|
const keys2 = Object.keys(input);
|
|
69170
69226
|
if (keys2.length === 0)
|
|
69171
69227
|
return;
|
|
69228
|
+
const budget = maxWidth && maxWidth > 0 ? Math.max(80, maxWidth - PREFIX_PADDING) : LEGACY_BUDGET;
|
|
69229
|
+
const valueCap = maxWidth && maxWidth > 0 ? Math.max(LEGACY_VALUE_CAP, Math.floor(budget / 3)) : LEGACY_VALUE_CAP;
|
|
69172
69230
|
const parts = [];
|
|
69173
69231
|
let len = 0;
|
|
69174
69232
|
for (const k of keys2) {
|
|
69175
69233
|
const v = input[k];
|
|
69176
69234
|
const val = typeof v === "string" ? v : JSON.stringify(v);
|
|
69177
|
-
const short = val.length >
|
|
69235
|
+
const short = val.length > valueCap ? val.slice(0, valueCap) + "\u2026" : val;
|
|
69178
69236
|
const part = `${k}=${short}`;
|
|
69179
|
-
if (len + part.length >
|
|
69237
|
+
if (len + part.length > budget)
|
|
69180
69238
|
break;
|
|
69181
69239
|
parts.push(part);
|
|
69182
69240
|
len += part.length + 2;
|
|
@@ -69195,7 +69253,7 @@ function extractUsage(event) {
|
|
|
69195
69253
|
cache_creation_input_tokens: usage.cache_creation_input_tokens ?? 0
|
|
69196
69254
|
};
|
|
69197
69255
|
}
|
|
69198
|
-
function parseClaudeLine(line, state) {
|
|
69256
|
+
function parseClaudeLine(line, state, options) {
|
|
69199
69257
|
if (!line.trim())
|
|
69200
69258
|
return [];
|
|
69201
69259
|
let event;
|
|
@@ -69248,7 +69306,7 @@ function parseClaudeLine(line, state) {
|
|
|
69248
69306
|
} else if (btype === "tool_use") {
|
|
69249
69307
|
state.toolCount++;
|
|
69250
69308
|
const name = block.name ?? "?";
|
|
69251
|
-
const summary = extractToolInputSummary(block.input ?? {});
|
|
69309
|
+
const summary = extractToolInputSummary(block.input ?? {}, options?.maxWidth);
|
|
69252
69310
|
const ev = { type: "tool-start", name };
|
|
69253
69311
|
if (summary)
|
|
69254
69312
|
ev.summary = summary;
|
|
@@ -69325,6 +69383,7 @@ function parseClaudeLine(line, state) {
|
|
|
69325
69383
|
}
|
|
69326
69384
|
return events;
|
|
69327
69385
|
}
|
|
69386
|
+
var LEGACY_BUDGET = 120, LEGACY_VALUE_CAP = 40, PREFIX_PADDING = 20;
|
|
69328
69387
|
|
|
69329
69388
|
// packages/engine/src/agents/stream.ts
|
|
69330
69389
|
async function* streamLines(stream) {
|
|
@@ -69452,6 +69511,7 @@ var init_claude = __esm(() => {
|
|
|
69452
69511
|
let sessionId = null;
|
|
69453
69512
|
let detectedRateLimit = false;
|
|
69454
69513
|
const stdout = proc.stdout;
|
|
69514
|
+
const parseOptions = process.stdout.isTTY && process.stdout.columns ? { maxWidth: process.stdout.columns } : undefined;
|
|
69455
69515
|
for await (const line of streamLines(stdout)) {
|
|
69456
69516
|
req.onRawLine?.(line);
|
|
69457
69517
|
if (sessionId === null) {
|
|
@@ -69462,7 +69522,7 @@ var init_claude = __esm(() => {
|
|
|
69462
69522
|
}
|
|
69463
69523
|
} catch {}
|
|
69464
69524
|
}
|
|
69465
|
-
for (const event of parseClaudeLine(line, claudeState)) {
|
|
69525
|
+
for (const event of parseClaudeLine(line, claudeState, parseOptions)) {
|
|
69466
69526
|
if (event.type === "text" && isRateLimitText(event.text)) {
|
|
69467
69527
|
detectedRateLimit = true;
|
|
69468
69528
|
}
|
|
@@ -70117,6 +70177,10 @@ function commitTaskDir(taskDir, message) {
|
|
|
70117
70177
|
var init_git = () => {};
|
|
70118
70178
|
|
|
70119
70179
|
// packages/core/src/tasks-md.ts
|
|
70180
|
+
function isFlowTaskHeading(heading) {
|
|
70181
|
+
const stripped = heading.replace(/\s*\([^()]*\)\s*$/, "").trim();
|
|
70182
|
+
return FLOW_TASK_HEADING_PREFIXES.some((p) => stripped.startsWith(p));
|
|
70183
|
+
}
|
|
70120
70184
|
function firstUnchecked(tasksContent) {
|
|
70121
70185
|
const sections = tasksContent.split(/(?=^## )/m);
|
|
70122
70186
|
for (const section of sections) {
|
|
@@ -70159,6 +70223,49 @@ ${failureOutput.trim()}
|
|
|
70159
70223
|
${fence}`;
|
|
70160
70224
|
await Bun.write(tasksPath, prependSection(existing, stamped, body));
|
|
70161
70225
|
}
|
|
70226
|
+
function normalizeNewlyAppendedSectionWithReport(previous, current) {
|
|
70227
|
+
const prevHeadings = new Set;
|
|
70228
|
+
for (const line of previous.split(`
|
|
70229
|
+
`)) {
|
|
70230
|
+
if (line.startsWith("## "))
|
|
70231
|
+
prevHeadings.add(line);
|
|
70232
|
+
}
|
|
70233
|
+
const sections = current.split(/(?=^## )/m);
|
|
70234
|
+
const headings = [];
|
|
70235
|
+
let count = 0;
|
|
70236
|
+
const out = sections.map((section) => {
|
|
70237
|
+
const nlIdx = section.indexOf(`
|
|
70238
|
+
`);
|
|
70239
|
+
const headingLine = nlIdx === -1 ? section.replace(/\n$/, "") : section.slice(0, nlIdx);
|
|
70240
|
+
if (!headingLine.startsWith("## "))
|
|
70241
|
+
return section;
|
|
70242
|
+
if (prevHeadings.has(headingLine))
|
|
70243
|
+
return section;
|
|
70244
|
+
let localCount = 0;
|
|
70245
|
+
const rewritten = section.replace(/^(\s*)- \[[xX]\] (.+)$/gm, (_m, indent, rest2) => {
|
|
70246
|
+
localCount += 1;
|
|
70247
|
+
return `${indent}- [ ] ${rest2}`;
|
|
70248
|
+
});
|
|
70249
|
+
if (localCount > 0) {
|
|
70250
|
+
headings.push(headingLine.slice(3));
|
|
70251
|
+
count += localCount;
|
|
70252
|
+
}
|
|
70253
|
+
return rewritten;
|
|
70254
|
+
});
|
|
70255
|
+
return { text: count > 0 ? out.join("") : current, headings, count };
|
|
70256
|
+
}
|
|
70257
|
+
var MISSION_TASKS_FILENAME = "tasks.md", AGENT_TASKS_FILENAME = "agent-tasks.md", FLOW_TASK_HEADING_PREFIXES;
|
|
70258
|
+
var init_tasks_md = __esm(() => {
|
|
70259
|
+
FLOW_TASK_HEADING_PREFIXES = [
|
|
70260
|
+
"Fix failing CI checks",
|
|
70261
|
+
"Fix push rejection",
|
|
70262
|
+
"Resolve PR merge conflicts",
|
|
70263
|
+
"Resolve merge conflict with origin/",
|
|
70264
|
+
"Address reviewer comments",
|
|
70265
|
+
"Address GitHub @ralphy mention",
|
|
70266
|
+
"Address Linear @ralphy mention"
|
|
70267
|
+
];
|
|
70268
|
+
});
|
|
70162
70269
|
|
|
70163
70270
|
// packages/core/src/loop.ts
|
|
70164
70271
|
import { join as join10 } from "path";
|
|
@@ -70184,9 +70291,21 @@ function buildTaskPrompt(state, taskDir) {
|
|
|
70184
70291
|
`;
|
|
70185
70292
|
}
|
|
70186
70293
|
}
|
|
70187
|
-
const
|
|
70188
|
-
|
|
70189
|
-
|
|
70294
|
+
const agentTasksPath = join10(taskDir, AGENT_TASKS_FILENAME);
|
|
70295
|
+
const missionTasksPath = join10(taskDir, MISSION_TASKS_FILENAME);
|
|
70296
|
+
const agentTasksContent = storage.read(agentTasksPath);
|
|
70297
|
+
const missionTasksContent = storage.read(missionTasksPath);
|
|
70298
|
+
let activePath = null;
|
|
70299
|
+
let activeContent = null;
|
|
70300
|
+
if (agentTasksContent !== null && /^- \[ \]/m.test(agentTasksContent)) {
|
|
70301
|
+
activePath = agentTasksPath;
|
|
70302
|
+
activeContent = agentTasksContent;
|
|
70303
|
+
} else if (missionTasksContent !== null) {
|
|
70304
|
+
activePath = missionTasksPath;
|
|
70305
|
+
activeContent = missionTasksContent;
|
|
70306
|
+
}
|
|
70307
|
+
if (activeContent !== null && activePath !== null) {
|
|
70308
|
+
const section = firstUnchecked(activeContent);
|
|
70190
70309
|
if (section) {
|
|
70191
70310
|
prompt += `---
|
|
70192
70311
|
|
|
@@ -70199,7 +70318,7 @@ function buildTaskPrompt(state, taskDir) {
|
|
|
70199
70318
|
prompt += `---
|
|
70200
70319
|
|
|
70201
70320
|
`;
|
|
70202
|
-
prompt += `**Tracking progress**: as you finish each item above, edit ` + `\`${
|
|
70321
|
+
prompt += `**Tracking progress**: as you finish each item above, edit ` + `\`${activePath}\` and change its \`- [ ]\` to ` + `\`- [x]\` in the same commit. The loop reads this file between ` + `iterations and stops when no \`- [ ]\` items remain \u2014 if you do ` + `not tick the box, the next iteration will repeat this task.
|
|
70203
70322
|
|
|
70204
70323
|
`;
|
|
70205
70324
|
}
|
|
@@ -70220,10 +70339,11 @@ function buildTaskPrompt(state, taskDir) {
|
|
|
70220
70339
|
`;
|
|
70221
70340
|
}
|
|
70222
70341
|
if (state.manualTest) {
|
|
70223
|
-
const
|
|
70224
|
-
const
|
|
70225
|
-
|
|
70226
|
-
|
|
70342
|
+
const tasksContent = missionTasksContent;
|
|
70343
|
+
const hasUncheckedMission = tasksContent !== null && /^- \[ \]/m.test(tasksContent);
|
|
70344
|
+
const hasUncheckedAgent = agentTasksContent !== null && /^- \[ \]/m.test(agentTasksContent);
|
|
70345
|
+
if (!hasUncheckedMission && !hasUncheckedAgent) {
|
|
70346
|
+
const hasManualTestSection = tasksContent !== null && /^## Manual Testing/m.test(tasksContent);
|
|
70227
70347
|
if (!hasManualTestSection) {
|
|
70228
70348
|
prompt += `---
|
|
70229
70349
|
|
|
@@ -70379,11 +70499,14 @@ var STEERING_MAX_LINES = 20;
|
|
|
70379
70499
|
var init_loop = __esm(() => {
|
|
70380
70500
|
init_state();
|
|
70381
70501
|
init_context();
|
|
70502
|
+
init_tasks_md();
|
|
70503
|
+
init_tasks_md();
|
|
70382
70504
|
});
|
|
70383
70505
|
|
|
70384
70506
|
// apps/loop/src/loop.ts
|
|
70385
70507
|
var init_loop2 = __esm(() => {
|
|
70386
70508
|
init_loop();
|
|
70509
|
+
init_tasks_md();
|
|
70387
70510
|
});
|
|
70388
70511
|
|
|
70389
70512
|
// apps/loop/src/hooks/useLoop.ts
|
|
@@ -70392,22 +70515,22 @@ function sleep(seconds) {
|
|
|
70392
70515
|
return new Promise((resolve3) => setTimeout(resolve3, seconds * 1000));
|
|
70393
70516
|
}
|
|
70394
70517
|
function useLoop(opts) {
|
|
70395
|
-
const [state, setState] =
|
|
70396
|
-
const [iteration, setIteration] =
|
|
70397
|
-
const [consecutiveFailures, setConsecutiveFailures] =
|
|
70398
|
-
const [logLines, setLogLines] =
|
|
70399
|
-
const [stopReason, setStopReason] =
|
|
70400
|
-
const [isRunning, setIsRunning] =
|
|
70401
|
-
const [isResume, setIsResume] =
|
|
70402
|
-
const [startedAt] =
|
|
70403
|
-
const lineIdRef =
|
|
70404
|
-
const steerControllerRef =
|
|
70405
|
-
const pendingSteerRef =
|
|
70518
|
+
const [state, setState] = import_react55.useState(null);
|
|
70519
|
+
const [iteration, setIteration] = import_react55.useState(0);
|
|
70520
|
+
const [consecutiveFailures, setConsecutiveFailures] = import_react55.useState(0);
|
|
70521
|
+
const [logLines, setLogLines] = import_react55.useState([]);
|
|
70522
|
+
const [stopReason, setStopReason] = import_react55.useState(null);
|
|
70523
|
+
const [isRunning, setIsRunning] = import_react55.useState(true);
|
|
70524
|
+
const [isResume, setIsResume] = import_react55.useState(false);
|
|
70525
|
+
const [startedAt] = import_react55.useState(() => Date.now());
|
|
70526
|
+
const lineIdRef = import_react55.useRef(0);
|
|
70527
|
+
const steerControllerRef = import_react55.useRef(null);
|
|
70528
|
+
const pendingSteerRef = import_react55.useRef(null);
|
|
70406
70529
|
const steer = (message) => {
|
|
70407
70530
|
pendingSteerRef.current = message;
|
|
70408
70531
|
steerControllerRef.current?.abort();
|
|
70409
70532
|
};
|
|
70410
|
-
|
|
70533
|
+
import_react55.useEffect(() => {
|
|
70411
70534
|
let cancelled = false;
|
|
70412
70535
|
const nextId = () => String(lineIdRef.current++);
|
|
70413
70536
|
const addInfo = (text) => {
|
|
@@ -70471,15 +70594,24 @@ function useLoop(opts) {
|
|
|
70471
70594
|
const stop = checkStopCondition(currentState, iter, opts, loopStartTime, consFailures);
|
|
70472
70595
|
if (stop !== null) {
|
|
70473
70596
|
finalStopReason = stop;
|
|
70474
|
-
setStopReason(stop);
|
|
70475
70597
|
break;
|
|
70476
70598
|
}
|
|
70477
|
-
const tasksContent = storage.read(join11(tasksDir,
|
|
70599
|
+
const tasksContent = storage.read(join11(tasksDir, MISSION_TASKS_FILENAME));
|
|
70600
|
+
const agentTasksContent = storage.read(join11(tasksDir, AGENT_TASKS_FILENAME));
|
|
70478
70601
|
if (tasksContent !== null) {
|
|
70479
70602
|
const remaining = countUnchecked(tasksContent);
|
|
70480
|
-
|
|
70481
|
-
|
|
70482
|
-
|
|
70603
|
+
const agentRemaining = agentTasksContent !== null ? countUnchecked(agentTasksContent) : 0;
|
|
70604
|
+
const parts = [
|
|
70605
|
+
`tasks.md: ${remaining} unchecked item${remaining === 1 ? "" : "s"} remaining`
|
|
70606
|
+
];
|
|
70607
|
+
if (agentTasksContent !== null) {
|
|
70608
|
+
parts.push(`agent-tasks.md: ${agentRemaining} unchecked item${agentRemaining === 1 ? "" : "s"} remaining`);
|
|
70609
|
+
}
|
|
70610
|
+
addInfo(parts.join(" \xB7 "));
|
|
70611
|
+
}
|
|
70612
|
+
const missionDone = tasksContent !== null && allCompleted(tasksContent);
|
|
70613
|
+
const agentDone = agentTasksContent === null || allCompleted(agentTasksContent);
|
|
70614
|
+
if (missionDone && agentDone && tasksContent !== null) {
|
|
70483
70615
|
addInfo("All tasks completed \u2014 archiving change.");
|
|
70484
70616
|
currentState = {
|
|
70485
70617
|
...currentState,
|
|
@@ -70495,7 +70627,6 @@ function useLoop(opts) {
|
|
|
70495
70627
|
addInfo(`Archive warning: ${err}`);
|
|
70496
70628
|
}
|
|
70497
70629
|
finalStopReason = "completed";
|
|
70498
|
-
setStopReason("completed");
|
|
70499
70630
|
break;
|
|
70500
70631
|
}
|
|
70501
70632
|
iter++;
|
|
@@ -70555,7 +70686,6 @@ function useLoop(opts) {
|
|
|
70555
70686
|
if (failure.shouldStop || engineResult.rateLimited) {
|
|
70556
70687
|
capture("engine_rate_limited", { exit_code: engineResult.exitCode, iteration: iter });
|
|
70557
70688
|
finalStopReason = "rateLimited";
|
|
70558
|
-
setStopReason("rateLimited");
|
|
70559
70689
|
break;
|
|
70560
70690
|
}
|
|
70561
70691
|
capture("iteration_failed", {
|
|
@@ -70614,6 +70744,9 @@ function useLoop(opts) {
|
|
|
70614
70744
|
gitPush();
|
|
70615
70745
|
} catch {}
|
|
70616
70746
|
}
|
|
70747
|
+
if (finalStopReason !== null) {
|
|
70748
|
+
setStopReason(finalStopReason);
|
|
70749
|
+
}
|
|
70617
70750
|
setIsRunning(false);
|
|
70618
70751
|
});
|
|
70619
70752
|
return () => {
|
|
@@ -70632,7 +70765,7 @@ function useLoop(opts) {
|
|
|
70632
70765
|
steer
|
|
70633
70766
|
};
|
|
70634
70767
|
}
|
|
70635
|
-
var
|
|
70768
|
+
var import_react55;
|
|
70636
70769
|
var init_useLoop = __esm(() => {
|
|
70637
70770
|
init_state();
|
|
70638
70771
|
init_engine();
|
|
@@ -70640,7 +70773,7 @@ var init_useLoop = __esm(() => {
|
|
|
70640
70773
|
init_context();
|
|
70641
70774
|
init_src();
|
|
70642
70775
|
init_loop2();
|
|
70643
|
-
|
|
70776
|
+
import_react55 = __toESM(require_react(), 1);
|
|
70644
70777
|
});
|
|
70645
70778
|
|
|
70646
70779
|
// apps/loop/src/components/TaskLoop.tsx
|
|
@@ -70695,10 +70828,10 @@ function handleSteerKeyInput(key, history, currentIndex) {
|
|
|
70695
70828
|
return navigateHistory(history, currentIndex, dir);
|
|
70696
70829
|
}
|
|
70697
70830
|
function SteerInput({ onSubmit }) {
|
|
70698
|
-
const [inputKey, setInputKey] =
|
|
70699
|
-
const [defaultValue, setDefaultValue] =
|
|
70700
|
-
const historyRef =
|
|
70701
|
-
const historyIndexRef =
|
|
70831
|
+
const [inputKey, setInputKey] = import_react56.useState(0);
|
|
70832
|
+
const [defaultValue, setDefaultValue] = import_react56.useState("");
|
|
70833
|
+
const historyRef = import_react56.useRef([]);
|
|
70834
|
+
const historyIndexRef = import_react56.useRef(-1);
|
|
70702
70835
|
use_input_default((_input, key) => {
|
|
70703
70836
|
const result2 = handleSteerKeyInput(key, historyRef.current, historyIndexRef.current);
|
|
70704
70837
|
if (result2) {
|
|
@@ -70730,12 +70863,19 @@ function TaskLoop({ opts }) {
|
|
|
70730
70863
|
const { exit } = use_app_default();
|
|
70731
70864
|
const loop = useLoop(opts);
|
|
70732
70865
|
const { isRawModeSupported } = use_stdin_default();
|
|
70733
|
-
const
|
|
70734
|
-
const
|
|
70866
|
+
const { stdout } = use_stdout_default();
|
|
70867
|
+
const { resizeKey } = useTerminalSize();
|
|
70868
|
+
const bannerItem = import_react56.useRef({ id: "__banner__", kind: "banner" });
|
|
70869
|
+
import_react56.useEffect(() => {
|
|
70870
|
+
if (resizeKey === 0)
|
|
70871
|
+
return;
|
|
70872
|
+
stdout.write("\x1B[2J\x1B[3J\x1B[H");
|
|
70873
|
+
}, [resizeKey, stdout]);
|
|
70874
|
+
const feedItems = import_react56.useMemo(() => [
|
|
70735
70875
|
bannerItem.current,
|
|
70736
70876
|
...loop.logLines.map((e) => ({ id: e.id, kind: "entry", entry: e }))
|
|
70737
70877
|
], [loop.logLines]);
|
|
70738
|
-
|
|
70878
|
+
import_react56.useEffect(() => {
|
|
70739
70879
|
if (!loop.isRunning) {
|
|
70740
70880
|
exit();
|
|
70741
70881
|
}
|
|
@@ -70783,7 +70923,7 @@ function TaskLoop({ opts }) {
|
|
|
70783
70923
|
}, undefined, false, undefined, this)
|
|
70784
70924
|
]
|
|
70785
70925
|
}, undefined, true, undefined, this),
|
|
70786
|
-
loop.stopReason && /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(jsx_dev_runtime7.Fragment, {
|
|
70926
|
+
!loop.isRunning && loop.stopReason && /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(jsx_dev_runtime7.Fragment, {
|
|
70787
70927
|
children: [
|
|
70788
70928
|
/* @__PURE__ */ jsx_dev_runtime7.jsxDEV(StatusBar, {
|
|
70789
70929
|
iteration: loop.iteration,
|
|
@@ -70805,11 +70945,12 @@ function TaskLoop({ opts }) {
|
|
|
70805
70945
|
]
|
|
70806
70946
|
}, undefined, true, undefined, this)
|
|
70807
70947
|
]
|
|
70808
|
-
},
|
|
70948
|
+
}, resizeKey, true, undefined, this);
|
|
70809
70949
|
}
|
|
70810
|
-
var
|
|
70950
|
+
var import_react56, jsx_dev_runtime7;
|
|
70811
70951
|
var init_TaskLoop = __esm(async () => {
|
|
70812
70952
|
init_useLoop();
|
|
70953
|
+
init_useTerminalSize();
|
|
70813
70954
|
await __promiseAll([
|
|
70814
70955
|
init_build2(),
|
|
70815
70956
|
init_build3(),
|
|
@@ -70819,7 +70960,7 @@ var init_TaskLoop = __esm(async () => {
|
|
|
70819
70960
|
init_StatusBar(),
|
|
70820
70961
|
init_StopMessage()
|
|
70821
70962
|
]);
|
|
70822
|
-
|
|
70963
|
+
import_react56 = __toESM(require_react(), 1);
|
|
70823
70964
|
jsx_dev_runtime7 = __toESM(require_jsx_dev_runtime(), 1);
|
|
70824
70965
|
});
|
|
70825
70966
|
|
|
@@ -70827,7 +70968,7 @@ var init_TaskLoop = __esm(async () => {
|
|
|
70827
70968
|
import { join as join13 } from "path";
|
|
70828
70969
|
function ExitAfterRender({ children }) {
|
|
70829
70970
|
const { exit } = use_app_default();
|
|
70830
|
-
|
|
70971
|
+
import_react57.useEffect(() => {
|
|
70831
70972
|
exit();
|
|
70832
70973
|
}, [exit]);
|
|
70833
70974
|
return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(jsx_dev_runtime8.Fragment, {
|
|
@@ -70836,7 +70977,7 @@ function ExitAfterRender({ children }) {
|
|
|
70836
70977
|
}
|
|
70837
70978
|
function ErrorMessage({ message }) {
|
|
70838
70979
|
const { exit } = use_app_default();
|
|
70839
|
-
|
|
70980
|
+
import_react57.useEffect(() => {
|
|
70840
70981
|
process.exitCode = 1;
|
|
70841
70982
|
exit();
|
|
70842
70983
|
}, [exit]);
|
|
@@ -70915,7 +71056,7 @@ function App2({ args, statesDir, tasksDir }) {
|
|
|
70915
71056
|
}
|
|
70916
71057
|
}
|
|
70917
71058
|
}
|
|
70918
|
-
var
|
|
71059
|
+
var import_react57, jsx_dev_runtime8;
|
|
70919
71060
|
var init_App2 = __esm(async () => {
|
|
70920
71061
|
init_state();
|
|
70921
71062
|
init_context();
|
|
@@ -70925,7 +71066,7 @@ var init_App2 = __esm(async () => {
|
|
|
70925
71066
|
init_TaskStatus(),
|
|
70926
71067
|
init_TaskLoop()
|
|
70927
71068
|
]);
|
|
70928
|
-
|
|
71069
|
+
import_react57 = __toESM(require_react(), 1);
|
|
70929
71070
|
jsx_dev_runtime8 = __toESM(require_jsx_dev_runtime(), 1);
|
|
70930
71071
|
});
|
|
70931
71072
|
|
|
@@ -79420,7 +79561,7 @@ __export(exports_regexes, {
|
|
|
79420
79561
|
integer: () => integer,
|
|
79421
79562
|
idnEmail: () => idnEmail,
|
|
79422
79563
|
html5Email: () => html5Email,
|
|
79423
|
-
hostname: () =>
|
|
79564
|
+
hostname: () => hostname2,
|
|
79424
79565
|
hex: () => hex,
|
|
79425
79566
|
guid: () => guid,
|
|
79426
79567
|
extendedDuration: () => extendedDuration,
|
|
@@ -79475,7 +79616,7 @@ var cuid, cuid2, ulid, xid, ksuid, nanoid, duration, extendedDuration, guid, uui
|
|
|
79475
79616
|
}, uuid4, uuid6, uuid7, email, html5Email, rfc5322Email, unicodeEmail, idnEmail, browserEmail, _emoji = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`, ipv4, ipv6, mac = (delimiter) => {
|
|
79476
79617
|
const escapedDelim = escapeRegex(delimiter ?? ":");
|
|
79477
79618
|
return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
|
|
79478
|
-
}, cidrv4, cidrv6, base64, base64url,
|
|
79619
|
+
}, cidrv4, cidrv6, base64, base64url, hostname2, domain, e164, dateSource = `(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))`, date, string = (params) => {
|
|
79479
79620
|
const regex2 = params ? `[\\s\\S]{${params?.minimum ?? 0},${params?.maximum ?? ""}}` : `[\\s\\S]*`;
|
|
79480
79621
|
return new RegExp(`^${regex2}$`);
|
|
79481
79622
|
}, bigint, integer, number, boolean, _null, _undefined, lowercase, uppercase, hex, md5_hex, md5_base64, md5_base64url, sha1_hex, sha1_base64, sha1_base64url, sha256_hex, sha256_base64, sha256_base64url, sha384_hex, sha384_base64, sha384_base64url, sha512_hex, sha512_base64, sha512_base64url;
|
|
@@ -79505,7 +79646,7 @@ var init_regexes = __esm(() => {
|
|
|
79505
79646
|
cidrv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
|
|
79506
79647
|
base64 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
|
|
79507
79648
|
base64url = /^[A-Za-z0-9_-]*$/;
|
|
79508
|
-
|
|
79649
|
+
hostname2 = /^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
|
|
79509
79650
|
domain = /^([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/;
|
|
79510
79651
|
e164 = /^\+[1-9]\d{6,14}$/;
|
|
79511
79652
|
date = /* @__PURE__ */ new RegExp(`^${dateSource}$`);
|
|
@@ -90290,7 +90431,7 @@ __export(exports_schemas2, {
|
|
|
90290
90431
|
int: () => int,
|
|
90291
90432
|
instanceof: () => _instanceof,
|
|
90292
90433
|
httpUrl: () => httpUrl,
|
|
90293
|
-
hostname: () =>
|
|
90434
|
+
hostname: () => hostname3,
|
|
90294
90435
|
hex: () => hex2,
|
|
90295
90436
|
hash: () => hash,
|
|
90296
90437
|
guid: () => guid2,
|
|
@@ -90474,7 +90615,7 @@ function jwt(params) {
|
|
|
90474
90615
|
function stringFormat(format2, fnOrRegex, _params = {}) {
|
|
90475
90616
|
return _stringFormat(ZodCustomStringFormat, format2, fnOrRegex, _params);
|
|
90476
90617
|
}
|
|
90477
|
-
function
|
|
90618
|
+
function hostname3(_params) {
|
|
90478
90619
|
return _stringFormat(ZodCustomStringFormat, "hostname", exports_regexes.hostname, _params);
|
|
90479
90620
|
}
|
|
90480
90621
|
function hex2(_params) {
|
|
@@ -92112,7 +92253,7 @@ __export(exports_external2, {
|
|
|
92112
92253
|
instanceof: () => _instanceof,
|
|
92113
92254
|
includes: () => _includes,
|
|
92114
92255
|
httpUrl: () => httpUrl,
|
|
92115
|
-
hostname: () =>
|
|
92256
|
+
hostname: () => hostname3,
|
|
92116
92257
|
hex: () => hex2,
|
|
92117
92258
|
hash: () => hash,
|
|
92118
92259
|
guid: () => guid2,
|
|
@@ -92364,6 +92505,7 @@ var init_schema = __esm(() => {
|
|
|
92364
92505
|
mentionHandle: exports_external2.string().default("@ralphy"),
|
|
92365
92506
|
codeReviewTrigger: exports_external2.boolean().default(false),
|
|
92366
92507
|
codeReviewStaleHours: exports_external2.number().nonnegative().default(24),
|
|
92508
|
+
syncTasksToDescription: exports_external2.boolean().default(false),
|
|
92367
92509
|
indicators: IndicatorsSchema.default({})
|
|
92368
92510
|
}).strict().default({
|
|
92369
92511
|
postComments: true,
|
|
@@ -92372,6 +92514,7 @@ var init_schema = __esm(() => {
|
|
|
92372
92514
|
mentionHandle: "@ralphy",
|
|
92373
92515
|
codeReviewTrigger: false,
|
|
92374
92516
|
codeReviewStaleHours: 24,
|
|
92517
|
+
syncTasksToDescription: false,
|
|
92375
92518
|
indicators: {}
|
|
92376
92519
|
}),
|
|
92377
92520
|
github: exports_external2.object({
|
|
@@ -92394,7 +92537,20 @@ var init_schema = __esm(() => {
|
|
|
92394
92537
|
fix_on_failure: exports_external2.boolean().optional(),
|
|
92395
92538
|
max_attempts: exports_external2.number().int().positive().optional(),
|
|
92396
92539
|
poll_interval_seconds: exports_external2.number().int().positive().optional()
|
|
92397
|
-
}).strict().optional()
|
|
92540
|
+
}).strict().optional(),
|
|
92541
|
+
preExistingErrorCheck: exports_external2.object({
|
|
92542
|
+
enabled: exports_external2.boolean().default(false),
|
|
92543
|
+
commands: exports_external2.array(exports_external2.string()).default([]),
|
|
92544
|
+
baseBranch: exports_external2.string().default("main"),
|
|
92545
|
+
label: exports_external2.string().default("ralph:pre-existing-error"),
|
|
92546
|
+
outputCharLimit: exports_external2.number().int().positive().default(4000)
|
|
92547
|
+
}).strict().default({
|
|
92548
|
+
enabled: false,
|
|
92549
|
+
commands: [],
|
|
92550
|
+
baseBranch: "main",
|
|
92551
|
+
label: "ralph:pre-existing-error",
|
|
92552
|
+
outputCharLimit: 4000
|
|
92553
|
+
})
|
|
92398
92554
|
});
|
|
92399
92555
|
});
|
|
92400
92556
|
|
|
@@ -92478,6 +92634,17 @@ engine: claude
|
|
|
92478
92634
|
# Model tier: "haiku", "sonnet", or "opus".
|
|
92479
92635
|
model: opus
|
|
92480
92636
|
|
|
92637
|
+
# Pre-existing error check: gate the agent when the base branch is already broken.
|
|
92638
|
+
# When enabled, the agent runs these commands against the base branch HEAD before
|
|
92639
|
+
# scheduling new work; failures open a Linear ticket and pause new pickups.
|
|
92640
|
+
preExistingErrorCheck:
|
|
92641
|
+
enabled: false
|
|
92642
|
+
# Commands to run against the base branch. When empty, falls back to commands.lint / commands.test.
|
|
92643
|
+
commands: []
|
|
92644
|
+
baseBranch: main
|
|
92645
|
+
label: "ralph:pre-existing-error"
|
|
92646
|
+
outputCharLimit: 4000
|
|
92647
|
+
|
|
92481
92648
|
linear:
|
|
92482
92649
|
# Linear team key (e.g. "ENG"). Omit to match all teams.
|
|
92483
92650
|
# team: ENG
|
|
@@ -92496,6 +92663,11 @@ linear:
|
|
|
92496
92663
|
codeReviewTrigger: false
|
|
92497
92664
|
codeReviewStaleHours: 24
|
|
92498
92665
|
|
|
92666
|
+
# Mirror the loop's tasks.md into the Linear issue description as a
|
|
92667
|
+
# checklist between sentinel markers. Updates on worker launch, on the
|
|
92668
|
+
# same cadence as updateEveryIterations, and on done-transition.
|
|
92669
|
+
syncTasksToDescription: false
|
|
92670
|
+
|
|
92499
92671
|
# Indicators map Ralph lifecycle events to Linear labels/statuses.
|
|
92500
92672
|
# Grouped by lifecycle: each get* is followed by the set*/clear* that
|
|
92501
92673
|
# mutates the same state, so the lifecycle reads top-to-bottom.
|
|
@@ -92556,6 +92728,10 @@ Previous attempt failed with: {{ last_error }}
|
|
|
92556
92728
|
|
|
92557
92729
|
{{ issue.description }}
|
|
92558
92730
|
|
|
92731
|
+
{% if issue.labels %}
|
|
92732
|
+
Labels: {{ issue.labels | join(", ") }}
|
|
92733
|
+
{% endif %}
|
|
92734
|
+
|
|
92559
92735
|
{% if rules %}
|
|
92560
92736
|
Project rules:
|
|
92561
92737
|
{% for rule in rules %}- {{ rule }}
|
|
@@ -92743,6 +92919,7 @@ function renderTemplate(src, ctx) {
|
|
|
92743
92919
|
var exports_workflow = {};
|
|
92744
92920
|
__export(exports_workflow, {
|
|
92745
92921
|
workflowPath: () => workflowPath,
|
|
92922
|
+
resolveBaselineCommands: () => resolveBaselineCommands,
|
|
92746
92923
|
renderWorkflowPrompt: () => renderWorkflowPrompt,
|
|
92747
92924
|
renderTemplate: () => renderTemplate,
|
|
92748
92925
|
parseWorkflow: () => parseWorkflow,
|
|
@@ -92875,6 +93052,17 @@ function extractDefaultBody() {
|
|
|
92875
93052
|
const m = FRONTMATTER_RE.exec(DEFAULT_WORKFLOW_MD);
|
|
92876
93053
|
return m ? m[2] ?? "" : "";
|
|
92877
93054
|
}
|
|
93055
|
+
function resolveBaselineCommands(config2) {
|
|
93056
|
+
const configured = config2.preExistingErrorCheck?.commands ?? [];
|
|
93057
|
+
if (configured.length > 0)
|
|
93058
|
+
return [...configured];
|
|
93059
|
+
const fallback = [];
|
|
93060
|
+
if (config2.commands.lint)
|
|
93061
|
+
fallback.push(config2.commands.lint);
|
|
93062
|
+
if (config2.commands.test)
|
|
93063
|
+
fallback.push(config2.commands.test);
|
|
93064
|
+
return fallback;
|
|
93065
|
+
}
|
|
92878
93066
|
function renderWorkflowPrompt(workflow, ctx) {
|
|
92879
93067
|
const fullCtx = {
|
|
92880
93068
|
project: workflow.config.project,
|
|
@@ -93027,12 +93215,12 @@ async function main(argv) {
|
|
|
93027
93215
|
await ensureRalphGitignore(projectRoot);
|
|
93028
93216
|
}
|
|
93029
93217
|
await runWithContext(createDefaultContext(), async () => {
|
|
93030
|
-
const { waitUntilExit } = render_default(
|
|
93218
|
+
const { waitUntilExit } = render_default(import_react58.createElement(App2, { args, statesDir, tasksDir, projectRoot }));
|
|
93031
93219
|
await waitUntilExit();
|
|
93032
93220
|
});
|
|
93033
93221
|
return typeof process.exitCode === "number" ? process.exitCode : 0;
|
|
93034
93222
|
}
|
|
93035
|
-
var
|
|
93223
|
+
var import_react58;
|
|
93036
93224
|
var init_src5 = __esm(async () => {
|
|
93037
93225
|
init_context();
|
|
93038
93226
|
init_layout();
|
|
@@ -93044,7 +93232,7 @@ var init_src5 = __esm(async () => {
|
|
|
93044
93232
|
init_build2(),
|
|
93045
93233
|
init_App2()
|
|
93046
93234
|
]);
|
|
93047
|
-
|
|
93235
|
+
import_react58 = __toESM(require_react(), 1);
|
|
93048
93236
|
});
|
|
93049
93237
|
|
|
93050
93238
|
// apps/agent/src/cli.ts
|
|
@@ -93225,6 +93413,9 @@ async function parseArgs2(argv) {
|
|
|
93225
93413
|
case "--debug":
|
|
93226
93414
|
result2.debug = true;
|
|
93227
93415
|
break;
|
|
93416
|
+
case "--pre-existing-error-check":
|
|
93417
|
+
result2.preExistingErrorCheck = true;
|
|
93418
|
+
break;
|
|
93228
93419
|
default:
|
|
93229
93420
|
if (VALID_MODES2.has(arg)) {
|
|
93230
93421
|
result2.mode = arg;
|
|
@@ -93305,6 +93496,7 @@ var init_cli2 = __esm(() => {
|
|
|
93305
93496
|
" --code-review Watch open tracked PRs for unresolved review comments",
|
|
93306
93497
|
" --max-tickets <n> Stop picking up new issues after N have been started (0 = unlimited)",
|
|
93307
93498
|
" --json-output Emit JSONL to stdout instead of the Ink dashboard (for scripting/CI)",
|
|
93499
|
+
" --pre-existing-error-check Run baseline commands against the base branch; pause new pickups + open a Linear ticket when red",
|
|
93308
93500
|
" --debug List mode: explain why a Linear ticket was not picked up (use with --name)",
|
|
93309
93501
|
" --help, -h Show this help message",
|
|
93310
93502
|
"",
|
|
@@ -93420,12 +93612,57 @@ function buildIssueFilter(spec) {
|
|
|
93420
93612
|
}
|
|
93421
93613
|
return where;
|
|
93422
93614
|
}
|
|
93615
|
+
async function fetchMentionScanIssues(apiKey, spec) {
|
|
93616
|
+
const where = {
|
|
93617
|
+
state: { type: { in: ["unstarted", "started", "backlog", "triage", "completed"] } }
|
|
93618
|
+
};
|
|
93619
|
+
if (spec.team)
|
|
93620
|
+
where.team = { key: { eq: spec.team } };
|
|
93621
|
+
if (spec.assignee) {
|
|
93622
|
+
if (spec.assignee === "me")
|
|
93623
|
+
where.assignee = { isMe: { eq: true } };
|
|
93624
|
+
else if (spec.assignee.includes("@"))
|
|
93625
|
+
where.assignee = { email: { eq: spec.assignee } };
|
|
93626
|
+
else
|
|
93627
|
+
where.assignee = { id: { eq: spec.assignee } };
|
|
93628
|
+
}
|
|
93629
|
+
const query = `query MentionScanIssues($filter: IssueFilter) {
|
|
93630
|
+
issues(filter: $filter, first: 50) {
|
|
93631
|
+
nodes {
|
|
93632
|
+
id identifier title description url priority createdAt
|
|
93633
|
+
state { name type }
|
|
93634
|
+
assignee { id email name }
|
|
93635
|
+
labels { nodes { name } }
|
|
93636
|
+
relations(first: 50) {
|
|
93637
|
+
nodes { type relatedIssue { id state { type } } }
|
|
93638
|
+
}
|
|
93639
|
+
}
|
|
93640
|
+
}
|
|
93641
|
+
}`;
|
|
93642
|
+
const data = await linearRequest(apiKey, query, {
|
|
93643
|
+
filter: where
|
|
93644
|
+
});
|
|
93645
|
+
const DONE_STATE_TYPES = new Set(["completed", "cancelled"]);
|
|
93646
|
+
return data.issues.nodes.map((n) => ({
|
|
93647
|
+
id: n.id,
|
|
93648
|
+
identifier: n.identifier,
|
|
93649
|
+
title: n.title,
|
|
93650
|
+
description: n.description,
|
|
93651
|
+
url: n.url,
|
|
93652
|
+
state: n.state,
|
|
93653
|
+
assignee: n.assignee,
|
|
93654
|
+
labels: n.labels.nodes.map((l) => l.name),
|
|
93655
|
+
priority: n.priority,
|
|
93656
|
+
createdAt: n.createdAt ?? "",
|
|
93657
|
+
blockedByIds: (n.relations?.nodes ?? []).filter((r) => r.type === "blocked_by" && !DONE_STATE_TYPES.has(r.relatedIssue.state.type)).map((r) => r.relatedIssue.id)
|
|
93658
|
+
}));
|
|
93659
|
+
}
|
|
93423
93660
|
async function fetchOpenIssues(apiKey, spec) {
|
|
93424
93661
|
const where = buildIssueFilter(spec);
|
|
93425
93662
|
const query = `query Issues($filter: IssueFilter) {
|
|
93426
93663
|
issues(filter: $filter, first: 50) {
|
|
93427
93664
|
nodes {
|
|
93428
|
-
id identifier title description url priority
|
|
93665
|
+
id identifier title description url priority createdAt
|
|
93429
93666
|
state { name type }
|
|
93430
93667
|
assignee { id email name }
|
|
93431
93668
|
labels { nodes { name } }
|
|
@@ -93452,6 +93689,7 @@ async function fetchOpenIssues(apiKey, spec) {
|
|
|
93452
93689
|
assignee: n.assignee,
|
|
93453
93690
|
labels: n.labels.nodes.map((l) => l.name),
|
|
93454
93691
|
priority: n.priority,
|
|
93692
|
+
createdAt: n.createdAt ?? "",
|
|
93455
93693
|
blockedByIds: (n.relations?.nodes ?? []).filter((r) => r.type === "blocked_by" && !DONE_STATE_TYPES.has(r.relatedIssue.state.type)).map((r) => r.relatedIssue.id)
|
|
93456
93694
|
}));
|
|
93457
93695
|
}
|
|
@@ -93478,6 +93716,15 @@ async function linearRequest(apiKey, query, variables) {
|
|
|
93478
93716
|
}
|
|
93479
93717
|
return json2.data;
|
|
93480
93718
|
}
|
|
93719
|
+
async function addReactionToComment(apiKey, commentId, emoji3) {
|
|
93720
|
+
const mutation = `mutation Reaction($commentId: String!, $emoji: String!) {
|
|
93721
|
+
reactionCreate(input: { commentId: $commentId, emoji: $emoji }) { success }
|
|
93722
|
+
}`;
|
|
93723
|
+
await linearRequest(apiKey, mutation, {
|
|
93724
|
+
commentId,
|
|
93725
|
+
emoji: emoji3
|
|
93726
|
+
});
|
|
93727
|
+
}
|
|
93481
93728
|
async function addIssueComment(apiKey, issueId, body) {
|
|
93482
93729
|
const mutation = `mutation Comment($issueId: String!, $body: String!) {
|
|
93483
93730
|
commentCreate(input: { issueId: $issueId, body: $body }) { success }
|
|
@@ -93653,6 +93900,53 @@ function issueMatchesGetIndicator(issue2, indicator) {
|
|
|
93653
93900
|
return false;
|
|
93654
93901
|
});
|
|
93655
93902
|
}
|
|
93903
|
+
async function createIssue(apiKey, input) {
|
|
93904
|
+
const mutation = `mutation CreateIssue($input: IssueCreateInput!) {
|
|
93905
|
+
issueCreate(input: $input) {
|
|
93906
|
+
success
|
|
93907
|
+
issue { id identifier }
|
|
93908
|
+
}
|
|
93909
|
+
}`;
|
|
93910
|
+
const variables = {
|
|
93911
|
+
input: {
|
|
93912
|
+
teamId: input.teamId,
|
|
93913
|
+
title: input.title,
|
|
93914
|
+
description: input.description,
|
|
93915
|
+
...input.labelIds && input.labelIds.length > 0 ? { labelIds: input.labelIds } : {}
|
|
93916
|
+
}
|
|
93917
|
+
};
|
|
93918
|
+
const data = await linearRequest(apiKey, mutation, variables);
|
|
93919
|
+
const issue2 = data.issueCreate.issue;
|
|
93920
|
+
if (!issue2)
|
|
93921
|
+
throw new Error("issueCreate returned no issue");
|
|
93922
|
+
return issue2;
|
|
93923
|
+
}
|
|
93924
|
+
async function updateIssueDescription(apiKey, issueId, description) {
|
|
93925
|
+
const mutation = `mutation UpdateDesc($id: String!, $description: String!) {
|
|
93926
|
+
issueUpdate(id: $id, input: { description: $description }) { success }
|
|
93927
|
+
}`;
|
|
93928
|
+
await linearRequest(apiKey, mutation, {
|
|
93929
|
+
id: issueId,
|
|
93930
|
+
description
|
|
93931
|
+
});
|
|
93932
|
+
}
|
|
93933
|
+
async function findOpenIssueByLabel(apiKey, teamKey, labelName) {
|
|
93934
|
+
const query = `query OpenByLabel($team: String!, $label: String!) {
|
|
93935
|
+
issues(
|
|
93936
|
+
filter: {
|
|
93937
|
+
team: { key: { eq: $team } },
|
|
93938
|
+
labels: { some: { name: { eq: $label } } },
|
|
93939
|
+
state: { type: { in: ["unstarted", "started", "backlog", "triage"] } }
|
|
93940
|
+
},
|
|
93941
|
+
first: 1,
|
|
93942
|
+
orderBy: createdAt
|
|
93943
|
+
) {
|
|
93944
|
+
nodes { id identifier description }
|
|
93945
|
+
}
|
|
93946
|
+
}`;
|
|
93947
|
+
const data = await linearRequest(apiKey, query, { team: teamKey, label: labelName });
|
|
93948
|
+
return data.issues.nodes[0] ?? null;
|
|
93949
|
+
}
|
|
93656
93950
|
async function removeLabelFromIssue(apiKey, issueId, labelId) {
|
|
93657
93951
|
const mutation = `mutation RemoveLabel($id: String!, $labelId: String!) {
|
|
93658
93952
|
issueRemoveLabel(id: $id, labelId: $labelId) { success }
|
|
@@ -93664,6 +93958,43 @@ async function removeLabelFromIssue(apiKey, issueId, labelId) {
|
|
|
93664
93958
|
}
|
|
93665
93959
|
var LINEAR_API = "https://api.linear.app/graphql", RALPHY_ATTACHMENT_TITLE_FILTER = "Ralphy", RALPHY_ATTACHMENT_TITLE = "Ralphy", BRANCH_LABEL_PREFIX = "ralph:branch:";
|
|
93666
93960
|
|
|
93961
|
+
// apps/agent/src/sort/compare.ts
|
|
93962
|
+
function chain(...comparators) {
|
|
93963
|
+
return (a, b) => {
|
|
93964
|
+
for (const c of comparators) {
|
|
93965
|
+
const r = c(a, b);
|
|
93966
|
+
if (r !== 0)
|
|
93967
|
+
return r;
|
|
93968
|
+
}
|
|
93969
|
+
return 0;
|
|
93970
|
+
};
|
|
93971
|
+
}
|
|
93972
|
+
|
|
93973
|
+
// apps/agent/src/queue/queue-order.ts
|
|
93974
|
+
function compareQueueEntries(getAutoMerge) {
|
|
93975
|
+
const isAutoMergeBoost = (e) => e.mode === "conflict-fix" && issueMatchesGetIndicator(e.issue, getAutoMerge);
|
|
93976
|
+
return chain((a, b) => Number(!isAutoMergeBoost(a)) - Number(!isAutoMergeBoost(b)), (a, b) => {
|
|
93977
|
+
const pa = a.issue.priority === 0 ? Infinity : a.issue.priority;
|
|
93978
|
+
const pb = b.issue.priority === 0 ? Infinity : b.issue.priority;
|
|
93979
|
+
return pa - pb;
|
|
93980
|
+
}, (a, b) => MODE_RANK[a.mode] - MODE_RANK[b.mode], (a, b) => {
|
|
93981
|
+
const ca = a.issue.createdAt;
|
|
93982
|
+
const cb = b.issue.createdAt;
|
|
93983
|
+
if (ca === cb)
|
|
93984
|
+
return 0;
|
|
93985
|
+
return ca < cb ? -1 : 1;
|
|
93986
|
+
});
|
|
93987
|
+
}
|
|
93988
|
+
var MODE_RANK;
|
|
93989
|
+
var init_queue_order = __esm(() => {
|
|
93990
|
+
MODE_RANK = {
|
|
93991
|
+
resume: 0,
|
|
93992
|
+
"conflict-fix": 1,
|
|
93993
|
+
review: 2,
|
|
93994
|
+
fresh: 3
|
|
93995
|
+
};
|
|
93996
|
+
});
|
|
93997
|
+
|
|
93667
93998
|
// apps/agent/src/agent/coordinator.ts
|
|
93668
93999
|
class AgentCoordinator {
|
|
93669
94000
|
deps;
|
|
@@ -93672,6 +94003,7 @@ class AgentCoordinator {
|
|
|
93672
94003
|
pendingIds = new Set;
|
|
93673
94004
|
queue = [];
|
|
93674
94005
|
stopped = false;
|
|
94006
|
+
paused = null;
|
|
93675
94007
|
conflictNotified = new Set;
|
|
93676
94008
|
ticketsStarted = 0;
|
|
93677
94009
|
constructor(deps, opts) {
|
|
@@ -93690,6 +94022,18 @@ class AgentCoordinator {
|
|
|
93690
94022
|
get ticketsStartedCount() {
|
|
93691
94023
|
return this.ticketsStarted;
|
|
93692
94024
|
}
|
|
94025
|
+
isPaused() {
|
|
94026
|
+
return this.paused !== null;
|
|
94027
|
+
}
|
|
94028
|
+
getPause() {
|
|
94029
|
+
return this.paused;
|
|
94030
|
+
}
|
|
94031
|
+
setPaused(state) {
|
|
94032
|
+
this.paused = state;
|
|
94033
|
+
}
|
|
94034
|
+
clearPaused() {
|
|
94035
|
+
this.paused = null;
|
|
94036
|
+
}
|
|
93693
94037
|
async init() {}
|
|
93694
94038
|
async pollOnce() {
|
|
93695
94039
|
if (this.stopped)
|
|
@@ -93713,11 +94057,23 @@ class AgentCoordinator {
|
|
|
93713
94057
|
return emptyPollResult();
|
|
93714
94058
|
}
|
|
93715
94059
|
if (todo.length + inProgress.length + conflicted.length + review.length + mentions.length > 0) {
|
|
93716
|
-
this.deps.
|
|
94060
|
+
this.deps.onFileLog?.(` poll: ${todo.length} todo, ${inProgress.length} in-progress, ${conflicted.length} conflicted, ${review.length} review, ${mentions.length} mention`);
|
|
93717
94061
|
}
|
|
93718
94062
|
const queuedIds = new Set(this.queue.map((q) => q.issue.id));
|
|
93719
94063
|
const activeIds = new Set(this.workers.map((w) => w.issueId));
|
|
93720
94064
|
const eligible = (id) => !queuedIds.has(id) && !activeIds.has(id) && !this.pendingIds.has(id);
|
|
94065
|
+
if (this.paused) {
|
|
94066
|
+
this.deps.onLog(` paused \u2014 baseline broken (${this.paused.issueIdentifier}); skipping new pickups`, "yellow");
|
|
94067
|
+
const buckets2 = {
|
|
94068
|
+
todo: todo.length,
|
|
94069
|
+
inProgress: inProgress.length,
|
|
94070
|
+
conflicted: conflicted.length,
|
|
94071
|
+
review: review.length,
|
|
94072
|
+
mentions: mentions.length
|
|
94073
|
+
};
|
|
94074
|
+
const found2 = buckets2.todo + buckets2.inProgress + buckets2.conflicted + buckets2.review + buckets2.mentions;
|
|
94075
|
+
return { found: found2, added: 0, buckets: buckets2, prStatus: emptyPrStatus() };
|
|
94076
|
+
}
|
|
93721
94077
|
const maxT = this.opts.maxTickets ?? 0;
|
|
93722
94078
|
const atTicketLimit = () => {
|
|
93723
94079
|
if (maxT === 0)
|
|
@@ -93746,7 +94102,11 @@ class AgentCoordinator {
|
|
|
93746
94102
|
this.queue.push({ issue: issue2, mode: "conflict-fix" });
|
|
93747
94103
|
queuedIds.add(issue2.id);
|
|
93748
94104
|
added += 1;
|
|
93749
|
-
this.
|
|
94105
|
+
if (this.isAutoMergeUnblock(issue2)) {
|
|
94106
|
+
this.deps.onLog(` \u21B3 ${issue2.identifier} queued (auto-merge unblock, prioritized)`, "cyan");
|
|
94107
|
+
} else {
|
|
94108
|
+
this.deps.onLog(` \u21B3 ${issue2.identifier} queued (conflict-fix)`, "gray");
|
|
94109
|
+
}
|
|
93750
94110
|
}
|
|
93751
94111
|
for (const issue2 of review) {
|
|
93752
94112
|
if (atTicketLimit())
|
|
@@ -93781,19 +94141,7 @@ class AgentCoordinator {
|
|
|
93781
94141
|
this.deps.onLog(` \u21B3 ${issue2.identifier} queued (fresh)`, "gray");
|
|
93782
94142
|
}
|
|
93783
94143
|
if (added > 0) {
|
|
93784
|
-
|
|
93785
|
-
resume: 0,
|
|
93786
|
-
"conflict-fix": 1,
|
|
93787
|
-
review: 2,
|
|
93788
|
-
fresh: 3
|
|
93789
|
-
};
|
|
93790
|
-
this.queue.sort((a, b) => {
|
|
93791
|
-
const pa = a.issue.priority === 0 ? Infinity : a.issue.priority;
|
|
93792
|
-
const pb = b.issue.priority === 0 ? Infinity : b.issue.priority;
|
|
93793
|
-
if (pa !== pb)
|
|
93794
|
-
return pa - pb;
|
|
93795
|
-
return modeRank[a.mode] - modeRank[b.mode];
|
|
93796
|
-
});
|
|
94144
|
+
this.queue.sort(compareQueueEntries(this.opts.getAutoMerge));
|
|
93797
94145
|
}
|
|
93798
94146
|
this.spawnNext();
|
|
93799
94147
|
const prStatus = await this.scanDoneForConflicts();
|
|
@@ -93808,6 +94156,9 @@ class AgentCoordinator {
|
|
|
93808
94156
|
const found = buckets.todo + buckets.inProgress + buckets.conflicted + buckets.review + buckets.mentions;
|
|
93809
94157
|
return { found, added, buckets, prStatus };
|
|
93810
94158
|
}
|
|
94159
|
+
isAutoMergeUnblock(issue2) {
|
|
94160
|
+
return issueMatchesGetIndicator(issue2, this.opts.getAutoMerge);
|
|
94161
|
+
}
|
|
93811
94162
|
dependenciesResolved(issue2) {
|
|
93812
94163
|
if (issue2.blockedByIds.length === 0)
|
|
93813
94164
|
return true;
|
|
@@ -93849,6 +94200,13 @@ class AgentCoordinator {
|
|
|
93849
94200
|
} catch (err) {
|
|
93850
94201
|
this.deps.onLog(`! Linear progress comment failed for ${w.issueIdentifier}: ${err.message}`, "red");
|
|
93851
94202
|
}
|
|
94203
|
+
if (this.deps.syncTasks) {
|
|
94204
|
+
try {
|
|
94205
|
+
await this.deps.syncTasks(w, count);
|
|
94206
|
+
} catch (err) {
|
|
94207
|
+
this.deps.onLog(`! sync-tasks (progress) failed for ${w.issueIdentifier}: ${err.message}`, "yellow");
|
|
94208
|
+
}
|
|
94209
|
+
}
|
|
93852
94210
|
}
|
|
93853
94211
|
}
|
|
93854
94212
|
async scanDoneForConflicts() {
|
|
@@ -94006,7 +94364,8 @@ class AgentCoordinator {
|
|
|
94006
94364
|
issue: issue2,
|
|
94007
94365
|
mode,
|
|
94008
94366
|
kill: handle.kill,
|
|
94009
|
-
lastReportedIteration: 0
|
|
94367
|
+
lastReportedIteration: 0,
|
|
94368
|
+
restarting: false
|
|
94010
94369
|
};
|
|
94011
94370
|
this.workers.push(worker);
|
|
94012
94371
|
this.pendingIds.delete(issue2.id);
|
|
@@ -94020,10 +94379,24 @@ class AgentCoordinator {
|
|
|
94020
94379
|
issue_identifier: issue2.identifier
|
|
94021
94380
|
});
|
|
94022
94381
|
this.deps.onWorkersChanged();
|
|
94382
|
+
if (this.deps.syncTasks) {
|
|
94383
|
+
try {
|
|
94384
|
+
await this.deps.syncTasks(worker, 0);
|
|
94385
|
+
} catch (err) {
|
|
94386
|
+
this.deps.onLog(`! sync-tasks (launch) failed for ${issue2.identifier}: ${err.message}`, "yellow");
|
|
94387
|
+
}
|
|
94388
|
+
}
|
|
94023
94389
|
handle.exited.then(async (code) => {
|
|
94024
94390
|
const idx = this.workers.indexOf(worker);
|
|
94025
94391
|
if (idx >= 0)
|
|
94026
94392
|
this.workers.splice(idx, 1);
|
|
94393
|
+
if (worker.restarting) {
|
|
94394
|
+
this.ticketsStarted = Math.max(0, this.ticketsStarted - 1);
|
|
94395
|
+
this.queue.unshift({ issue: issue2, mode: "resume" });
|
|
94396
|
+
this.deps.onWorkersChanged();
|
|
94397
|
+
this.spawnNext();
|
|
94398
|
+
return;
|
|
94399
|
+
}
|
|
94027
94400
|
const ok = code === 0;
|
|
94028
94401
|
this.deps.onLog(`${ok ? "\u2713" : "\u2717"} ${issue2.identifier} \u2192 ${prep.changeName} exited (code ${code})`, ok ? "green" : "red");
|
|
94029
94402
|
capture("agent_worker_exited", {
|
|
@@ -94037,8 +94410,51 @@ class AgentCoordinator {
|
|
|
94037
94410
|
this.spawnNext();
|
|
94038
94411
|
});
|
|
94039
94412
|
}
|
|
94413
|
+
async restartWorker(changeName) {
|
|
94414
|
+
if (this.stopped)
|
|
94415
|
+
return false;
|
|
94416
|
+
const worker = this.workers.find((w) => w.changeName === changeName);
|
|
94417
|
+
if (!worker)
|
|
94418
|
+
return false;
|
|
94419
|
+
if (worker.restarting)
|
|
94420
|
+
return true;
|
|
94421
|
+
worker.restarting = true;
|
|
94422
|
+
capture("agent_worker_restarted", {
|
|
94423
|
+
change_name: changeName,
|
|
94424
|
+
reason: "steering"
|
|
94425
|
+
});
|
|
94426
|
+
try {
|
|
94427
|
+
worker.kill();
|
|
94428
|
+
} catch {}
|
|
94429
|
+
return true;
|
|
94430
|
+
}
|
|
94040
94431
|
async notifyExited(issue2, changeName, code, mode) {
|
|
94041
94432
|
const ok = code === 0;
|
|
94433
|
+
if (this.deps.syncTasks && ok) {
|
|
94434
|
+
const synthetic = {
|
|
94435
|
+
changeName,
|
|
94436
|
+
issueId: issue2.id,
|
|
94437
|
+
issueIdentifier: issue2.identifier,
|
|
94438
|
+
issue: issue2,
|
|
94439
|
+
mode,
|
|
94440
|
+
kill: () => {},
|
|
94441
|
+
lastReportedIteration: 0,
|
|
94442
|
+
restarting: false
|
|
94443
|
+
};
|
|
94444
|
+
try {
|
|
94445
|
+
let iteration = 0;
|
|
94446
|
+
if (this.deps.getIterationCount) {
|
|
94447
|
+
try {
|
|
94448
|
+
iteration = await this.deps.getIterationCount(changeName);
|
|
94449
|
+
} catch {
|
|
94450
|
+
iteration = 0;
|
|
94451
|
+
}
|
|
94452
|
+
}
|
|
94453
|
+
await this.deps.syncTasks(synthetic, iteration);
|
|
94454
|
+
} catch (err) {
|
|
94455
|
+
this.deps.onLog(`! sync-tasks (done) failed for ${issue2.identifier}: ${err.message}`, "yellow");
|
|
94456
|
+
}
|
|
94457
|
+
}
|
|
94042
94458
|
if (this.opts.postComments !== false) {
|
|
94043
94459
|
const body = ok ? mode === "conflict-fix" ? `\u2705 Ralph resolved merge conflicts on this issue. Change: \`${changeName}\`` : `\u2705 Ralph completed work on this issue. Change: \`${changeName}\`` : `\u2717 Ralph exited with code ${code} on this issue. Change: \`${changeName}\`
|
|
94044
94460
|
|
|
@@ -94121,6 +94537,7 @@ var emptyPrStatus = () => ({ mergeable: 0, conflicted: 0, ciFailed: 0 }), emptyP
|
|
|
94121
94537
|
prStatus: emptyPrStatus()
|
|
94122
94538
|
});
|
|
94123
94539
|
var init_coordinator = __esm(() => {
|
|
94540
|
+
init_queue_order();
|
|
94124
94541
|
init_src();
|
|
94125
94542
|
});
|
|
94126
94543
|
|
|
@@ -94149,6 +94566,7 @@ async function scaffoldChangeForIssue(tasksDir, statesDir, issue2, comments = []
|
|
|
94149
94566
|
""
|
|
94150
94567
|
])
|
|
94151
94568
|
] : [];
|
|
94569
|
+
const descriptionBody = issue2.description?.trim() || "_No description provided in Linear._";
|
|
94152
94570
|
const proposal = [
|
|
94153
94571
|
`# ${issue2.identifier}: ${issue2.title}`,
|
|
94154
94572
|
"",
|
|
@@ -94157,9 +94575,17 @@ async function scaffoldChangeForIssue(tasksDir, statesDir, issue2, comments = []
|
|
|
94157
94575
|
issue2.assignee ? `Assignee: ${issue2.assignee.name}` : "",
|
|
94158
94576
|
issue2.labels.length ? `Labels: ${issue2.labels.join(", ")}` : "",
|
|
94159
94577
|
"",
|
|
94578
|
+
"## Why",
|
|
94579
|
+
"",
|
|
94580
|
+
descriptionBody,
|
|
94581
|
+
"",
|
|
94582
|
+
"## What Changes",
|
|
94583
|
+
"",
|
|
94584
|
+
"_Describe the concrete changes this proposal introduces (one bullet per change)._",
|
|
94585
|
+
"",
|
|
94160
94586
|
"## Description",
|
|
94161
94587
|
"",
|
|
94162
|
-
|
|
94588
|
+
descriptionBody,
|
|
94163
94589
|
...commentsBlock,
|
|
94164
94590
|
...appendPrompt.trim() ? ["", "## Additional instructions", "", appendPrompt.trim()] : [],
|
|
94165
94591
|
"",
|
|
@@ -94176,8 +94602,10 @@ async function scaffoldChangeForIssue(tasksDir, statesDir, issue2, comments = []
|
|
|
94176
94602
|
"",
|
|
94177
94603
|
`- [ ] Read the Linear issue at ${issue2.url} and research the codebase to understand the mission and its scope`,
|
|
94178
94604
|
`- [ ] Refine proposal.md with the problem statement, approach, and acceptance criteria derived from the research`,
|
|
94605
|
+
`- [ ] Fill in \`## Why\` and \`## What Changes\` in proposal.md so \`openspec validate\` passes (these sections are required by the validator)`,
|
|
94606
|
+
`- [ ] Add at least one spec delta under \`specs/<capability>/spec.md\` describing the behavior added/modified/removed by this change`,
|
|
94179
94607
|
`- [ ] Fill in design.md with the technical design (files to touch, data flow, edge cases)`,
|
|
94180
|
-
`- [ ] Append an \`## Implementation\` section below with concrete mission-specific tasks derived from the plan
|
|
94608
|
+
`- [ ] Append an \`## Implementation\` section below with concrete mission-specific tasks derived from the plan, including tests and \`bun run lint\` / \`bun run test\`. Every item in the new section MUST start as \`- [ ]\` (unchecked) \u2014 do not pre-check items even if you already did the work during planning. The loop ticks them off in later iterations after each one is verified.`,
|
|
94181
94609
|
""
|
|
94182
94610
|
].join(`
|
|
94183
94611
|
`);
|
|
@@ -94509,6 +94937,33 @@ async function createPullRequest(input, runner) {
|
|
|
94509
94937
|
|
|
94510
94938
|
// apps/agent/src/agent/post-task.ts
|
|
94511
94939
|
import { join as join20 } from "path";
|
|
94940
|
+
function summarizeUncommittedStatus(stdout) {
|
|
94941
|
+
const lines = stdout.split(`
|
|
94942
|
+
`).filter((line) => line.length > 0);
|
|
94943
|
+
const preview = lines.slice(0, 10);
|
|
94944
|
+
return { count: lines.length, preview, truncated: Math.max(0, lines.length - preview.length) };
|
|
94945
|
+
}
|
|
94946
|
+
async function findExistingOpenPrUrl(cmd, cwd2, branch) {
|
|
94947
|
+
try {
|
|
94948
|
+
const result2 = await cmd.run([
|
|
94949
|
+
"gh",
|
|
94950
|
+
"pr",
|
|
94951
|
+
"list",
|
|
94952
|
+
"--head",
|
|
94953
|
+
branch,
|
|
94954
|
+
"--state",
|
|
94955
|
+
"open",
|
|
94956
|
+
"--json",
|
|
94957
|
+
"url",
|
|
94958
|
+
"--jq",
|
|
94959
|
+
".[0].url // empty"
|
|
94960
|
+
], cwd2);
|
|
94961
|
+
const url2 = result2.stdout.trim();
|
|
94962
|
+
return url2 || null;
|
|
94963
|
+
} catch {
|
|
94964
|
+
return null;
|
|
94965
|
+
}
|
|
94966
|
+
}
|
|
94512
94967
|
async function detectRepoAutoMergeAllowed(prUrl, cmd, cwd2, log2) {
|
|
94513
94968
|
const m = /^https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/\d+/.exec(prUrl);
|
|
94514
94969
|
if (!m)
|
|
@@ -94552,7 +95007,7 @@ async function reactivateState(stateFilePath, log2, changeName) {
|
|
|
94552
95007
|
}
|
|
94553
95008
|
async function runWorkerWithFixTask(ctx, heading, body) {
|
|
94554
95009
|
try {
|
|
94555
|
-
await prependFixTask(join20(ctx.changeDir,
|
|
95010
|
+
await prependFixTask(join20(ctx.changeDir, AGENT_TASKS_FILENAME), heading, body);
|
|
94556
95011
|
} catch (err) {
|
|
94557
95012
|
ctx.log(`! could not prepend fix task: ${err.message}`, "red");
|
|
94558
95013
|
return 1;
|
|
@@ -94831,8 +95286,20 @@ async function runPrPhase(input, deps) {
|
|
|
94831
95286
|
};
|
|
94832
95287
|
try {
|
|
94833
95288
|
const status = await cmd.run(["git", "status", "--porcelain"], cwd2);
|
|
94834
|
-
|
|
94835
|
-
|
|
95289
|
+
const summary = summarizeUncommittedStatus(status.stdout);
|
|
95290
|
+
if (summary.count > 0) {
|
|
95291
|
+
const existingPrUrl = branch ? await findExistingOpenPrUrl(cmd, cwd2, branch) : null;
|
|
95292
|
+
const indented = summary.preview.map((line) => ` ${line}`).join(`
|
|
95293
|
+
`);
|
|
95294
|
+
const suffix = summary.truncated ? `
|
|
95295
|
+
... and ${summary.truncated} more` : "";
|
|
95296
|
+
if (existingPrUrl) {
|
|
95297
|
+
log2(` ${changeName}: ${summary.count} uncommitted file(s) after worker \u2014 will retry next iteration:
|
|
95298
|
+
${indented}${suffix}`, "gray");
|
|
95299
|
+
} else {
|
|
95300
|
+
log2(`! ${changeName} has uncommitted changes after worker exit \u2014 the agent should commit everything before finishing. These changes will not be included in the PR:
|
|
95301
|
+
${indented}${suffix}`, "yellow");
|
|
95302
|
+
}
|
|
94836
95303
|
}
|
|
94837
95304
|
} catch (err) {
|
|
94838
95305
|
log2(`! git status check failed for ${changeName}: ${err.message}`, "yellow");
|
|
@@ -94987,14 +95454,370 @@ async function runPostTask(input, deps) {
|
|
|
94987
95454
|
}
|
|
94988
95455
|
var CI_FAILED_EXIT = 70, PR_FAILED_EXIT = 71, repoAutoMergeCache;
|
|
94989
95456
|
var init_post_task = __esm(() => {
|
|
95457
|
+
init_tasks_md();
|
|
94990
95458
|
init_ci();
|
|
94991
95459
|
init_worktree();
|
|
94992
95460
|
repoAutoMergeCache = new Map;
|
|
94993
95461
|
});
|
|
94994
95462
|
|
|
95463
|
+
// apps/agent/src/agent/baseline/runner.ts
|
|
95464
|
+
import { createHash } from "crypto";
|
|
95465
|
+
async function runBaseline(input) {
|
|
95466
|
+
const { cmdRunner, gitRunner, cwd: cwd2, commands, baseBranch, outputCharLimit } = input;
|
|
95467
|
+
if (commands.length === 0) {
|
|
95468
|
+
return { ok: true, failures: [], fingerprint: "" };
|
|
95469
|
+
}
|
|
95470
|
+
try {
|
|
95471
|
+
await gitRunner.run(["fetch", "origin", baseBranch], cwd2);
|
|
95472
|
+
await gitRunner.run(["reset", "--hard", `origin/${baseBranch}`], cwd2);
|
|
95473
|
+
} catch (err) {
|
|
95474
|
+
const e = err;
|
|
95475
|
+
const failure = {
|
|
95476
|
+
command: `git checkout ${baseBranch}`,
|
|
95477
|
+
exitCode: -1,
|
|
95478
|
+
stdout: "",
|
|
95479
|
+
stderr: truncate3(e.stderr ?? e.message, outputCharLimit),
|
|
95480
|
+
fingerprint: fingerprintFor(`git checkout ${baseBranch}`, e.stderr ?? e.message)
|
|
95481
|
+
};
|
|
95482
|
+
return {
|
|
95483
|
+
ok: false,
|
|
95484
|
+
failures: [failure],
|
|
95485
|
+
fingerprint: failure.fingerprint
|
|
95486
|
+
};
|
|
95487
|
+
}
|
|
95488
|
+
const failures = [];
|
|
95489
|
+
for (const command of commands) {
|
|
95490
|
+
const parts = parseCommand(command);
|
|
95491
|
+
let stdout = "";
|
|
95492
|
+
let stderr = "";
|
|
95493
|
+
let exitCode = 0;
|
|
95494
|
+
try {
|
|
95495
|
+
const r = await cmdRunner.run(parts, cwd2);
|
|
95496
|
+
stdout = r.stdout;
|
|
95497
|
+
stderr = r.stderr;
|
|
95498
|
+
} catch (err) {
|
|
95499
|
+
const e = err;
|
|
95500
|
+
stdout = e.stdout ?? "";
|
|
95501
|
+
stderr = e.stderr ?? e.message;
|
|
95502
|
+
exitCode = typeof e.code === "number" ? e.code : 1;
|
|
95503
|
+
}
|
|
95504
|
+
if (exitCode !== 0) {
|
|
95505
|
+
failures.push({
|
|
95506
|
+
command,
|
|
95507
|
+
exitCode,
|
|
95508
|
+
stdout: truncate3(stdout, outputCharLimit),
|
|
95509
|
+
stderr: truncate3(stderr, outputCharLimit),
|
|
95510
|
+
fingerprint: fingerprintFor(command, stderr || stdout)
|
|
95511
|
+
});
|
|
95512
|
+
}
|
|
95513
|
+
}
|
|
95514
|
+
return {
|
|
95515
|
+
ok: failures.length === 0,
|
|
95516
|
+
failures,
|
|
95517
|
+
fingerprint: failures[0]?.fingerprint ?? ""
|
|
95518
|
+
};
|
|
95519
|
+
}
|
|
95520
|
+
function parseCommand(cmd) {
|
|
95521
|
+
return cmd.trim().split(/\s+/);
|
|
95522
|
+
}
|
|
95523
|
+
function truncate3(text, limit) {
|
|
95524
|
+
if (text.length <= limit)
|
|
95525
|
+
return text;
|
|
95526
|
+
return text.slice(0, limit) + `
|
|
95527
|
+
\u2026(truncated ${text.length - limit} chars)`;
|
|
95528
|
+
}
|
|
95529
|
+
function fingerprintFor(command, output) {
|
|
95530
|
+
const firstLine = (output || "").split(`
|
|
95531
|
+
`).find((l) => l.trim().length > 0) ?? "";
|
|
95532
|
+
return createHash("sha1").update(`${command}
|
|
95533
|
+
${firstLine.trim()}`).digest("hex").slice(0, 12);
|
|
95534
|
+
}
|
|
95535
|
+
var init_runner = () => {};
|
|
95536
|
+
|
|
95537
|
+
// apps/agent/src/agent/baseline/gate.ts
|
|
95538
|
+
async function runBaselineGate(deps) {
|
|
95539
|
+
if (!deps.enabled)
|
|
95540
|
+
return;
|
|
95541
|
+
if (deps.commands.length === 0) {
|
|
95542
|
+
deps.onLog(" baseline check skipped \u2014 no commands configured", "gray");
|
|
95543
|
+
return;
|
|
95544
|
+
}
|
|
95545
|
+
const result2 = await runBaseline({
|
|
95546
|
+
cmdRunner: deps.cmdRunner,
|
|
95547
|
+
gitRunner: deps.gitRunner,
|
|
95548
|
+
cwd: deps.cwd,
|
|
95549
|
+
commands: deps.commands,
|
|
95550
|
+
baseBranch: deps.baseBranch,
|
|
95551
|
+
outputCharLimit: deps.outputCharLimit
|
|
95552
|
+
});
|
|
95553
|
+
if (result2.ok) {
|
|
95554
|
+
if (deps.coordinator.isPaused()) {
|
|
95555
|
+
deps.coordinator.clearPaused();
|
|
95556
|
+
deps.onLog("\u2713 baseline recovered \u2014 resuming new pickups", "green");
|
|
95557
|
+
}
|
|
95558
|
+
return;
|
|
95559
|
+
}
|
|
95560
|
+
const firstFailure = result2.failures[0];
|
|
95561
|
+
const description = renderIssueBody(result2, deps.outputCharLimit);
|
|
95562
|
+
const title = `Pre-existing baseline error on ${deps.baseBranch}: \`${firstFailure.command}\``;
|
|
95563
|
+
let issueIdentifier = "BASELINE";
|
|
95564
|
+
let issueId;
|
|
95565
|
+
if (deps.linear) {
|
|
95566
|
+
try {
|
|
95567
|
+
const existing = await deps.linear.findOpen();
|
|
95568
|
+
if (existing) {
|
|
95569
|
+
const existingFp = extractFingerprint(existing.description ?? "");
|
|
95570
|
+
if (existingFp !== result2.fingerprint) {
|
|
95571
|
+
await deps.linear.updateDescription(existing.id, description);
|
|
95572
|
+
deps.onLog(` baseline ticket ${existing.identifier} updated (fingerprint changed)`, "yellow");
|
|
95573
|
+
}
|
|
95574
|
+
issueIdentifier = existing.identifier;
|
|
95575
|
+
issueId = existing.id;
|
|
95576
|
+
} else {
|
|
95577
|
+
const created = await deps.linear.create(title, description);
|
|
95578
|
+
issueIdentifier = created.identifier;
|
|
95579
|
+
issueId = created.id;
|
|
95580
|
+
deps.onLog(` baseline ticket ${created.identifier} created`, "yellow");
|
|
95581
|
+
}
|
|
95582
|
+
} catch (err) {
|
|
95583
|
+
deps.onLog(`! Linear baseline ticket sync failed: ${err.message}`, "red");
|
|
95584
|
+
}
|
|
95585
|
+
} else {
|
|
95586
|
+
deps.onLog("! baseline failed but no Linear client configured \u2014 pausing without ticket", "yellow");
|
|
95587
|
+
}
|
|
95588
|
+
const since = deps.coordinator.isPaused() ? deps.coordinator.getPause()?.since ?? deps.now?.() ?? Date.now() : deps.now?.() ?? Date.now();
|
|
95589
|
+
deps.coordinator.setPaused({
|
|
95590
|
+
issueIdentifier,
|
|
95591
|
+
...issueId !== undefined ? { issueId } : {},
|
|
95592
|
+
command: firstFailure.command,
|
|
95593
|
+
fingerprint: result2.fingerprint,
|
|
95594
|
+
since
|
|
95595
|
+
});
|
|
95596
|
+
}
|
|
95597
|
+
function extractFingerprint(body) {
|
|
95598
|
+
const m = FINGERPRINT_MARKER_RE.exec(body);
|
|
95599
|
+
return m?.[1] ?? null;
|
|
95600
|
+
}
|
|
95601
|
+
function renderIssueBody(result2, outputCharLimit) {
|
|
95602
|
+
const lines = [];
|
|
95603
|
+
lines.push(`<!-- ralphy:baseline:${result2.fingerprint} -->`);
|
|
95604
|
+
lines.push("");
|
|
95605
|
+
lines.push("Ralph detected a failing command on the base branch.");
|
|
95606
|
+
lines.push("");
|
|
95607
|
+
lines.push("New issues will not be picked up by Ralph until this is resolved.");
|
|
95608
|
+
lines.push("Mark this Linear issue as Done to lift the pause.");
|
|
95609
|
+
lines.push("");
|
|
95610
|
+
for (const f2 of result2.failures) {
|
|
95611
|
+
lines.push(`### \`${f2.command}\` \u2014 exit ${f2.exitCode}`);
|
|
95612
|
+
lines.push("");
|
|
95613
|
+
if (f2.stdout.trim()) {
|
|
95614
|
+
lines.push("**stdout:**");
|
|
95615
|
+
lines.push("```");
|
|
95616
|
+
lines.push(truncateForBody(f2.stdout, outputCharLimit));
|
|
95617
|
+
lines.push("```");
|
|
95618
|
+
}
|
|
95619
|
+
if (f2.stderr.trim()) {
|
|
95620
|
+
lines.push("**stderr:**");
|
|
95621
|
+
lines.push("```");
|
|
95622
|
+
lines.push(truncateForBody(f2.stderr, outputCharLimit));
|
|
95623
|
+
lines.push("```");
|
|
95624
|
+
}
|
|
95625
|
+
lines.push("");
|
|
95626
|
+
}
|
|
95627
|
+
return lines.join(`
|
|
95628
|
+
`);
|
|
95629
|
+
}
|
|
95630
|
+
function truncateForBody(text, limit) {
|
|
95631
|
+
if (text.length <= limit)
|
|
95632
|
+
return text;
|
|
95633
|
+
return text.slice(0, limit) + `
|
|
95634
|
+
\u2026(truncated)`;
|
|
95635
|
+
}
|
|
95636
|
+
var FINGERPRINT_MARKER_RE;
|
|
95637
|
+
var init_gate = __esm(() => {
|
|
95638
|
+
init_runner();
|
|
95639
|
+
FINGERPRINT_MARKER_RE = /<!--\s*ralphy:baseline:([a-f0-9]+)\s*-->/i;
|
|
95640
|
+
});
|
|
95641
|
+
|
|
95642
|
+
// apps/agent/src/agent/linear-sync/index.ts
|
|
95643
|
+
function parseTasksMd(md) {
|
|
95644
|
+
const lines = md.split(/\r?\n/);
|
|
95645
|
+
const sections = [];
|
|
95646
|
+
let current = null;
|
|
95647
|
+
let i = 0;
|
|
95648
|
+
while (i < lines.length) {
|
|
95649
|
+
const line = lines[i];
|
|
95650
|
+
const headingMatch = /^##\s+(.+?)\s*$/.exec(line);
|
|
95651
|
+
if (headingMatch) {
|
|
95652
|
+
current = { heading: headingMatch[1], items: [] };
|
|
95653
|
+
sections.push(current);
|
|
95654
|
+
i += 1;
|
|
95655
|
+
continue;
|
|
95656
|
+
}
|
|
95657
|
+
const bulletMatch = /^(\s*)-\s+\[( |x|X)\]\s+(.+?)\s*$/.exec(line);
|
|
95658
|
+
if (bulletMatch && current) {
|
|
95659
|
+
const indent = bulletMatch[1] ?? "";
|
|
95660
|
+
const checked = bulletMatch[2]?.toLowerCase() === "x";
|
|
95661
|
+
const text = bulletMatch[3] ?? "";
|
|
95662
|
+
const bullet = `${indent}- [${checked ? "x" : " "}] ${text}`;
|
|
95663
|
+
i += 1;
|
|
95664
|
+
let j = i;
|
|
95665
|
+
while (j < lines.length && lines[j].trim() === "")
|
|
95666
|
+
j += 1;
|
|
95667
|
+
let code;
|
|
95668
|
+
if (j < lines.length && /^\s*```/.test(lines[j])) {
|
|
95669
|
+
const fenceOpen = lines[j];
|
|
95670
|
+
const fenceMatch = /^(\s*)```/.exec(fenceOpen);
|
|
95671
|
+
const fenceIndent = fenceMatch?.[1] ?? "";
|
|
95672
|
+
const buf = [];
|
|
95673
|
+
j += 1;
|
|
95674
|
+
while (j < lines.length) {
|
|
95675
|
+
if (new RegExp(`^${fenceIndent}\`\`\`\\s*$`).test(lines[j])) {
|
|
95676
|
+
j += 1;
|
|
95677
|
+
break;
|
|
95678
|
+
}
|
|
95679
|
+
buf.push(lines[j]);
|
|
95680
|
+
j += 1;
|
|
95681
|
+
}
|
|
95682
|
+
code = buf.join(`
|
|
95683
|
+
`);
|
|
95684
|
+
i = j;
|
|
95685
|
+
}
|
|
95686
|
+
current.items.push(code !== undefined ? { bullet, code } : { bullet });
|
|
95687
|
+
continue;
|
|
95688
|
+
}
|
|
95689
|
+
i += 1;
|
|
95690
|
+
}
|
|
95691
|
+
return sections;
|
|
95692
|
+
}
|
|
95693
|
+
function truncate4(s, max2) {
|
|
95694
|
+
if (s.length <= max2)
|
|
95695
|
+
return s;
|
|
95696
|
+
return `${s.slice(0, max2)}
|
|
95697
|
+
\u2026(truncated)`;
|
|
95698
|
+
}
|
|
95699
|
+
function renderTasksBlock(tasksMd, meta3) {
|
|
95700
|
+
const sections = parseTasksMd(tasksMd);
|
|
95701
|
+
const out = [];
|
|
95702
|
+
out.push(RALPHY_TASKS_START);
|
|
95703
|
+
out.push("### Ralph progress");
|
|
95704
|
+
out.push("");
|
|
95705
|
+
for (const section of sections) {
|
|
95706
|
+
if (section.items.length === 0)
|
|
95707
|
+
continue;
|
|
95708
|
+
out.push(`**${section.heading}**`);
|
|
95709
|
+
out.push("");
|
|
95710
|
+
for (const item of section.items) {
|
|
95711
|
+
out.push(item.bullet);
|
|
95712
|
+
if (item.code !== undefined) {
|
|
95713
|
+
const inner = truncate4(item.code, MAX_CODE_BLOCK_BYTES);
|
|
95714
|
+
out.push(` <details><summary>output</summary><pre>${inner}</pre></details>`);
|
|
95715
|
+
}
|
|
95716
|
+
}
|
|
95717
|
+
out.push("");
|
|
95718
|
+
}
|
|
95719
|
+
out.push(`<sub>\`${meta3.changeName}\` \xB7 iteration ${meta3.iteration}</sub>`);
|
|
95720
|
+
out.push(RALPHY_TASKS_END);
|
|
95721
|
+
return out.join(`
|
|
95722
|
+
`);
|
|
95723
|
+
}
|
|
95724
|
+
function applyTasksBlock(existingDescription, block) {
|
|
95725
|
+
const existing = existingDescription ?? "";
|
|
95726
|
+
const startIdx = existing.indexOf(RALPHY_TASKS_START);
|
|
95727
|
+
const endIdx = startIdx >= 0 ? existing.indexOf(RALPHY_TASKS_END, startIdx + RALPHY_TASKS_START.length) : -1;
|
|
95728
|
+
if (startIdx >= 0 && endIdx >= 0) {
|
|
95729
|
+
const before2 = existing.slice(0, startIdx);
|
|
95730
|
+
const after2 = existing.slice(endIdx + RALPHY_TASKS_END.length);
|
|
95731
|
+
return `${before2}${block}${after2}`;
|
|
95732
|
+
}
|
|
95733
|
+
if (existing.length === 0)
|
|
95734
|
+
return block;
|
|
95735
|
+
const trimmed = existing.replace(/\s+$/, "");
|
|
95736
|
+
return `${trimmed}
|
|
95737
|
+
|
|
95738
|
+
${block}`;
|
|
95739
|
+
}
|
|
95740
|
+
async function syncTasksToLinearDescription(deps) {
|
|
95741
|
+
const file2 = Bun.file(deps.tasksPath);
|
|
95742
|
+
if (!await file2.exists()) {
|
|
95743
|
+
deps.log(` sync-tasks: tasks.md missing at ${deps.tasksPath}, skipping`, "gray");
|
|
95744
|
+
return null;
|
|
95745
|
+
}
|
|
95746
|
+
let tasksMd;
|
|
95747
|
+
try {
|
|
95748
|
+
tasksMd = await file2.text();
|
|
95749
|
+
} catch (err) {
|
|
95750
|
+
deps.log(`! sync-tasks: read failed for ${deps.tasksPath}: ${err.message}`, "yellow");
|
|
95751
|
+
return null;
|
|
95752
|
+
}
|
|
95753
|
+
const block = renderTasksBlock(tasksMd, {
|
|
95754
|
+
changeName: deps.changeName,
|
|
95755
|
+
iteration: deps.iteration
|
|
95756
|
+
});
|
|
95757
|
+
if (block.length > MAX_BLOCK_BYTES) {
|
|
95758
|
+
deps.log(`! sync-tasks: rendered block exceeds ${MAX_BLOCK_BYTES} bytes (${block.length}), skipping update`, "yellow");
|
|
95759
|
+
return null;
|
|
95760
|
+
}
|
|
95761
|
+
const next = applyTasksBlock(deps.currentDescription, block);
|
|
95762
|
+
if (next === (deps.currentDescription ?? ""))
|
|
95763
|
+
return null;
|
|
95764
|
+
try {
|
|
95765
|
+
await deps.updateIssueDescription(deps.apiKey, deps.issueId, next);
|
|
95766
|
+
deps.log(` sync-tasks: updated Linear description for ${deps.changeName}`, "gray");
|
|
95767
|
+
return next;
|
|
95768
|
+
} catch (err) {
|
|
95769
|
+
deps.log(`! sync-tasks: updateIssueDescription failed: ${err.message}`, "yellow");
|
|
95770
|
+
return null;
|
|
95771
|
+
}
|
|
95772
|
+
}
|
|
95773
|
+
var RALPHY_TASKS_START = "<!-- ralphy:tasks:start -->", RALPHY_TASKS_END = "<!-- ralphy:tasks:end -->", MAX_BLOCK_BYTES, MAX_CODE_BLOCK_BYTES;
|
|
95774
|
+
var init_linear_sync = __esm(() => {
|
|
95775
|
+
MAX_BLOCK_BYTES = 60 * 1024;
|
|
95776
|
+
MAX_CODE_BLOCK_BYTES = 2 * 1024;
|
|
95777
|
+
});
|
|
95778
|
+
|
|
94995
95779
|
// apps/agent/src/agent/wire.ts
|
|
94996
95780
|
import { join as join21 } from "path";
|
|
94997
95781
|
import { mkdir as mkdir6 } from "fs/promises";
|
|
95782
|
+
async function pickOpenPrUrlFromAttachments(urls, issueIdent, cmd, cwd2, onLog) {
|
|
95783
|
+
const candidates = urls.filter((url2) => GITHUB_PR_URL_RE.test(url2));
|
|
95784
|
+
let sawNonOpenPr = false;
|
|
95785
|
+
for (const url2 of candidates) {
|
|
95786
|
+
try {
|
|
95787
|
+
const res = await cmd.run(["gh", "pr", "view", url2, "--json", "state"], cwd2);
|
|
95788
|
+
const parsed = JSON.parse(res.stdout.trim());
|
|
95789
|
+
if (parsed.state === "OPEN")
|
|
95790
|
+
return { url: url2, sawNonOpenPr };
|
|
95791
|
+
if (parsed.state === "MERGED" || parsed.state === "CLOSED")
|
|
95792
|
+
sawNonOpenPr = true;
|
|
95793
|
+
} catch (err) {
|
|
95794
|
+
onLog(`! gh pr view ${url2} failed for ${issueIdent}: ${err.message}`, "yellow");
|
|
95795
|
+
}
|
|
95796
|
+
}
|
|
95797
|
+
return { url: null, sawNonOpenPr };
|
|
95798
|
+
}
|
|
95799
|
+
function githubReactionSlug(emoji3) {
|
|
95800
|
+
switch (emoji3) {
|
|
95801
|
+
case "\uD83D\uDC40":
|
|
95802
|
+
return "eyes";
|
|
95803
|
+
case "\uD83D\uDC4D":
|
|
95804
|
+
return "+1";
|
|
95805
|
+
case "\uD83D\uDC4E":
|
|
95806
|
+
return "-1";
|
|
95807
|
+
case "\u2764\uFE0F":
|
|
95808
|
+
return "heart";
|
|
95809
|
+
case "\uD83C\uDF89":
|
|
95810
|
+
return "hooray";
|
|
95811
|
+
case "\uD83D\uDE80":
|
|
95812
|
+
return "rocket";
|
|
95813
|
+
case "\uD83D\uDE04":
|
|
95814
|
+
return "laugh";
|
|
95815
|
+
case "\uD83D\uDE15":
|
|
95816
|
+
return "confused";
|
|
95817
|
+
default:
|
|
95818
|
+
return emoji3;
|
|
95819
|
+
}
|
|
95820
|
+
}
|
|
94998
95821
|
function traceCmdRunner(base2, onStart, onEnd) {
|
|
94999
95822
|
return {
|
|
95000
95823
|
run: async (cmd, cwd2) => {
|
|
@@ -95111,6 +95934,7 @@ function buildAgentCoordinator(input) {
|
|
|
95111
95934
|
tasksDir,
|
|
95112
95935
|
apiKey,
|
|
95113
95936
|
onLog,
|
|
95937
|
+
onFileLog,
|
|
95114
95938
|
onWorkersChanged,
|
|
95115
95939
|
onWorkerStarted,
|
|
95116
95940
|
onWorkerExited,
|
|
@@ -95275,21 +96099,23 @@ function buildAgentCoordinator(input) {
|
|
|
95275
96099
|
return { workerCwd, scaffoldTasksDir, scaffoldStatesDir, branch };
|
|
95276
96100
|
const probeName = issue2.identifier.toLowerCase();
|
|
95277
96101
|
const baseBranch = baseBranchFromLabels(issue2.labels) ?? cfg.prBaseBranch;
|
|
96102
|
+
let wt;
|
|
95278
96103
|
try {
|
|
95279
|
-
|
|
95280
|
-
workerCwd = wt.cwd;
|
|
95281
|
-
branch = wt.branch;
|
|
95282
|
-
const wtLayout = projectLayout(wt.cwd);
|
|
95283
|
-
scaffoldTasksDir = wtLayout.tasksDir;
|
|
95284
|
-
scaffoldStatesDir = wtLayout.statesDir;
|
|
95285
|
-
onLog(` ${issue2.identifier} worktree: ${wt.cwd} (${wt.branch})`, "gray");
|
|
95286
|
-
try {
|
|
95287
|
-
await seedWorktreeMcpConfig(projectRoot, wt.cwd);
|
|
95288
|
-
} catch (err) {
|
|
95289
|
-
onLog(`! seeding .mcp.json failed for ${issue2.identifier}: ${err.message}`, "yellow");
|
|
95290
|
-
}
|
|
96104
|
+
wt = await createWorktree(projectRoot, probeName, baseBranch, gitRunner);
|
|
95291
96105
|
} catch (err) {
|
|
95292
|
-
onLog(`! worktree create failed for ${issue2.identifier}: ${err.message} \u2014
|
|
96106
|
+
onLog(`! worktree create failed for ${issue2.identifier}: ${err.message} \u2014 skipping (useWorktree is required)`, "red");
|
|
96107
|
+
throw err;
|
|
96108
|
+
}
|
|
96109
|
+
workerCwd = wt.cwd;
|
|
96110
|
+
branch = wt.branch;
|
|
96111
|
+
const wtLayout = projectLayout(wt.cwd);
|
|
96112
|
+
scaffoldTasksDir = wtLayout.tasksDir;
|
|
96113
|
+
scaffoldStatesDir = wtLayout.statesDir;
|
|
96114
|
+
onLog(` ${issue2.identifier} worktree: ${wt.cwd} (${wt.branch})`, "gray");
|
|
96115
|
+
try {
|
|
96116
|
+
await seedWorktreeMcpConfig(projectRoot, wt.cwd);
|
|
96117
|
+
} catch (err) {
|
|
96118
|
+
onLog(`! seeding .mcp.json failed for ${issue2.identifier}: ${err.message}`, "yellow");
|
|
95293
96119
|
}
|
|
95294
96120
|
return { workerCwd, scaffoldTasksDir, scaffoldStatesDir, branch };
|
|
95295
96121
|
}
|
|
@@ -95312,7 +96138,8 @@ function buildAgentCoordinator(input) {
|
|
|
95312
96138
|
identifier: issue2.identifier,
|
|
95313
96139
|
title: issue2.title,
|
|
95314
96140
|
description: issue2.description ?? "",
|
|
95315
|
-
url: issue2.url
|
|
96141
|
+
url: issue2.url,
|
|
96142
|
+
labels: issue2.labels
|
|
95316
96143
|
},
|
|
95317
96144
|
attempt: 1,
|
|
95318
96145
|
last_error: ""
|
|
@@ -95337,7 +96164,7 @@ function buildAgentCoordinator(input) {
|
|
|
95337
96164
|
branchByChange.set(changeName, branch);
|
|
95338
96165
|
if (mode === "review") {
|
|
95339
96166
|
const wtLayout = projectLayout(workerCwd);
|
|
95340
|
-
const tasksFile = join21(wtLayout.changeDir(changeName),
|
|
96167
|
+
const tasksFile = join21(wtLayout.changeDir(changeName), AGENT_TASKS_FILENAME);
|
|
95341
96168
|
let body;
|
|
95342
96169
|
let heading;
|
|
95343
96170
|
if (trigger) {
|
|
@@ -95362,7 +96189,7 @@ function buildAgentCoordinator(input) {
|
|
|
95362
96189
|
await reactivateState2(wtLayout.stateFile(changeName), changeName);
|
|
95363
96190
|
} else if (mode === "conflict-fix") {
|
|
95364
96191
|
const wtLayout = projectLayout(workerCwd);
|
|
95365
|
-
const tasksFile = join21(wtLayout.changeDir(changeName),
|
|
96192
|
+
const tasksFile = join21(wtLayout.changeDir(changeName), AGENT_TASKS_FILENAME);
|
|
95366
96193
|
const prUrl = prByChange.get(changeName);
|
|
95367
96194
|
const body = [
|
|
95368
96195
|
`The PR for this change has merge conflicts with \`${cfg.prBaseBranch}\`.`,
|
|
@@ -95501,6 +96328,11 @@ PR: ${prUrl}` : ""
|
|
|
95501
96328
|
function spawnWorker(changeName) {
|
|
95502
96329
|
const cwd2 = cwdByChange.get(changeName) ?? projectRoot;
|
|
95503
96330
|
const injected = input.runners?.spawnWorker;
|
|
96331
|
+
const missionTasksPath = join21(projectLayout(cwd2).changeDir(changeName), MISSION_TASKS_FILENAME);
|
|
96332
|
+
const prevTasksPromise = (async () => {
|
|
96333
|
+
const f2 = Bun.file(missionTasksPath);
|
|
96334
|
+
return await f2.exists() ? await f2.text() : "";
|
|
96335
|
+
})();
|
|
95504
96336
|
let logFilePath;
|
|
95505
96337
|
let handle;
|
|
95506
96338
|
if (injected) {
|
|
@@ -95526,6 +96358,21 @@ PR: ${prUrl}` : ""
|
|
|
95526
96358
|
const wantAutoMerge = issueForChange ? issueMatchesGetIndicator(issueForChange, indicators.getAutoMerge) : false;
|
|
95527
96359
|
const wrapped = handle.exited.then(async (code) => {
|
|
95528
96360
|
const workerLayout = projectLayout(cwd2);
|
|
96361
|
+
try {
|
|
96362
|
+
const prevTasks = await prevTasksPromise;
|
|
96363
|
+
const nextFile = Bun.file(missionTasksPath);
|
|
96364
|
+
if (await nextFile.exists()) {
|
|
96365
|
+
const nextTasks = await nextFile.text();
|
|
96366
|
+
const report = normalizeNewlyAppendedSectionWithReport(prevTasks, nextTasks);
|
|
96367
|
+
if (report.text !== nextTasks) {
|
|
96368
|
+
await Bun.write(missionTasksPath, report.text);
|
|
96369
|
+
const sections = report.headings.map((h) => `## ${h}`).join(", ");
|
|
96370
|
+
onLog(`! normalized ${report.count} pre-checked item(s) in newly added section(s) ${sections}`, "yellow");
|
|
96371
|
+
}
|
|
96372
|
+
}
|
|
96373
|
+
} catch (err) {
|
|
96374
|
+
onLog(`! tasks.md normalization failed: ${err.message}`, "yellow");
|
|
96375
|
+
}
|
|
95529
96376
|
const effectiveCode = await runPostTask({
|
|
95530
96377
|
changeName,
|
|
95531
96378
|
cwd: cwd2,
|
|
@@ -95681,9 +96528,13 @@ PR: ${prUrl}` : ""
|
|
|
95681
96528
|
if (byBranch)
|
|
95682
96529
|
return byBranch;
|
|
95683
96530
|
const fromLinear = await discoverPrUrlFromLinear(issue2);
|
|
95684
|
-
if (fromLinear) {
|
|
95685
|
-
onLog(` ${issue2.identifier}: PR discovered via Linear attachment (${fromLinear})`, "gray");
|
|
95686
|
-
return fromLinear;
|
|
96531
|
+
if (fromLinear.url) {
|
|
96532
|
+
onLog(` ${issue2.identifier}: PR discovered via Linear attachment (${fromLinear.url})`, "gray");
|
|
96533
|
+
return fromLinear.url;
|
|
96534
|
+
}
|
|
96535
|
+
if (fromLinear.sawNonOpenPr) {
|
|
96536
|
+
markPrUnavailable(changeName);
|
|
96537
|
+
return null;
|
|
95687
96538
|
}
|
|
95688
96539
|
onLog(` ${issue2.identifier}: no open PR found on head=${branch} or Linear attachments; conflict scan skipped for ${PR_UNAVAILABLE_TTL_MS / 60000}m`, "gray");
|
|
95689
96540
|
markPrUnavailable(changeName);
|
|
@@ -95729,14 +96580,14 @@ PR: ${prUrl}` : ""
|
|
|
95729
96580
|
return null;
|
|
95730
96581
|
}
|
|
95731
96582
|
async function discoverPrUrlFromLinear(issue2) {
|
|
96583
|
+
let attachments;
|
|
95732
96584
|
try {
|
|
95733
|
-
|
|
95734
|
-
const match = attachments.find((a) => /^https:\/\/github\.com\/[^/]+\/[^/]+\/pull\/\d+/.test(a.url));
|
|
95735
|
-
return match?.url ?? null;
|
|
96585
|
+
attachments = await fetchIssueAttachments(apiKey, issue2.id);
|
|
95736
96586
|
} catch (err) {
|
|
95737
96587
|
onLog(`! Linear attachments fetch failed for ${issue2.identifier}: ${err.message}`, "yellow");
|
|
95738
|
-
return null;
|
|
96588
|
+
return { url: null, sawNonOpenPr: false };
|
|
95739
96589
|
}
|
|
96590
|
+
return pickOpenPrUrlFromAttachments(attachments.map((a) => a.url), issue2.identifier, cmdRunner, projectRoot, onLog);
|
|
95740
96591
|
}
|
|
95741
96592
|
async function fetchDoneCandidates() {
|
|
95742
96593
|
if (!indicators.setDone)
|
|
@@ -95755,9 +96606,9 @@ PR: ${prUrl}` : ""
|
|
|
95755
96606
|
const handle = cfg.linear.mentionHandle;
|
|
95756
96607
|
let candidates = [];
|
|
95757
96608
|
try {
|
|
95758
|
-
candidates = await
|
|
96609
|
+
candidates = await fetchMentionScanIssues(apiKey, { team, assignee });
|
|
95759
96610
|
} catch (err) {
|
|
95760
|
-
onLog(`! mention scan:
|
|
96611
|
+
onLog(`! mention scan: fetchMentionScanIssues failed: ${err.message}`, "yellow");
|
|
95761
96612
|
return [];
|
|
95762
96613
|
}
|
|
95763
96614
|
const out = [];
|
|
@@ -95789,6 +96640,11 @@ PR: ${prUrl}` : ""
|
|
|
95789
96640
|
url: issue2.url
|
|
95790
96641
|
}
|
|
95791
96642
|
});
|
|
96643
|
+
try {
|
|
96644
|
+
await addReactionToComment(apiKey, c.id, "\uD83D\uDC40");
|
|
96645
|
+
} catch (err) {
|
|
96646
|
+
onLog(`! mention scan: Linear reaction failed for ${issue2.identifier}: ${err.message}`, "yellow");
|
|
96647
|
+
}
|
|
95792
96648
|
queued.add(issue2.id);
|
|
95793
96649
|
break;
|
|
95794
96650
|
}
|
|
@@ -95800,6 +96656,7 @@ PR: ${prUrl}` : ""
|
|
|
95800
96656
|
continue;
|
|
95801
96657
|
if (wantMention) {
|
|
95802
96658
|
const ghComments = await fetchPrIssueComments(prUrl);
|
|
96659
|
+
const prMatch = /^https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/\d+/.exec(prUrl);
|
|
95803
96660
|
for (const c of ghComments) {
|
|
95804
96661
|
if (!containsHandle(c.body, handle))
|
|
95805
96662
|
continue;
|
|
@@ -95815,6 +96672,14 @@ PR: ${prUrl}` : ""
|
|
|
95815
96672
|
url: c.url
|
|
95816
96673
|
}
|
|
95817
96674
|
});
|
|
96675
|
+
if (prMatch) {
|
|
96676
|
+
const [, owner, repo] = prMatch;
|
|
96677
|
+
try {
|
|
96678
|
+
await addGithubReactionToComment({ owner, repo, kind: "issue" }, c.id, "\uD83D\uDC40");
|
|
96679
|
+
} catch (err) {
|
|
96680
|
+
onLog(`! mention scan: GitHub reaction failed for ${prUrl}: ${err.message}`, "yellow");
|
|
96681
|
+
}
|
|
96682
|
+
}
|
|
95818
96683
|
queued.add(issue2.id);
|
|
95819
96684
|
break;
|
|
95820
96685
|
}
|
|
@@ -95982,6 +96847,11 @@ PR: ${prUrl}` : ""
|
|
|
95982
96847
|
prByChange.set(changeName, found);
|
|
95983
96848
|
return found;
|
|
95984
96849
|
}
|
|
96850
|
+
async function addGithubReactionToComment(source, commentId, emoji3) {
|
|
96851
|
+
const content = githubReactionSlug(emoji3);
|
|
96852
|
+
const path = source.kind === "issue" ? `repos/${source.owner}/${source.repo}/issues/comments/${commentId}/reactions` : `repos/${source.owner}/${source.repo}/pulls/comments/${commentId}/reactions`;
|
|
96853
|
+
await cmdRunner.run(["gh", "api", "-X", "POST", path, "-f", `content=${content}`], projectRoot);
|
|
96854
|
+
}
|
|
95985
96855
|
async function fetchPrIssueComments(prUrl) {
|
|
95986
96856
|
const m = /^https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)/.exec(prUrl);
|
|
95987
96857
|
if (!m)
|
|
@@ -95993,7 +96863,7 @@ PR: ${prUrl}` : ""
|
|
|
95993
96863
|
"api",
|
|
95994
96864
|
`repos/${owner}/${repo}/issues/${num}/comments`,
|
|
95995
96865
|
"--jq",
|
|
95996
|
-
"[.[] | {body: .body, createdAt: .created_at, author: .user.login, url: .html_url}]"
|
|
96866
|
+
"[.[] | {id: .id, body: .body, createdAt: .created_at, author: .user.login, url: .html_url}]"
|
|
95997
96867
|
], projectRoot);
|
|
95998
96868
|
const parsed = JSON.parse(res.stdout || "[]");
|
|
95999
96869
|
return parsed;
|
|
@@ -96020,6 +96890,7 @@ PR: ${prUrl}` : ""
|
|
|
96020
96890
|
},
|
|
96021
96891
|
checkPrStatus,
|
|
96022
96892
|
onLog,
|
|
96893
|
+
...onFileLog ? { onFileLog } : {},
|
|
96023
96894
|
onWorkersChanged,
|
|
96024
96895
|
getIterationCount: async (changeName) => {
|
|
96025
96896
|
const root = cwdByChange.get(changeName) ?? projectRoot;
|
|
@@ -96028,7 +96899,29 @@ PR: ${prUrl}` : ""
|
|
|
96028
96899
|
return 0;
|
|
96029
96900
|
const json2 = await file2.json();
|
|
96030
96901
|
return json2.iteration ?? 0;
|
|
96031
|
-
}
|
|
96902
|
+
},
|
|
96903
|
+
...cfg.linear.syncTasksToDescription && apiKey ? {
|
|
96904
|
+
syncTasks: async (worker, iteration) => {
|
|
96905
|
+
const root = cwdByChange.get(worker.changeName) ?? projectRoot;
|
|
96906
|
+
const tasksPath = join21(projectLayout(root).changeDir(worker.changeName), "tasks.md");
|
|
96907
|
+
const cachedIssue = issueByChange.get(worker.changeName) ?? worker.issue;
|
|
96908
|
+
const next = await syncTasksToLinearDescription({
|
|
96909
|
+
apiKey,
|
|
96910
|
+
issueId: worker.issueId,
|
|
96911
|
+
currentDescription: cachedIssue.description,
|
|
96912
|
+
tasksPath,
|
|
96913
|
+
changeName: worker.changeName,
|
|
96914
|
+
iteration,
|
|
96915
|
+
log: onLog,
|
|
96916
|
+
updateIssueDescription
|
|
96917
|
+
});
|
|
96918
|
+
if (next !== null) {
|
|
96919
|
+
const updated = { ...cachedIssue, description: next };
|
|
96920
|
+
issueByChange.set(worker.changeName, updated);
|
|
96921
|
+
worker.issue = updated;
|
|
96922
|
+
}
|
|
96923
|
+
}
|
|
96924
|
+
} : {}
|
|
96032
96925
|
}, {
|
|
96033
96926
|
concurrency,
|
|
96034
96927
|
...indicators.setInProgress !== undefined ? { setInProgress: indicators.setInProgress } : {},
|
|
@@ -96037,17 +96930,66 @@ PR: ${prUrl}` : ""
|
|
|
96037
96930
|
...indicators.setConflicted !== undefined ? { setConflicted: indicators.setConflicted } : {},
|
|
96038
96931
|
...indicators.clearConflicted !== undefined ? { clearConflicted: indicators.clearConflicted } : {},
|
|
96039
96932
|
...indicators.clearReview !== undefined ? { clearReview: indicators.clearReview } : {},
|
|
96933
|
+
...indicators.getAutoMerge !== undefined ? { getAutoMerge: indicators.getAutoMerge } : {},
|
|
96040
96934
|
postComments: cfg.linear.postComments,
|
|
96041
96935
|
commentEveryIterations: cfg.linear.updateEveryIterations,
|
|
96042
96936
|
...args.maxTickets > 0 ? { maxTickets: args.maxTickets } : {}
|
|
96043
96937
|
});
|
|
96044
96938
|
const filterDesc = describeIndicators(indicators, team, assignee);
|
|
96939
|
+
const baselineCfg = cfg.preExistingErrorCheck;
|
|
96940
|
+
const baselineCommands = resolveBaselineCommands(cfg);
|
|
96941
|
+
const baselineEnabled = (args.preExistingErrorCheck ?? baselineCfg.enabled) === true;
|
|
96942
|
+
const baselineTeam = team;
|
|
96943
|
+
const runBaselineGateOnce = async () => {
|
|
96944
|
+
if (!baselineEnabled)
|
|
96945
|
+
return;
|
|
96946
|
+
await runBaselineGate({
|
|
96947
|
+
enabled: true,
|
|
96948
|
+
commands: baselineCommands,
|
|
96949
|
+
baseBranch: baselineCfg.baseBranch,
|
|
96950
|
+
outputCharLimit: baselineCfg.outputCharLimit,
|
|
96951
|
+
cwd: projectRoot,
|
|
96952
|
+
cmdRunner,
|
|
96953
|
+
gitRunner,
|
|
96954
|
+
coordinator: coord,
|
|
96955
|
+
...baselineTeam && apiKey ? {
|
|
96956
|
+
linear: {
|
|
96957
|
+
findOpen: () => findOpenIssueByLabel(apiKey, baselineTeam, baselineCfg.label),
|
|
96958
|
+
create: async (title, description) => {
|
|
96959
|
+
const teamId = await fetchTeamIdByKey(apiKey, baselineTeam);
|
|
96960
|
+
if (!teamId)
|
|
96961
|
+
throw new Error("Linear team not found");
|
|
96962
|
+
let labelIds;
|
|
96963
|
+
try {
|
|
96964
|
+
const labelId = await resolveLabelIdForTeam(baselineTeam, baselineCfg.label);
|
|
96965
|
+
if (labelId)
|
|
96966
|
+
labelIds = [labelId];
|
|
96967
|
+
} catch {}
|
|
96968
|
+
return createIssue(apiKey, {
|
|
96969
|
+
teamId,
|
|
96970
|
+
title,
|
|
96971
|
+
description,
|
|
96972
|
+
...labelIds ? { labelIds } : {}
|
|
96973
|
+
});
|
|
96974
|
+
},
|
|
96975
|
+
updateDescription: (id, description) => updateIssueDescription(apiKey, id, description)
|
|
96976
|
+
}
|
|
96977
|
+
} : {},
|
|
96978
|
+
onLog
|
|
96979
|
+
});
|
|
96980
|
+
};
|
|
96981
|
+
async function resolveLabelIdForTeam(teamKey, labelName) {
|
|
96982
|
+
const fakeIssue = { identifier: `${teamKey}-0` };
|
|
96983
|
+
return resolveLabelId(fakeIssue, labelName);
|
|
96984
|
+
}
|
|
96045
96985
|
return {
|
|
96046
96986
|
coord,
|
|
96047
96987
|
filterDesc,
|
|
96048
96988
|
concurrency,
|
|
96049
96989
|
pollInterval,
|
|
96050
|
-
getWorkerCwd: (changeName) => cwdByChange.get(changeName)
|
|
96990
|
+
getWorkerCwd: (changeName) => cwdByChange.get(changeName),
|
|
96991
|
+
syncTasksEnabled: Boolean(cfg.linear.syncTasksToDescription && apiKey),
|
|
96992
|
+
runBaselineGate: runBaselineGateOnce
|
|
96051
96993
|
};
|
|
96052
96994
|
}
|
|
96053
96995
|
function describeIndicators(indicators, team, assignee) {
|
|
@@ -96068,10 +97010,11 @@ function describeIndicators(indicators, team, assignee) {
|
|
|
96068
97010
|
}
|
|
96069
97011
|
return parts.join(", ");
|
|
96070
97012
|
}
|
|
96071
|
-
var bunGitRunner, bunCmdRunner;
|
|
97013
|
+
var GITHUB_PR_URL_RE, bunGitRunner, bunCmdRunner;
|
|
96072
97014
|
var init_wire = __esm(() => {
|
|
96073
97015
|
init_log();
|
|
96074
97016
|
init_layout();
|
|
97017
|
+
init_tasks_md();
|
|
96075
97018
|
init_workflow();
|
|
96076
97019
|
init_types2();
|
|
96077
97020
|
init_coordinator();
|
|
@@ -96079,6 +97022,10 @@ var init_wire = __esm(() => {
|
|
|
96079
97022
|
init_worktree();
|
|
96080
97023
|
init_ci();
|
|
96081
97024
|
init_post_task();
|
|
97025
|
+
init_gate();
|
|
97026
|
+
init_workflow();
|
|
97027
|
+
init_linear_sync();
|
|
97028
|
+
GITHUB_PR_URL_RE = /^https:\/\/github\.com\/[^/]+\/[^/]+\/pull\/\d+/;
|
|
96082
97029
|
bunGitRunner = {
|
|
96083
97030
|
run: async (args, cwd2) => {
|
|
96084
97031
|
const proc = Bun.spawn({ cmd: ["git", ...args], cwd: cwd2, stdout: "pipe", stderr: "pipe" });
|
|
@@ -96155,15 +97102,286 @@ function deriveOpenSpecPhase(inputs) {
|
|
|
96155
97102
|
return "implement";
|
|
96156
97103
|
return "tasks";
|
|
96157
97104
|
}
|
|
97105
|
+
function shouldShowPhasePipeline(phase) {
|
|
97106
|
+
return phase === "proposal" || phase === "design" || phase === "tasks";
|
|
97107
|
+
}
|
|
97108
|
+
function shouldShowSubtasksPanel(phase, showPendingTasks, hasSubtasks) {
|
|
97109
|
+
if (!showPendingTasks || !hasSubtasks)
|
|
97110
|
+
return false;
|
|
97111
|
+
return phase == null || phase === "implement" || phase === "done";
|
|
97112
|
+
}
|
|
97113
|
+
function shouldShowProgressBar(phase, showPendingTasks, hasProgress) {
|
|
97114
|
+
if (showPendingTasks || !hasProgress)
|
|
97115
|
+
return false;
|
|
97116
|
+
return phase == null || phase === "implement" || phase === "done";
|
|
97117
|
+
}
|
|
97118
|
+
function phasePipeline(phase) {
|
|
97119
|
+
if (phase === "done") {
|
|
97120
|
+
return PIPELINE_PHASES.map((p) => ({ phase: p, label: p, status: "done" }));
|
|
97121
|
+
}
|
|
97122
|
+
const idx = PIPELINE_PHASES.indexOf(phase);
|
|
97123
|
+
return PIPELINE_PHASES.map((p, i) => ({
|
|
97124
|
+
phase: p,
|
|
97125
|
+
label: p,
|
|
97126
|
+
status: i < idx ? "done" : i === idx ? "current" : "pending"
|
|
97127
|
+
}));
|
|
97128
|
+
}
|
|
97129
|
+
var PIPELINE_PHASES;
|
|
97130
|
+
var init_phase = __esm(() => {
|
|
97131
|
+
PIPELINE_PHASES = [
|
|
97132
|
+
"proposal",
|
|
97133
|
+
"design",
|
|
97134
|
+
"tasks",
|
|
97135
|
+
"implement"
|
|
97136
|
+
];
|
|
97137
|
+
});
|
|
97138
|
+
|
|
97139
|
+
// apps/agent/src/hooks/useTerminalSize.ts
|
|
97140
|
+
function readSize2() {
|
|
97141
|
+
return {
|
|
97142
|
+
columns: process.stdout.columns ?? 80,
|
|
97143
|
+
rows: process.stdout.rows ?? 24
|
|
97144
|
+
};
|
|
97145
|
+
}
|
|
97146
|
+
function useTerminalSize2() {
|
|
97147
|
+
const [size2, setSize] = import_react59.useState(() => ({
|
|
97148
|
+
...readSize2(),
|
|
97149
|
+
resizeKey: 0
|
|
97150
|
+
}));
|
|
97151
|
+
import_react59.useEffect(() => {
|
|
97152
|
+
if (!process.stdout.isTTY)
|
|
97153
|
+
return;
|
|
97154
|
+
const onResize = () => {
|
|
97155
|
+
const { columns, rows } = readSize2();
|
|
97156
|
+
setSize((prev) => {
|
|
97157
|
+
if (prev.columns === columns && prev.rows === rows)
|
|
97158
|
+
return prev;
|
|
97159
|
+
return { columns, rows, resizeKey: prev.resizeKey + 1 };
|
|
97160
|
+
});
|
|
97161
|
+
};
|
|
97162
|
+
process.stdout.on("resize", onResize);
|
|
97163
|
+
return () => {
|
|
97164
|
+
process.stdout.off("resize", onResize);
|
|
97165
|
+
};
|
|
97166
|
+
}, []);
|
|
97167
|
+
return size2;
|
|
97168
|
+
}
|
|
97169
|
+
var import_react59;
|
|
97170
|
+
var init_useTerminalSize2 = __esm(() => {
|
|
97171
|
+
import_react59 = __toESM(require_react(), 1);
|
|
97172
|
+
});
|
|
97173
|
+
|
|
97174
|
+
// apps/agent/src/components/SteeringField.tsx
|
|
97175
|
+
function reducer2(state, action) {
|
|
97176
|
+
switch (action.type) {
|
|
97177
|
+
case "toggleFocus":
|
|
97178
|
+
return { ...state, focused: !state.focused };
|
|
97179
|
+
case "clearAndBlur":
|
|
97180
|
+
return { ...state, buffer: "", cursor: 0, focused: false };
|
|
97181
|
+
case "insert": {
|
|
97182
|
+
const before2 = state.buffer.slice(0, state.cursor);
|
|
97183
|
+
const after2 = state.buffer.slice(state.cursor);
|
|
97184
|
+
return {
|
|
97185
|
+
...state,
|
|
97186
|
+
buffer: before2 + action.chars + after2,
|
|
97187
|
+
cursor: state.cursor + action.chars.length
|
|
97188
|
+
};
|
|
97189
|
+
}
|
|
97190
|
+
case "backspace": {
|
|
97191
|
+
if (state.cursor === 0)
|
|
97192
|
+
return state;
|
|
97193
|
+
return {
|
|
97194
|
+
...state,
|
|
97195
|
+
buffer: state.buffer.slice(0, state.cursor - 1) + state.buffer.slice(state.cursor),
|
|
97196
|
+
cursor: state.cursor - 1
|
|
97197
|
+
};
|
|
97198
|
+
}
|
|
97199
|
+
case "moveLeft":
|
|
97200
|
+
return { ...state, cursor: Math.max(0, state.cursor - 1) };
|
|
97201
|
+
case "moveRight":
|
|
97202
|
+
return { ...state, cursor: Math.min(state.buffer.length, state.cursor + 1) };
|
|
97203
|
+
case "status":
|
|
97204
|
+
return { ...state, status: action.value };
|
|
97205
|
+
}
|
|
97206
|
+
}
|
|
97207
|
+
function SteeringField({
|
|
97208
|
+
active,
|
|
97209
|
+
width,
|
|
97210
|
+
onSubmit,
|
|
97211
|
+
onFocusChange,
|
|
97212
|
+
initialBuffer = "",
|
|
97213
|
+
initialCursor,
|
|
97214
|
+
initialFocused = false,
|
|
97215
|
+
onStateChange
|
|
97216
|
+
}) {
|
|
97217
|
+
const [state, dispatch] = import_react60.useReducer(reducer2, { initialBuffer, initialCursor, initialFocused }, (init2) => ({
|
|
97218
|
+
buffer: init2.initialBuffer,
|
|
97219
|
+
cursor: init2.initialCursor ?? init2.initialBuffer.length,
|
|
97220
|
+
focused: init2.initialFocused,
|
|
97221
|
+
status: "idle"
|
|
97222
|
+
}));
|
|
97223
|
+
const { buffer, cursor: cursor4, focused, status } = state;
|
|
97224
|
+
const stateRef = import_react60.useRef(state);
|
|
97225
|
+
stateRef.current = state;
|
|
97226
|
+
const hintTimerRef = import_react60.useRef(null);
|
|
97227
|
+
import_react60.useEffect(() => {
|
|
97228
|
+
onFocusChange?.(focused);
|
|
97229
|
+
}, [focused, onFocusChange]);
|
|
97230
|
+
import_react60.useEffect(() => {
|
|
97231
|
+
onStateChange?.({ buffer, cursor: cursor4, focused });
|
|
97232
|
+
}, [buffer, cursor4, focused, onStateChange]);
|
|
97233
|
+
import_react60.useEffect(() => {
|
|
97234
|
+
return () => {
|
|
97235
|
+
if (hintTimerRef.current)
|
|
97236
|
+
clearTimeout(hintTimerRef.current);
|
|
97237
|
+
};
|
|
97238
|
+
}, []);
|
|
97239
|
+
function flashStatus(next) {
|
|
97240
|
+
dispatch({ type: "status", value: next });
|
|
97241
|
+
if (hintTimerRef.current)
|
|
97242
|
+
clearTimeout(hintTimerRef.current);
|
|
97243
|
+
hintTimerRef.current = setTimeout(() => dispatch({ type: "status", value: "idle" }), STATUS_HINT_MS);
|
|
97244
|
+
}
|
|
97245
|
+
use_input_default((input, key) => {
|
|
97246
|
+
if (key.ctrl && (input === "s" || input === "S")) {
|
|
97247
|
+
dispatch({ type: "toggleFocus" });
|
|
97248
|
+
return;
|
|
97249
|
+
}
|
|
97250
|
+
if (!stateRef.current.focused)
|
|
97251
|
+
return;
|
|
97252
|
+
if (key.escape) {
|
|
97253
|
+
dispatch({ type: "clearAndBlur" });
|
|
97254
|
+
return;
|
|
97255
|
+
}
|
|
97256
|
+
if (key.return) {
|
|
97257
|
+
const trimmed = stateRef.current.buffer.trim();
|
|
97258
|
+
if (trimmed.length === 0)
|
|
97259
|
+
return;
|
|
97260
|
+
Promise.resolve().then(() => onSubmit(trimmed)).then(() => {
|
|
97261
|
+
flashStatus("sent");
|
|
97262
|
+
}).catch(() => {
|
|
97263
|
+
flashStatus("failed");
|
|
97264
|
+
});
|
|
97265
|
+
dispatch({ type: "clearAndBlur" });
|
|
97266
|
+
return;
|
|
97267
|
+
}
|
|
97268
|
+
if (key.backspace || key.delete) {
|
|
97269
|
+
dispatch({ type: "backspace" });
|
|
97270
|
+
return;
|
|
97271
|
+
}
|
|
97272
|
+
if (key.leftArrow) {
|
|
97273
|
+
dispatch({ type: "moveLeft" });
|
|
97274
|
+
return;
|
|
97275
|
+
}
|
|
97276
|
+
if (key.rightArrow) {
|
|
97277
|
+
dispatch({ type: "moveRight" });
|
|
97278
|
+
return;
|
|
97279
|
+
}
|
|
97280
|
+
if (key.tab || key.upArrow || key.downArrow || key.ctrl || key.meta)
|
|
97281
|
+
return;
|
|
97282
|
+
if (!input)
|
|
97283
|
+
return;
|
|
97284
|
+
const printable = input.replace(/[\x00-\x1f\x7f]/g, "");
|
|
97285
|
+
if (!printable)
|
|
97286
|
+
return;
|
|
97287
|
+
dispatch({ type: "insert", chars: printable });
|
|
97288
|
+
}, { isActive: active });
|
|
97289
|
+
if (!active)
|
|
97290
|
+
return null;
|
|
97291
|
+
const placeholder = status === "sent" ? PLACEHOLDER_SENT : status === "failed" ? PLACEHOLDER_FAILED : PLACEHOLDER_IDLE;
|
|
97292
|
+
const borderColor = focused ? "yellow" : "gray";
|
|
97293
|
+
const placeholderColor = status === "sent" ? "green" : status === "failed" ? "red" : "gray";
|
|
97294
|
+
const innerWidth = Math.max(0, width - 4);
|
|
97295
|
+
const labelText = " STEER (CTRL+S) ";
|
|
97296
|
+
const dashes = Math.max(0, innerWidth - labelText.length);
|
|
97297
|
+
const left = Math.floor(dashes / 2);
|
|
97298
|
+
const right = dashes - left;
|
|
97299
|
+
const before2 = buffer.slice(0, cursor4);
|
|
97300
|
+
const at2 = buffer.slice(cursor4, cursor4 + 1) || " ";
|
|
97301
|
+
const after2 = buffer.slice(cursor4 + 1);
|
|
97302
|
+
return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
97303
|
+
flexDirection: "column",
|
|
97304
|
+
width,
|
|
97305
|
+
children: [
|
|
97306
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
97307
|
+
color: borderColor,
|
|
97308
|
+
children: `\u256D${"\u2500".repeat(left)}${labelText}${"\u2500".repeat(right)}\u256E`
|
|
97309
|
+
}, undefined, false, undefined, this),
|
|
97310
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
97311
|
+
borderStyle: "round",
|
|
97312
|
+
borderTop: false,
|
|
97313
|
+
borderColor,
|
|
97314
|
+
width,
|
|
97315
|
+
paddingX: 1,
|
|
97316
|
+
children: focused ? /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
97317
|
+
children: [
|
|
97318
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
97319
|
+
color: "white",
|
|
97320
|
+
children: "> "
|
|
97321
|
+
}, undefined, false, undefined, this),
|
|
97322
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
97323
|
+
children: before2
|
|
97324
|
+
}, undefined, false, undefined, this),
|
|
97325
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
97326
|
+
inverse: true,
|
|
97327
|
+
children: at2
|
|
97328
|
+
}, undefined, false, undefined, this),
|
|
97329
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
97330
|
+
children: after2
|
|
97331
|
+
}, undefined, false, undefined, this)
|
|
97332
|
+
]
|
|
97333
|
+
}, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
97334
|
+
color: placeholderColor,
|
|
97335
|
+
dimColor: status === "idle",
|
|
97336
|
+
children: placeholder
|
|
97337
|
+
}, undefined, false, undefined, this)
|
|
97338
|
+
}, undefined, false, undefined, this)
|
|
97339
|
+
]
|
|
97340
|
+
}, undefined, true, undefined, this);
|
|
97341
|
+
}
|
|
97342
|
+
var import_react60, jsx_dev_runtime9, STATUS_HINT_MS = 2000, PLACEHOLDER_IDLE = "CTRL+S to steer", PLACEHOLDER_SENT = "steered \u2192 next iteration", PLACEHOLDER_FAILED = "send failed";
|
|
97343
|
+
var init_SteeringField = __esm(async () => {
|
|
97344
|
+
await init_build2();
|
|
97345
|
+
import_react60 = __toESM(require_react(), 1);
|
|
97346
|
+
jsx_dev_runtime9 = __toESM(require_jsx_dev_runtime(), 1);
|
|
97347
|
+
});
|
|
96158
97348
|
|
|
96159
97349
|
// apps/agent/src/components/AgentMode.tsx
|
|
96160
97350
|
import { join as join22 } from "path";
|
|
97351
|
+
async function appendSteeringImpl(changeDir, message) {
|
|
97352
|
+
await runWithContext(createDefaultContext(), async () => {
|
|
97353
|
+
appendSteeringMessage(changeDir, message);
|
|
97354
|
+
});
|
|
97355
|
+
}
|
|
96161
97356
|
function nextId() {
|
|
96162
97357
|
lineCounter += 1;
|
|
96163
97358
|
return `${Date.now()}-${lineCounter}`;
|
|
96164
97359
|
}
|
|
96165
|
-
function
|
|
96166
|
-
|
|
97360
|
+
function parseSubtasks(tasksMd) {
|
|
97361
|
+
const out = [];
|
|
97362
|
+
let skipSection = false;
|
|
97363
|
+
for (const line of tasksMd.split(`
|
|
97364
|
+
`)) {
|
|
97365
|
+
const heading = line.match(/^##\s+(.+?)\s*$/);
|
|
97366
|
+
if (heading) {
|
|
97367
|
+
const title = heading[1].trim();
|
|
97368
|
+
skipSection = title.toLowerCase() === "planning" || isFlowTaskHeading(title);
|
|
97369
|
+
continue;
|
|
97370
|
+
}
|
|
97371
|
+
if (skipSection)
|
|
97372
|
+
continue;
|
|
97373
|
+
const m = line.match(/^- \[([ xX])\] (.+)$/);
|
|
97374
|
+
if (m)
|
|
97375
|
+
out.push({ done: m[1] !== " ", text: m[2].trim() });
|
|
97376
|
+
}
|
|
97377
|
+
return out;
|
|
97378
|
+
}
|
|
97379
|
+
function orderSubtasksForCappedDisplay(subtasks) {
|
|
97380
|
+
const pending = [];
|
|
97381
|
+
const done = [];
|
|
97382
|
+
for (const s of subtasks)
|
|
97383
|
+
(s.done ? done : pending).push(s);
|
|
97384
|
+
return [...pending, ...done];
|
|
96167
97385
|
}
|
|
96168
97386
|
function fmtCmd(argv) {
|
|
96169
97387
|
const joined = argv.join(" ");
|
|
@@ -96213,28 +97431,28 @@ function LabeledBox({
|
|
|
96213
97431
|
const dashes = Math.max(0, innerWidth - visualLen);
|
|
96214
97432
|
const left = Math.floor(dashes / 2);
|
|
96215
97433
|
const right = dashes - left;
|
|
96216
|
-
return /* @__PURE__ */
|
|
97434
|
+
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
96217
97435
|
flexDirection: "column",
|
|
96218
97436
|
width,
|
|
96219
97437
|
children: [
|
|
96220
|
-
labelNode ? /* @__PURE__ */
|
|
97438
|
+
labelNode ? /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
96221
97439
|
flexDirection: "row",
|
|
96222
97440
|
children: [
|
|
96223
|
-
/* @__PURE__ */
|
|
97441
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96224
97442
|
color: borderColor,
|
|
96225
97443
|
children: `\u256D${"\u2500".repeat(left)}`
|
|
96226
97444
|
}, undefined, false, undefined, this),
|
|
96227
97445
|
labelNode,
|
|
96228
|
-
/* @__PURE__ */
|
|
97446
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96229
97447
|
color: borderColor,
|
|
96230
97448
|
children: `${"\u2500".repeat(right)}\u256E`
|
|
96231
97449
|
}, undefined, false, undefined, this)
|
|
96232
97450
|
]
|
|
96233
|
-
}, undefined, true, undefined, this) : /* @__PURE__ */
|
|
97451
|
+
}, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96234
97452
|
color: borderColor,
|
|
96235
97453
|
children: `\u256D${"\u2500".repeat(left)} ${label ?? ""} ${"\u2500".repeat(right)}\u256E`
|
|
96236
97454
|
}, undefined, false, undefined, this),
|
|
96237
|
-
/* @__PURE__ */
|
|
97455
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
96238
97456
|
borderStyle: "round",
|
|
96239
97457
|
borderTop: false,
|
|
96240
97458
|
borderColor,
|
|
@@ -96247,13 +97465,13 @@ function LabeledBox({
|
|
|
96247
97465
|
}
|
|
96248
97466
|
function Link({ url: url2, label, color }) {
|
|
96249
97467
|
if (!HYPERLINKS_SUPPORTED)
|
|
96250
|
-
return /* @__PURE__ */
|
|
97468
|
+
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96251
97469
|
color,
|
|
96252
97470
|
children: label
|
|
96253
97471
|
}, undefined, false, undefined, this);
|
|
96254
|
-
return /* @__PURE__ */
|
|
97472
|
+
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Transform, {
|
|
96255
97473
|
transform: (output) => `\x1B]8;;${url2}\x07${output}\x1B]8;;\x07`,
|
|
96256
|
-
children: /* @__PURE__ */
|
|
97474
|
+
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96257
97475
|
color,
|
|
96258
97476
|
underline: true,
|
|
96259
97477
|
children: label
|
|
@@ -96369,19 +97587,37 @@ function displayTailLines(activeCount) {
|
|
|
96369
97587
|
return 8;
|
|
96370
97588
|
return 5;
|
|
96371
97589
|
}
|
|
96372
|
-
function AgentMode({
|
|
97590
|
+
function AgentMode({
|
|
97591
|
+
args,
|
|
97592
|
+
projectRoot,
|
|
97593
|
+
statesDir,
|
|
97594
|
+
tasksDir,
|
|
97595
|
+
appendSteering = appendSteeringImpl,
|
|
97596
|
+
buildCoordinator = buildAgentCoordinator,
|
|
97597
|
+
ensureConfig = ensureRalphyConfig,
|
|
97598
|
+
loadConfig = loadRalphyConfig
|
|
97599
|
+
}) {
|
|
96373
97600
|
const { exit } = use_app_default();
|
|
96374
97601
|
const { stdout } = use_stdout_default();
|
|
96375
97602
|
const { isRawModeSupported } = use_stdin_default();
|
|
96376
|
-
const
|
|
96377
|
-
|
|
96378
|
-
|
|
96379
|
-
|
|
96380
|
-
|
|
96381
|
-
|
|
96382
|
-
const
|
|
96383
|
-
const
|
|
96384
|
-
const [
|
|
97603
|
+
const { columns, rows, resizeKey } = useTerminalSize2();
|
|
97604
|
+
import_react61.useEffect(() => {
|
|
97605
|
+
if (resizeKey === 0)
|
|
97606
|
+
return;
|
|
97607
|
+
stdout.write("\x1B[2J\x1B[3J\x1B[H");
|
|
97608
|
+
}, [resizeKey, stdout]);
|
|
97609
|
+
const [logs, setLogs] = import_react61.useState([]);
|
|
97610
|
+
const [, setTick] = import_react61.useState(0);
|
|
97611
|
+
const [clock, setClock] = import_react61.useState(0);
|
|
97612
|
+
const [focusedIdx, setFocusedIdx] = import_react61.useState(0);
|
|
97613
|
+
const [showPendingTasks, setShowPendingTasks] = import_react61.useState(true);
|
|
97614
|
+
const [showAllSubtasks, setShowAllSubtasks] = import_react61.useState(false);
|
|
97615
|
+
const coordRef = import_react61.useRef(null);
|
|
97616
|
+
const workerMetaRef = import_react61.useRef(new Map);
|
|
97617
|
+
const nextPollAtRef = import_react61.useRef(0);
|
|
97618
|
+
const cfgRef = import_react61.useRef(null);
|
|
97619
|
+
const [effective, setEffective] = import_react61.useState(null);
|
|
97620
|
+
const [pollStatus, setPollStatus] = import_react61.useState({
|
|
96385
97621
|
state: "idle",
|
|
96386
97622
|
lastFound: null,
|
|
96387
97623
|
lastAdded: null,
|
|
@@ -96394,20 +97630,20 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
96394
97630
|
setLogs((prev) => [...prev, { id: nextId(), text, color }]);
|
|
96395
97631
|
logCoord(text, workerLogFile);
|
|
96396
97632
|
}
|
|
96397
|
-
|
|
97633
|
+
import_react61.useEffect(() => {
|
|
96398
97634
|
let pollTimer = null;
|
|
96399
97635
|
let cancelled = false;
|
|
96400
97636
|
async function init2() {
|
|
96401
97637
|
logSession(`=== session start ${SESSION_START} ===`);
|
|
96402
|
-
const cfgPath = await
|
|
96403
|
-
const cfg2 = await
|
|
97638
|
+
const cfgPath = await ensureConfig(projectRoot);
|
|
97639
|
+
const cfg2 = await loadConfig(projectRoot);
|
|
96404
97640
|
cfgRef.current = cfg2;
|
|
96405
97641
|
appendLog(`agent mode v${VERSION} \u2014 config: ${cfgPath}`, "gray");
|
|
96406
97642
|
const apiKey = process.env["LINEAR_API_KEY"];
|
|
96407
97643
|
if (!apiKey) {
|
|
96408
97644
|
throw new Error("LINEAR_API_KEY not set \u2014 cannot poll Linear");
|
|
96409
97645
|
}
|
|
96410
|
-
const { coord: coord2, filterDesc, concurrency, pollInterval } =
|
|
97646
|
+
const { coord: coord2, filterDesc, concurrency, pollInterval, runBaselineGate: runBaselineGate2 } = buildCoordinator({
|
|
96411
97647
|
args,
|
|
96412
97648
|
cfg: cfg2,
|
|
96413
97649
|
projectRoot,
|
|
@@ -96415,6 +97651,7 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
96415
97651
|
tasksDir,
|
|
96416
97652
|
apiKey,
|
|
96417
97653
|
onLog: appendLog,
|
|
97654
|
+
onFileLog: (text) => logCoord(text),
|
|
96418
97655
|
onWorkersChanged: () => setTick((t) => t + 1),
|
|
96419
97656
|
onWorkerStarted: (changeName, dir, logFile, changeDir) => {
|
|
96420
97657
|
logSession(`worker-started ${changeName} log=${logFile}`, logFile);
|
|
@@ -96428,6 +97665,7 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
96428
97665
|
phaseDetail: "",
|
|
96429
97666
|
phaseStartedAt: Date.now(),
|
|
96430
97667
|
currentTask: null,
|
|
97668
|
+
subtasks: [],
|
|
96431
97669
|
taskProgress: null,
|
|
96432
97670
|
openspecPhase: null,
|
|
96433
97671
|
prUrl: null,
|
|
@@ -96477,12 +97715,20 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
96477
97715
|
m.prUrl = prUrl;
|
|
96478
97716
|
}
|
|
96479
97717
|
});
|
|
97718
|
+
setEffective({ concurrency, pollInterval });
|
|
96480
97719
|
coordRef.current = coord2;
|
|
96481
97720
|
await coord2.init();
|
|
96482
97721
|
const tick = async () => {
|
|
96483
97722
|
if (cancelled)
|
|
96484
97723
|
return;
|
|
96485
97724
|
setPollStatus((p) => ({ ...p, state: "polling", filterDesc }));
|
|
97725
|
+
try {
|
|
97726
|
+
await runBaselineGate2();
|
|
97727
|
+
} catch (err) {
|
|
97728
|
+
appendLog(`! baseline gate failed: ${err.message}`, "yellow");
|
|
97729
|
+
}
|
|
97730
|
+
if (cancelled)
|
|
97731
|
+
return;
|
|
96486
97732
|
const { found, added, buckets, prStatus } = await coord2.pollOnce();
|
|
96487
97733
|
if (cancelled)
|
|
96488
97734
|
return;
|
|
@@ -96554,7 +97800,7 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
96554
97800
|
process.off("SIGTERM", onSig);
|
|
96555
97801
|
};
|
|
96556
97802
|
}, []);
|
|
96557
|
-
|
|
97803
|
+
import_react61.useEffect(() => {
|
|
96558
97804
|
let cancelled = false;
|
|
96559
97805
|
const interval = setInterval(() => {
|
|
96560
97806
|
if (cancelled)
|
|
@@ -96581,8 +97827,9 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
96581
97827
|
designFile.exists().then((ok) => ok ? designFile.text() : null)
|
|
96582
97828
|
]);
|
|
96583
97829
|
if (tasksText !== null) {
|
|
96584
|
-
const
|
|
96585
|
-
meta3.
|
|
97830
|
+
const subtasks = parseSubtasks(tasksText);
|
|
97831
|
+
meta3.subtasks = subtasks;
|
|
97832
|
+
meta3.currentTask = subtasks.find((s) => !s.done)?.text ?? null;
|
|
96586
97833
|
const { checked, total } = countProgress(tasksText);
|
|
96587
97834
|
meta3.taskProgress = total > 0 ? { checked, total } : null;
|
|
96588
97835
|
}
|
|
@@ -96611,10 +97858,26 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
96611
97858
|
const now2 = Date.now();
|
|
96612
97859
|
const secsToNextPoll = nextPollAtRef.current ? Math.max(0, Math.ceil((nextPollAtRef.current - now2) / 1000)) : null;
|
|
96613
97860
|
const activeCount = coord?.activeCount ?? 0;
|
|
96614
|
-
const termWidth =
|
|
96615
|
-
const termHeight =
|
|
97861
|
+
const termWidth = columns - 2;
|
|
97862
|
+
const termHeight = rows;
|
|
96616
97863
|
const safeFocusedIdx = activeCount > 0 ? Math.min(focusedIdx, activeCount - 1) : 0;
|
|
97864
|
+
const steeringFocusedRef = import_react61.useRef(false);
|
|
97865
|
+
const steeringBufferRef = import_react61.useRef("");
|
|
97866
|
+
const steeringCursorRef = import_react61.useRef(0);
|
|
97867
|
+
const steeringFocusedInitRef = import_react61.useRef(false);
|
|
96617
97868
|
use_input_default((input, key) => {
|
|
97869
|
+
if (steeringFocusedRef.current)
|
|
97870
|
+
return;
|
|
97871
|
+
if (key.ctrl && key.meta && (input === "t" || input === "T")) {
|
|
97872
|
+
if (activeCount > 0)
|
|
97873
|
+
setShowAllSubtasks((v) => !v);
|
|
97874
|
+
return;
|
|
97875
|
+
}
|
|
97876
|
+
if (key.ctrl && (input === "t" || input === "T")) {
|
|
97877
|
+
if (activeCount > 0)
|
|
97878
|
+
setShowPendingTasks((v) => !v);
|
|
97879
|
+
return;
|
|
97880
|
+
}
|
|
96618
97881
|
if (activeCount === 0)
|
|
96619
97882
|
return;
|
|
96620
97883
|
if (key.tab || key.rightArrow) {
|
|
@@ -96626,57 +97889,80 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
96626
97889
|
if (!isNaN(n) && n >= 1 && n <= activeCount)
|
|
96627
97890
|
setFocusedIdx(n - 1);
|
|
96628
97891
|
}
|
|
96629
|
-
}, { isActive: isRawModeSupported && activeCount >
|
|
97892
|
+
}, { isActive: isRawModeSupported && activeCount > 0 });
|
|
97893
|
+
const focusedWorker = coordRef.current?.activeWorkers[safeFocusedIdx];
|
|
97894
|
+
const steeringActive = isRawModeSupported && activeCount > 0 && focusedWorker !== undefined;
|
|
96630
97895
|
const nonFocusedCount = Math.max(0, activeCount - 1);
|
|
96631
97896
|
const tasksBoxLines = activeCount > 1 ? 5 : 0;
|
|
96632
|
-
const
|
|
96633
|
-
const
|
|
96634
|
-
const FIXED_OVERHEAD = logsBoxLines + 5 + 6 + tasksBoxLines + 8 + nonFocusedCount * 4;
|
|
97897
|
+
const steeringBoxLines = steeringActive ? 3 : 0;
|
|
97898
|
+
const FIXED_OVERHEAD = 5 + 7 + tasksBoxLines + 8 + steeringBoxLines + nonFocusedCount * 4;
|
|
96635
97899
|
const focusedTailLines = Math.max(3, termHeight - FIXED_OVERHEAD);
|
|
96636
97900
|
const compactTailLines = displayTailLines(activeCount);
|
|
96637
|
-
return /* @__PURE__ */
|
|
97901
|
+
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
96638
97902
|
flexDirection: "column",
|
|
96639
97903
|
children: [
|
|
96640
|
-
|
|
96641
|
-
|
|
96642
|
-
|
|
96643
|
-
flexDirection: "column",
|
|
96644
|
-
paddingX: 1,
|
|
96645
|
-
width: termWidth,
|
|
96646
|
-
children: visibleLogWindow(logs).map((line) => line.color ? /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
97904
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Static, {
|
|
97905
|
+
items: logs,
|
|
97906
|
+
children: (line) => line.color ? /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96647
97907
|
color: line.color,
|
|
96648
97908
|
children: line.text
|
|
96649
|
-
}, line.id, false, undefined, this) : /* @__PURE__ */
|
|
97909
|
+
}, line.id, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96650
97910
|
children: line.text
|
|
96651
|
-
}, line.id, false, undefined, this)
|
|
97911
|
+
}, line.id, false, undefined, this)
|
|
96652
97912
|
}, undefined, false, undefined, this),
|
|
96653
|
-
/* @__PURE__ */
|
|
97913
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
96654
97914
|
flexDirection: "column",
|
|
96655
97915
|
marginTop: 0,
|
|
96656
97916
|
children: [
|
|
96657
|
-
|
|
97917
|
+
(() => {
|
|
97918
|
+
const pause = coordRef.current?.getPause?.() ?? null;
|
|
97919
|
+
if (!pause)
|
|
97920
|
+
return null;
|
|
97921
|
+
const seconds = Math.floor((Date.now() - pause.since) / 1000);
|
|
97922
|
+
const duration3 = seconds < 60 ? `${seconds}s` : seconds < 3600 ? `${Math.floor(seconds / 60)}m` : `${Math.floor(seconds / 3600)}h${Math.floor(seconds % 3600 / 60)}m`;
|
|
97923
|
+
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
97924
|
+
borderStyle: "round",
|
|
97925
|
+
borderColor: "red",
|
|
97926
|
+
paddingX: 1,
|
|
97927
|
+
width: termWidth,
|
|
97928
|
+
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97929
|
+
color: "red",
|
|
97930
|
+
bold: true,
|
|
97931
|
+
children: [
|
|
97932
|
+
"\u26D4 BASELINE BROKEN ",
|
|
97933
|
+
pause.issueIdentifier,
|
|
97934
|
+
" \xB7 ",
|
|
97935
|
+
duration3,
|
|
97936
|
+
" \xB7 `",
|
|
97937
|
+
pause.command,
|
|
97938
|
+
"`"
|
|
97939
|
+
]
|
|
97940
|
+
}, undefined, true, undefined, this)
|
|
97941
|
+
}, undefined, false, undefined, this);
|
|
97942
|
+
})(),
|
|
97943
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(LabeledBox, {
|
|
96658
97944
|
label: "\u25C8 RALPH AGENT",
|
|
96659
97945
|
borderColor: "blue",
|
|
96660
97946
|
width: termWidth,
|
|
96661
97947
|
paddingX: 1,
|
|
96662
97948
|
flexDirection: "column",
|
|
96663
97949
|
children: [
|
|
96664
|
-
/* @__PURE__ */
|
|
97950
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96665
97951
|
children: [
|
|
96666
|
-
/* @__PURE__ */
|
|
97952
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96667
97953
|
dimColor: true,
|
|
96668
97954
|
children: [
|
|
96669
97955
|
"v",
|
|
96670
97956
|
VERSION
|
|
96671
97957
|
]
|
|
96672
97958
|
}, undefined, true, undefined, this),
|
|
96673
|
-
cfg && /* @__PURE__ */
|
|
97959
|
+
cfg && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96674
97960
|
children: [
|
|
96675
|
-
/* @__PURE__ */
|
|
97961
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96676
97962
|
dimColor: true,
|
|
96677
97963
|
children: " \u2502 "
|
|
96678
97964
|
}, undefined, false, undefined, this),
|
|
96679
|
-
/* @__PURE__ */
|
|
97965
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96680
97966
|
color: "cyan",
|
|
96681
97967
|
bold: true,
|
|
96682
97968
|
children: [
|
|
@@ -96685,51 +97971,51 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
96685
97971
|
cfg.model
|
|
96686
97972
|
]
|
|
96687
97973
|
}, undefined, true, undefined, this),
|
|
96688
|
-
/* @__PURE__ */
|
|
97974
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96689
97975
|
dimColor: true,
|
|
96690
97976
|
children: [
|
|
96691
97977
|
" \u2502 \xD7",
|
|
96692
|
-
cfg.concurrency
|
|
97978
|
+
effective?.concurrency ?? cfg.concurrency
|
|
96693
97979
|
]
|
|
96694
97980
|
}, undefined, true, undefined, this),
|
|
96695
|
-
/* @__PURE__ */
|
|
97981
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96696
97982
|
dimColor: true,
|
|
96697
97983
|
children: [
|
|
96698
97984
|
" \u2502 poll ",
|
|
96699
|
-
cfg.pollIntervalSeconds,
|
|
97985
|
+
effective?.pollInterval ?? cfg.pollIntervalSeconds,
|
|
96700
97986
|
"s"
|
|
96701
97987
|
]
|
|
96702
97988
|
}, undefined, true, undefined, this),
|
|
96703
|
-
cfg.maxIterationsPerTask > 0 && /* @__PURE__ */
|
|
97989
|
+
cfg.maxIterationsPerTask > 0 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96704
97990
|
color: "yellow",
|
|
96705
97991
|
children: [
|
|
96706
97992
|
" \u2502 iter \u2264",
|
|
96707
97993
|
cfg.maxIterationsPerTask
|
|
96708
97994
|
]
|
|
96709
97995
|
}, undefined, true, undefined, this),
|
|
96710
|
-
cfg.maxCostUsdPerTask > 0 && /* @__PURE__ */
|
|
97996
|
+
cfg.maxCostUsdPerTask > 0 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96711
97997
|
color: "yellow",
|
|
96712
97998
|
children: [
|
|
96713
97999
|
" \u2502 cost \u2264$",
|
|
96714
98000
|
cfg.maxCostUsdPerTask
|
|
96715
98001
|
]
|
|
96716
98002
|
}, undefined, true, undefined, this),
|
|
96717
|
-
args.maxTickets > 0 && /* @__PURE__ */
|
|
98003
|
+
args.maxTickets > 0 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96718
98004
|
color: "yellow",
|
|
96719
98005
|
children: [
|
|
96720
98006
|
" \u2502 tickets \u2264",
|
|
96721
98007
|
args.maxTickets
|
|
96722
98008
|
]
|
|
96723
98009
|
}, undefined, true, undefined, this),
|
|
96724
|
-
cfg.createPrOnSuccess && /* @__PURE__ */
|
|
98010
|
+
cfg.createPrOnSuccess && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96725
98011
|
color: "green",
|
|
96726
98012
|
children: " \u25CF PR"
|
|
96727
98013
|
}, undefined, false, undefined, this),
|
|
96728
|
-
cfg.fixCiOnFailure && /* @__PURE__ */
|
|
98014
|
+
cfg.fixCiOnFailure && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96729
98015
|
color: "green",
|
|
96730
98016
|
children: " \u25CF fixCI"
|
|
96731
98017
|
}, undefined, false, undefined, this),
|
|
96732
|
-
cfg.useWorktree && /* @__PURE__ */
|
|
98018
|
+
cfg.useWorktree && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96733
98019
|
color: "green",
|
|
96734
98020
|
children: " \u25CF worktree"
|
|
96735
98021
|
}, undefined, false, undefined, this)
|
|
@@ -96749,7 +98035,7 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
96749
98035
|
lines.push(remaining.slice(0, budget));
|
|
96750
98036
|
remaining = remaining.slice(budget);
|
|
96751
98037
|
}
|
|
96752
|
-
return lines.map((segment, i) => /* @__PURE__ */
|
|
98038
|
+
return lines.map((segment, i) => /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96753
98039
|
dimColor: true,
|
|
96754
98040
|
children: [
|
|
96755
98041
|
i === 0 ? prefix : indent,
|
|
@@ -96759,157 +98045,140 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
96759
98045
|
})()
|
|
96760
98046
|
]
|
|
96761
98047
|
}, undefined, true, undefined, this),
|
|
96762
|
-
/* @__PURE__ */
|
|
98048
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
96763
98049
|
flexDirection: "row",
|
|
96764
98050
|
gap: 1,
|
|
96765
98051
|
marginTop: 0,
|
|
96766
98052
|
width: termWidth,
|
|
96767
98053
|
children: [
|
|
96768
|
-
/* @__PURE__ */
|
|
98054
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(LabeledBox, {
|
|
96769
98055
|
label: "POLL STATUS",
|
|
96770
98056
|
borderColor: "gray",
|
|
96771
|
-
width: termWidth -
|
|
98057
|
+
width: termWidth - 17,
|
|
96772
98058
|
paddingX: 1,
|
|
96773
98059
|
flexDirection: "column",
|
|
96774
98060
|
children: [
|
|
96775
|
-
/* @__PURE__ */
|
|
98061
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
96776
98062
|
gap: 2,
|
|
96777
98063
|
children: [
|
|
96778
|
-
/* @__PURE__ */
|
|
98064
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96779
98065
|
color: "gray",
|
|
96780
98066
|
children: spinnerFrame
|
|
96781
98067
|
}, undefined, false, undefined, this),
|
|
96782
|
-
/* @__PURE__ */
|
|
98068
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96783
98069
|
children: pollStatus.state === "polling" ? "Polling Linear\u2026" : pollStatus.lastAt !== null ? "Idle" : "Starting\u2026"
|
|
96784
98070
|
}, undefined, false, undefined, this),
|
|
96785
|
-
pollStatus.lastAt !== null && /* @__PURE__ */
|
|
98071
|
+
pollStatus.lastAt !== null && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(jsx_dev_runtime10.Fragment, {
|
|
98072
|
+
children: pollStatus.lastBuckets && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(jsx_dev_runtime10.Fragment, {
|
|
98073
|
+
children: [
|
|
98074
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98075
|
+
dimColor: true,
|
|
98076
|
+
children: "\u2502"
|
|
98077
|
+
}, undefined, false, undefined, this),
|
|
98078
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98079
|
+
dimColor: true,
|
|
98080
|
+
children: "todo"
|
|
98081
|
+
}, undefined, false, undefined, this),
|
|
98082
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98083
|
+
color: "white",
|
|
98084
|
+
children: pollStatus.lastBuckets.todo
|
|
98085
|
+
}, undefined, false, undefined, this),
|
|
98086
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98087
|
+
dimColor: true,
|
|
98088
|
+
children: "\xB7"
|
|
98089
|
+
}, undefined, false, undefined, this),
|
|
98090
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98091
|
+
dimColor: true,
|
|
98092
|
+
children: "resume"
|
|
98093
|
+
}, undefined, false, undefined, this),
|
|
98094
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98095
|
+
color: pollStatus.lastBuckets.inProgress > 0 ? "cyan" : "white",
|
|
98096
|
+
children: pollStatus.lastBuckets.inProgress
|
|
98097
|
+
}, undefined, false, undefined, this),
|
|
98098
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98099
|
+
dimColor: true,
|
|
98100
|
+
children: "\xB7"
|
|
98101
|
+
}, undefined, false, undefined, this),
|
|
98102
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98103
|
+
dimColor: true,
|
|
98104
|
+
children: "review"
|
|
98105
|
+
}, undefined, false, undefined, this),
|
|
98106
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98107
|
+
color: pollStatus.lastBuckets.review > 0 ? "yellow" : "white",
|
|
98108
|
+
children: pollStatus.lastBuckets.review
|
|
98109
|
+
}, undefined, false, undefined, this),
|
|
98110
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98111
|
+
dimColor: true,
|
|
98112
|
+
children: "\xB7"
|
|
98113
|
+
}, undefined, false, undefined, this),
|
|
98114
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98115
|
+
dimColor: true,
|
|
98116
|
+
children: "mentions"
|
|
98117
|
+
}, undefined, false, undefined, this),
|
|
98118
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98119
|
+
color: pollStatus.lastBuckets.mentions > 0 ? "magenta" : "white",
|
|
98120
|
+
children: pollStatus.lastBuckets.mentions
|
|
98121
|
+
}, undefined, false, undefined, this)
|
|
98122
|
+
]
|
|
98123
|
+
}, undefined, true, undefined, this)
|
|
98124
|
+
}, undefined, false, undefined, this)
|
|
98125
|
+
]
|
|
98126
|
+
}, undefined, true, undefined, this),
|
|
98127
|
+
pollStatus.lastAt !== null && pollStatus.lastPrStatus && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
98128
|
+
gap: 2,
|
|
98129
|
+
children: [
|
|
98130
|
+
secsToNextPoll !== null ? /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
98131
|
+
gap: 1,
|
|
98132
|
+
width: 7,
|
|
96786
98133
|
children: [
|
|
96787
|
-
|
|
96788
|
-
|
|
96789
|
-
|
|
96790
|
-
|
|
96791
|
-
|
|
96792
|
-
|
|
96793
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
96794
|
-
dimColor: true,
|
|
96795
|
-
children: "todo"
|
|
96796
|
-
}, undefined, false, undefined, this),
|
|
96797
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
96798
|
-
color: "white",
|
|
96799
|
-
children: pollStatus.lastBuckets.todo
|
|
96800
|
-
}, undefined, false, undefined, this),
|
|
96801
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
96802
|
-
dimColor: true,
|
|
96803
|
-
children: "\xB7"
|
|
96804
|
-
}, undefined, false, undefined, this),
|
|
96805
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
96806
|
-
dimColor: true,
|
|
96807
|
-
children: "res"
|
|
96808
|
-
}, undefined, false, undefined, this),
|
|
96809
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
96810
|
-
color: pollStatus.lastBuckets.inProgress > 0 ? "cyan" : "white",
|
|
96811
|
-
children: pollStatus.lastBuckets.inProgress
|
|
96812
|
-
}, undefined, false, undefined, this),
|
|
96813
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
96814
|
-
dimColor: true,
|
|
96815
|
-
children: "\xB7"
|
|
96816
|
-
}, undefined, false, undefined, this),
|
|
96817
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
96818
|
-
dimColor: true,
|
|
96819
|
-
children: "conf"
|
|
96820
|
-
}, undefined, false, undefined, this),
|
|
96821
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
96822
|
-
color: pollStatus.lastBuckets.conflicted > 0 ? "red" : "white",
|
|
96823
|
-
children: pollStatus.lastBuckets.conflicted
|
|
96824
|
-
}, undefined, false, undefined, this),
|
|
96825
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
96826
|
-
dimColor: true,
|
|
96827
|
-
children: "\xB7"
|
|
96828
|
-
}, undefined, false, undefined, this),
|
|
96829
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
96830
|
-
dimColor: true,
|
|
96831
|
-
children: "rev"
|
|
96832
|
-
}, undefined, false, undefined, this),
|
|
96833
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
96834
|
-
color: pollStatus.lastBuckets.review > 0 ? "yellow" : "white",
|
|
96835
|
-
children: pollStatus.lastBuckets.review
|
|
96836
|
-
}, undefined, false, undefined, this),
|
|
96837
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
96838
|
-
dimColor: true,
|
|
96839
|
-
children: "\xB7"
|
|
96840
|
-
}, undefined, false, undefined, this),
|
|
96841
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
96842
|
-
dimColor: true,
|
|
96843
|
-
children: "@"
|
|
96844
|
-
}, undefined, false, undefined, this),
|
|
96845
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
96846
|
-
color: pollStatus.lastBuckets.mentions > 0 ? "magenta" : "white",
|
|
96847
|
-
children: pollStatus.lastBuckets.mentions
|
|
96848
|
-
}, undefined, false, undefined, this)
|
|
96849
|
-
]
|
|
96850
|
-
}, undefined, true, undefined, this),
|
|
96851
|
-
secsToNextPoll !== null && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(jsx_dev_runtime9.Fragment, {
|
|
98134
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98135
|
+
dimColor: true,
|
|
98136
|
+
children: "\u21BA"
|
|
98137
|
+
}, undefined, false, undefined, this),
|
|
98138
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98139
|
+
color: "gray",
|
|
96852
98140
|
children: [
|
|
96853
|
-
|
|
96854
|
-
|
|
96855
|
-
children: "\u2502"
|
|
96856
|
-
}, undefined, false, undefined, this),
|
|
96857
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
96858
|
-
dimColor: true,
|
|
96859
|
-
children: "\u21BA"
|
|
96860
|
-
}, undefined, false, undefined, this),
|
|
96861
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
96862
|
-
color: "gray",
|
|
96863
|
-
children: [
|
|
96864
|
-
secsToNextPoll,
|
|
96865
|
-
"s"
|
|
96866
|
-
]
|
|
96867
|
-
}, undefined, true, undefined, this)
|
|
98141
|
+
secsToNextPoll,
|
|
98142
|
+
"s"
|
|
96868
98143
|
]
|
|
96869
98144
|
}, undefined, true, undefined, this)
|
|
96870
98145
|
]
|
|
96871
|
-
}, undefined, true, undefined, this)
|
|
96872
|
-
]
|
|
96873
|
-
}, undefined, true, undefined, this),
|
|
96874
|
-
pollStatus.lastAt !== null && pollStatus.lastPrStatus && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
96875
|
-
gap: 2,
|
|
96876
|
-
children: [
|
|
96877
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
98146
|
+
}, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96878
98147
|
children: " ".repeat(7)
|
|
96879
98148
|
}, undefined, false, undefined, this),
|
|
96880
|
-
/* @__PURE__ */
|
|
98149
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96881
98150
|
dimColor: true,
|
|
96882
98151
|
children: "\u2502"
|
|
96883
98152
|
}, undefined, false, undefined, this),
|
|
96884
|
-
/* @__PURE__ */
|
|
98153
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96885
98154
|
dimColor: true,
|
|
96886
98155
|
children: "mergeable"
|
|
96887
98156
|
}, undefined, false, undefined, this),
|
|
96888
|
-
/* @__PURE__ */
|
|
98157
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96889
98158
|
color: pollStatus.lastPrStatus.mergeable > 0 ? "green" : "white",
|
|
96890
98159
|
children: pollStatus.lastPrStatus.mergeable
|
|
96891
98160
|
}, undefined, false, undefined, this),
|
|
96892
|
-
/* @__PURE__ */
|
|
98161
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96893
98162
|
dimColor: true,
|
|
96894
98163
|
children: "\xB7"
|
|
96895
98164
|
}, undefined, false, undefined, this),
|
|
96896
|
-
/* @__PURE__ */
|
|
98165
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96897
98166
|
dimColor: true,
|
|
96898
98167
|
children: "conflicted"
|
|
96899
98168
|
}, undefined, false, undefined, this),
|
|
96900
|
-
/* @__PURE__ */
|
|
98169
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96901
98170
|
color: pollStatus.lastPrStatus.conflicted > 0 ? "red" : "white",
|
|
96902
98171
|
children: pollStatus.lastPrStatus.conflicted
|
|
96903
98172
|
}, undefined, false, undefined, this),
|
|
96904
|
-
/* @__PURE__ */
|
|
98173
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96905
98174
|
dimColor: true,
|
|
96906
98175
|
children: "\xB7"
|
|
96907
98176
|
}, undefined, false, undefined, this),
|
|
96908
|
-
/* @__PURE__ */
|
|
98177
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96909
98178
|
dimColor: true,
|
|
96910
98179
|
children: "ci-failed"
|
|
96911
98180
|
}, undefined, false, undefined, this),
|
|
96912
|
-
/* @__PURE__ */
|
|
98181
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96913
98182
|
color: pollStatus.lastPrStatus.ciFailed > 0 ? "red" : "white",
|
|
96914
98183
|
children: pollStatus.lastPrStatus.ciFailed
|
|
96915
98184
|
}, undefined, false, undefined, this)
|
|
@@ -96917,35 +98186,35 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
96917
98186
|
}, undefined, true, undefined, this)
|
|
96918
98187
|
]
|
|
96919
98188
|
}, undefined, true, undefined, this),
|
|
96920
|
-
/* @__PURE__ */
|
|
98189
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(LabeledBox, {
|
|
96921
98190
|
label: "WORKERS",
|
|
96922
98191
|
borderColor: "gray",
|
|
96923
|
-
width:
|
|
98192
|
+
width: 16,
|
|
96924
98193
|
paddingX: 1,
|
|
96925
98194
|
flexDirection: "column",
|
|
96926
98195
|
children: [
|
|
96927
|
-
/* @__PURE__ */
|
|
98196
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
96928
98197
|
gap: 1,
|
|
96929
98198
|
children: [
|
|
96930
|
-
/* @__PURE__ */
|
|
98199
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96931
98200
|
dimColor: true,
|
|
96932
|
-
children: "
|
|
98201
|
+
children: "active"
|
|
96933
98202
|
}, undefined, false, undefined, this),
|
|
96934
|
-
/* @__PURE__ */
|
|
98203
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96935
98204
|
color: activeCount > 0 ? "cyan" : "gray",
|
|
96936
98205
|
bold: true,
|
|
96937
98206
|
children: activeCount
|
|
96938
98207
|
}, undefined, false, undefined, this)
|
|
96939
98208
|
]
|
|
96940
98209
|
}, undefined, true, undefined, this),
|
|
96941
|
-
/* @__PURE__ */
|
|
98210
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
96942
98211
|
gap: 1,
|
|
96943
98212
|
children: [
|
|
96944
|
-
/* @__PURE__ */
|
|
98213
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96945
98214
|
dimColor: true,
|
|
96946
98215
|
children: "queue"
|
|
96947
98216
|
}, undefined, false, undefined, this),
|
|
96948
|
-
/* @__PURE__ */
|
|
98217
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96949
98218
|
color: (coord?.queuedCount ?? 0) > 0 ? "yellow" : "gray",
|
|
96950
98219
|
bold: true,
|
|
96951
98220
|
children: coord?.queuedCount ?? 0
|
|
@@ -96956,13 +98225,13 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
96956
98225
|
}, undefined, true, undefined, this)
|
|
96957
98226
|
]
|
|
96958
98227
|
}, undefined, true, undefined, this),
|
|
96959
|
-
activeCount > 1 && /* @__PURE__ */
|
|
98228
|
+
activeCount > 1 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(LabeledBox, {
|
|
96960
98229
|
label: `TASKS${activeCount > 1 ? " Tab/\u2190 \u2192 \xB7 1-9" : ""}`,
|
|
96961
98230
|
borderColor: "gray",
|
|
96962
98231
|
width: termWidth,
|
|
96963
98232
|
paddingX: 1,
|
|
96964
98233
|
flexDirection: "column",
|
|
96965
|
-
children: /* @__PURE__ */
|
|
98234
|
+
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
96966
98235
|
gap: 3,
|
|
96967
98236
|
flexWrap: "wrap",
|
|
96968
98237
|
children: coord?.activeWorkers.map((w, idx) => {
|
|
@@ -96970,10 +98239,10 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
96970
98239
|
const phase = meta3?.phase ?? "working";
|
|
96971
98240
|
const pBadge = priorityBadge(w.issue.priority);
|
|
96972
98241
|
const isFocused = idx === safeFocusedIdx;
|
|
96973
|
-
return /* @__PURE__ */
|
|
98242
|
+
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
96974
98243
|
gap: 1,
|
|
96975
98244
|
children: [
|
|
96976
|
-
/* @__PURE__ */
|
|
98245
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96977
98246
|
color: isFocused ? "white" : "gray",
|
|
96978
98247
|
bold: isFocused,
|
|
96979
98248
|
children: [
|
|
@@ -96982,7 +98251,7 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
96982
98251
|
"]"
|
|
96983
98252
|
]
|
|
96984
98253
|
}, undefined, true, undefined, this),
|
|
96985
|
-
pBadge.label && /* @__PURE__ */
|
|
98254
|
+
pBadge.label && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96986
98255
|
color: pBadge.color,
|
|
96987
98256
|
children: [
|
|
96988
98257
|
pBadge.text,
|
|
@@ -96990,17 +98259,17 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
96990
98259
|
pBadge.label
|
|
96991
98260
|
]
|
|
96992
98261
|
}, undefined, true, undefined, this),
|
|
96993
|
-
/* @__PURE__ */
|
|
98262
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Link, {
|
|
96994
98263
|
url: w.issue.url,
|
|
96995
98264
|
label: w.issueIdentifier,
|
|
96996
98265
|
color: isFocused ? "cyan" : "gray"
|
|
96997
98266
|
}, undefined, false, undefined, this),
|
|
96998
|
-
/* @__PURE__ */
|
|
98267
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
96999
98268
|
color: phaseColor(phase),
|
|
97000
98269
|
dimColor: !isFocused,
|
|
97001
98270
|
children: phase
|
|
97002
98271
|
}, undefined, false, undefined, this),
|
|
97003
|
-
isFocused && /* @__PURE__ */
|
|
98272
|
+
isFocused && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97004
98273
|
color: "white",
|
|
97005
98274
|
children: "\u25C0"
|
|
97006
98275
|
}, undefined, false, undefined, this)
|
|
@@ -97023,6 +98292,7 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
97023
98292
|
const currentTask = meta3?.currentTask ?? null;
|
|
97024
98293
|
const taskProgress = meta3?.taskProgress ?? null;
|
|
97025
98294
|
const openspecPhase = meta3?.openspecPhase ?? null;
|
|
98295
|
+
const subtasks = meta3?.subtasks ?? [];
|
|
97026
98296
|
const pBadge = priorityBadge(w.issue.priority);
|
|
97027
98297
|
const mBadge = modeBadge(w.mode);
|
|
97028
98298
|
const pColor = phaseColor(phase);
|
|
@@ -97030,33 +98300,33 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
97030
98300
|
const visibleTailLines = isFocused ? focusedTailLines : compactTailLines;
|
|
97031
98301
|
if (!isFocused && activeCount > 1) {
|
|
97032
98302
|
const cardLabelWidth2 = (prUrl ? prLabel(prUrl).length + 3 : 0) + w.issueIdentifier.length + 2;
|
|
97033
|
-
const cardLabelNode2 = /* @__PURE__ */
|
|
98303
|
+
const cardLabelNode2 = /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(jsx_dev_runtime10.Fragment, {
|
|
97034
98304
|
children: [
|
|
97035
|
-
/* @__PURE__ */
|
|
98305
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97036
98306
|
color: "gray",
|
|
97037
98307
|
children: " "
|
|
97038
98308
|
}, undefined, false, undefined, this),
|
|
97039
|
-
prUrl && /* @__PURE__ */
|
|
98309
|
+
prUrl && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Link, {
|
|
97040
98310
|
url: prUrl,
|
|
97041
98311
|
label: prLabel(prUrl),
|
|
97042
98312
|
color: "green"
|
|
97043
98313
|
}, undefined, false, undefined, this),
|
|
97044
|
-
prUrl && /* @__PURE__ */
|
|
98314
|
+
prUrl && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97045
98315
|
color: "gray",
|
|
97046
98316
|
children: " \xB7 "
|
|
97047
98317
|
}, undefined, false, undefined, this),
|
|
97048
|
-
/* @__PURE__ */
|
|
98318
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Link, {
|
|
97049
98319
|
url: w.issue.url,
|
|
97050
98320
|
label: w.issueIdentifier,
|
|
97051
98321
|
color: "cyan"
|
|
97052
98322
|
}, undefined, false, undefined, this),
|
|
97053
|
-
/* @__PURE__ */
|
|
98323
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97054
98324
|
color: "gray",
|
|
97055
98325
|
children: " "
|
|
97056
98326
|
}, undefined, false, undefined, this)
|
|
97057
98327
|
]
|
|
97058
98328
|
}, undefined, true, undefined, this);
|
|
97059
|
-
return /* @__PURE__ */
|
|
98329
|
+
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(LabeledBox, {
|
|
97060
98330
|
labelNode: cardLabelNode2,
|
|
97061
98331
|
labelVisualWidth: cardLabelWidth2,
|
|
97062
98332
|
borderColor: "gray",
|
|
@@ -97064,7 +98334,7 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
97064
98334
|
gap: 2,
|
|
97065
98335
|
width: termWidth,
|
|
97066
98336
|
children: [
|
|
97067
|
-
/* @__PURE__ */
|
|
98337
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97068
98338
|
dimColor: true,
|
|
97069
98339
|
children: [
|
|
97070
98340
|
"[",
|
|
@@ -97072,54 +98342,54 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
97072
98342
|
"]"
|
|
97073
98343
|
]
|
|
97074
98344
|
}, undefined, true, undefined, this),
|
|
97075
|
-
pBadge.label && /* @__PURE__ */
|
|
98345
|
+
pBadge.label && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97076
98346
|
color: pBadge.color,
|
|
97077
98347
|
children: pBadge.text
|
|
97078
98348
|
}, undefined, false, undefined, this),
|
|
97079
|
-
/* @__PURE__ */
|
|
98349
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97080
98350
|
color: "gray",
|
|
97081
98351
|
bold: true,
|
|
97082
98352
|
children: w.issueIdentifier
|
|
97083
98353
|
}, undefined, false, undefined, this),
|
|
97084
|
-
/* @__PURE__ */
|
|
98354
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97085
98355
|
dimColor: true,
|
|
97086
98356
|
children: trunc(w.issue.title, 40)
|
|
97087
98357
|
}, undefined, false, undefined, this),
|
|
97088
|
-
/* @__PURE__ */
|
|
98358
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97089
98359
|
dimColor: true,
|
|
97090
98360
|
children: "\u2502"
|
|
97091
98361
|
}, undefined, false, undefined, this),
|
|
97092
|
-
/* @__PURE__ */
|
|
98362
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97093
98363
|
color: pColor,
|
|
97094
98364
|
dimColor: true,
|
|
97095
98365
|
children: phase
|
|
97096
98366
|
}, undefined, false, undefined, this),
|
|
97097
|
-
/* @__PURE__ */
|
|
98367
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97098
98368
|
dimColor: true,
|
|
97099
98369
|
children: "\u2502"
|
|
97100
98370
|
}, undefined, false, undefined, this),
|
|
97101
|
-
/* @__PURE__ */
|
|
98371
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97102
98372
|
dimColor: true,
|
|
97103
98373
|
children: elapsed
|
|
97104
98374
|
}, undefined, false, undefined, this),
|
|
97105
|
-
/* @__PURE__ */
|
|
98375
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97106
98376
|
dimColor: true,
|
|
97107
98377
|
children: "\xB7"
|
|
97108
98378
|
}, undefined, false, undefined, this),
|
|
97109
|
-
/* @__PURE__ */
|
|
98379
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97110
98380
|
dimColor: true,
|
|
97111
98381
|
children: [
|
|
97112
98382
|
"iter ",
|
|
97113
98383
|
iter
|
|
97114
98384
|
]
|
|
97115
98385
|
}, undefined, true, undefined, this),
|
|
97116
|
-
currentTask && /* @__PURE__ */
|
|
98386
|
+
currentTask && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(jsx_dev_runtime10.Fragment, {
|
|
97117
98387
|
children: [
|
|
97118
|
-
/* @__PURE__ */
|
|
98388
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97119
98389
|
dimColor: true,
|
|
97120
98390
|
children: "\u2502"
|
|
97121
98391
|
}, undefined, false, undefined, this),
|
|
97122
|
-
openspecPhase && /* @__PURE__ */
|
|
98392
|
+
openspecPhase && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97123
98393
|
color: openspecPhaseColor(openspecPhase),
|
|
97124
98394
|
children: [
|
|
97125
98395
|
"[",
|
|
@@ -97127,7 +98397,7 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
97127
98397
|
"]"
|
|
97128
98398
|
]
|
|
97129
98399
|
}, undefined, true, undefined, this),
|
|
97130
|
-
/* @__PURE__ */
|
|
98400
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97131
98401
|
dimColor: true,
|
|
97132
98402
|
children: [
|
|
97133
98403
|
"\u25B6 ",
|
|
@@ -97140,33 +98410,33 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
97140
98410
|
}, w.changeName, true, undefined, this);
|
|
97141
98411
|
}
|
|
97142
98412
|
const cardLabelWidth = (prUrl ? prLabel(prUrl).length + 3 : 0) + w.issueIdentifier.length + 2;
|
|
97143
|
-
const cardLabelNode = /* @__PURE__ */
|
|
98413
|
+
const cardLabelNode = /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(jsx_dev_runtime10.Fragment, {
|
|
97144
98414
|
children: [
|
|
97145
|
-
/* @__PURE__ */
|
|
98415
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97146
98416
|
color: bColor,
|
|
97147
98417
|
children: " "
|
|
97148
98418
|
}, undefined, false, undefined, this),
|
|
97149
|
-
prUrl && /* @__PURE__ */
|
|
98419
|
+
prUrl && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Link, {
|
|
97150
98420
|
url: prUrl,
|
|
97151
98421
|
label: prLabel(prUrl),
|
|
97152
98422
|
color: "green"
|
|
97153
98423
|
}, undefined, false, undefined, this),
|
|
97154
|
-
prUrl && /* @__PURE__ */
|
|
98424
|
+
prUrl && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97155
98425
|
color: bColor,
|
|
97156
98426
|
children: " \xB7 "
|
|
97157
98427
|
}, undefined, false, undefined, this),
|
|
97158
|
-
/* @__PURE__ */
|
|
98428
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Link, {
|
|
97159
98429
|
url: w.issue.url,
|
|
97160
98430
|
label: w.issueIdentifier,
|
|
97161
98431
|
color: "cyan"
|
|
97162
98432
|
}, undefined, false, undefined, this),
|
|
97163
|
-
/* @__PURE__ */
|
|
98433
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97164
98434
|
color: bColor,
|
|
97165
98435
|
children: " "
|
|
97166
98436
|
}, undefined, false, undefined, this)
|
|
97167
98437
|
]
|
|
97168
98438
|
}, undefined, true, undefined, this);
|
|
97169
|
-
return /* @__PURE__ */
|
|
98439
|
+
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(LabeledBox, {
|
|
97170
98440
|
labelNode: cardLabelNode,
|
|
97171
98441
|
labelVisualWidth: cardLabelWidth,
|
|
97172
98442
|
borderColor: bColor,
|
|
@@ -97174,18 +98444,18 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
97174
98444
|
paddingX: 1,
|
|
97175
98445
|
width: termWidth,
|
|
97176
98446
|
children: [
|
|
97177
|
-
/* @__PURE__ */
|
|
98447
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
97178
98448
|
gap: 2,
|
|
97179
98449
|
children: [
|
|
97180
|
-
/* @__PURE__ */
|
|
98450
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97181
98451
|
children: spinnerFrame
|
|
97182
98452
|
}, undefined, false, undefined, this),
|
|
97183
|
-
/* @__PURE__ */
|
|
98453
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97184
98454
|
color: "white",
|
|
97185
98455
|
bold: true,
|
|
97186
98456
|
children: trunc(w.issue.title, Math.max(20, termWidth - 55))
|
|
97187
98457
|
}, undefined, false, undefined, this),
|
|
97188
|
-
/* @__PURE__ */
|
|
98458
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97189
98459
|
color: mBadge.color,
|
|
97190
98460
|
bold: true,
|
|
97191
98461
|
children: [
|
|
@@ -97194,7 +98464,7 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
97194
98464
|
"]"
|
|
97195
98465
|
]
|
|
97196
98466
|
}, undefined, true, undefined, this),
|
|
97197
|
-
/* @__PURE__ */
|
|
98467
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97198
98468
|
color: pColor,
|
|
97199
98469
|
bold: true,
|
|
97200
98470
|
children: [
|
|
@@ -97202,79 +98472,39 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
97202
98472
|
phaseDetail ? ` (${phaseDetail})` : ""
|
|
97203
98473
|
]
|
|
97204
98474
|
}, undefined, true, undefined, this),
|
|
97205
|
-
/* @__PURE__ */
|
|
98475
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97206
98476
|
dimColor: true,
|
|
97207
98477
|
children: "\u2502"
|
|
97208
98478
|
}, undefined, false, undefined, this),
|
|
97209
|
-
/* @__PURE__ */
|
|
98479
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97210
98480
|
color: "white",
|
|
97211
98481
|
children: elapsed
|
|
97212
98482
|
}, undefined, false, undefined, this),
|
|
97213
|
-
/* @__PURE__ */
|
|
98483
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97214
98484
|
dimColor: true,
|
|
97215
98485
|
children: "\u2502"
|
|
97216
98486
|
}, undefined, false, undefined, this),
|
|
97217
|
-
/* @__PURE__ */
|
|
98487
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97218
98488
|
dimColor: true,
|
|
97219
98489
|
children: "\u21BA"
|
|
97220
98490
|
}, undefined, false, undefined, this),
|
|
97221
|
-
/* @__PURE__ */
|
|
98491
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97222
98492
|
color: "white",
|
|
97223
98493
|
bold: true,
|
|
97224
98494
|
children: iter
|
|
97225
98495
|
}, undefined, false, undefined, this)
|
|
97226
98496
|
]
|
|
97227
98497
|
}, undefined, true, undefined, this),
|
|
97228
|
-
|
|
97229
|
-
const bar = calcProgressBar(taskProgress.checked, taskProgress.total, termWidth - 4);
|
|
97230
|
-
if (!bar)
|
|
97231
|
-
return null;
|
|
97232
|
-
const { countStr, filledLeft, leftSlot, filledRight, rightSlot } = bar;
|
|
97233
|
-
return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
97234
|
-
marginTop: 0,
|
|
97235
|
-
children: [
|
|
97236
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
97237
|
-
dimColor: true,
|
|
97238
|
-
children: "["
|
|
97239
|
-
}, undefined, false, undefined, this),
|
|
97240
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
97241
|
-
color: "green",
|
|
97242
|
-
children: "\u2588".repeat(filledLeft)
|
|
97243
|
-
}, undefined, false, undefined, this),
|
|
97244
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
97245
|
-
dimColor: true,
|
|
97246
|
-
children: "\u2591".repeat(leftSlot - filledLeft)
|
|
97247
|
-
}, undefined, false, undefined, this),
|
|
97248
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
97249
|
-
color: "white",
|
|
97250
|
-
bold: true,
|
|
97251
|
-
children: countStr
|
|
97252
|
-
}, undefined, false, undefined, this),
|
|
97253
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
97254
|
-
color: "green",
|
|
97255
|
-
children: "\u2588".repeat(filledRight)
|
|
97256
|
-
}, undefined, false, undefined, this),
|
|
97257
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
97258
|
-
dimColor: true,
|
|
97259
|
-
children: "\u2591".repeat(rightSlot - filledRight)
|
|
97260
|
-
}, undefined, false, undefined, this),
|
|
97261
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
97262
|
-
dimColor: true,
|
|
97263
|
-
children: "]"
|
|
97264
|
-
}, undefined, false, undefined, this)
|
|
97265
|
-
]
|
|
97266
|
-
}, undefined, true, undefined, this);
|
|
97267
|
-
})(),
|
|
97268
|
-
currentTask && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
98498
|
+
currentTask && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
97269
98499
|
gap: 1,
|
|
97270
98500
|
marginTop: 0,
|
|
97271
98501
|
children: [
|
|
97272
|
-
/* @__PURE__ */
|
|
98502
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97273
98503
|
color: "yellow",
|
|
97274
98504
|
bold: true,
|
|
97275
98505
|
children: "\u25B6 TASK"
|
|
97276
98506
|
}, undefined, false, undefined, this),
|
|
97277
|
-
openspecPhase && /* @__PURE__ */
|
|
98507
|
+
openspecPhase && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97278
98508
|
color: openspecPhaseColor(openspecPhase),
|
|
97279
98509
|
bold: true,
|
|
97280
98510
|
children: [
|
|
@@ -97283,42 +98513,42 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
97283
98513
|
"]"
|
|
97284
98514
|
]
|
|
97285
98515
|
}, undefined, true, undefined, this),
|
|
97286
|
-
/* @__PURE__ */
|
|
98516
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97287
98517
|
color: "white",
|
|
97288
98518
|
children: trunc(currentTask, termWidth - 14 - (openspecPhase ? openspecPhase.length + 11 : 0))
|
|
97289
98519
|
}, undefined, false, undefined, this)
|
|
97290
98520
|
]
|
|
97291
98521
|
}, undefined, true, undefined, this),
|
|
97292
|
-
cmd && /* @__PURE__ */
|
|
98522
|
+
cmd && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
97293
98523
|
gap: 1,
|
|
97294
98524
|
marginTop: 0,
|
|
97295
98525
|
children: [
|
|
97296
|
-
/* @__PURE__ */
|
|
98526
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97297
98527
|
color: "yellow",
|
|
97298
98528
|
children: "\u23F5 CMD"
|
|
97299
98529
|
}, undefined, false, undefined, this),
|
|
97300
|
-
/* @__PURE__ */
|
|
98530
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97301
98531
|
color: "yellow",
|
|
97302
98532
|
children: fmtCmd(cmd.argv)
|
|
97303
98533
|
}, undefined, false, undefined, this),
|
|
97304
|
-
/* @__PURE__ */
|
|
98534
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97305
98535
|
dimColor: true,
|
|
97306
98536
|
children: cmdElapsed
|
|
97307
98537
|
}, undefined, false, undefined, this)
|
|
97308
98538
|
]
|
|
97309
98539
|
}, undefined, true, undefined, this),
|
|
97310
|
-
tail2.length > 0 && /* @__PURE__ */
|
|
98540
|
+
tail2.length > 0 && !(showPendingTasks && showAllSubtasks) && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
97311
98541
|
flexDirection: "column",
|
|
97312
98542
|
marginTop: 0,
|
|
97313
98543
|
children: [
|
|
97314
|
-
/* @__PURE__ */
|
|
98544
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97315
98545
|
dimColor: true,
|
|
97316
98546
|
children: [
|
|
97317
98547
|
"\u2500 OUTPUT ",
|
|
97318
98548
|
"\u2500".repeat(Math.max(4, termWidth - 14))
|
|
97319
98549
|
]
|
|
97320
98550
|
}, undefined, true, undefined, this),
|
|
97321
|
-
tail2.slice(-visibleTailLines).map((line, i) => /* @__PURE__ */
|
|
98551
|
+
tail2.slice(-visibleTailLines).map((line, i) => /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
97322
98552
|
dimColor: true,
|
|
97323
98553
|
children: [
|
|
97324
98554
|
"\u2502 ",
|
|
@@ -97326,24 +98556,185 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
97326
98556
|
]
|
|
97327
98557
|
}, `${w.changeName}-tail-${i}`, true, undefined, this))
|
|
97328
98558
|
]
|
|
97329
|
-
}, undefined, true, undefined, this)
|
|
98559
|
+
}, undefined, true, undefined, this),
|
|
98560
|
+
shouldShowPhasePipeline(openspecPhase) && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
98561
|
+
marginTop: 0,
|
|
98562
|
+
children: phasePipeline(openspecPhase).map((seg, i, arr) => {
|
|
98563
|
+
const glyph = seg.status === "done" ? "\u2713" : seg.status === "current" ? "\u25CF" : "\u25CB";
|
|
98564
|
+
const node2 = seg.status === "done" ? /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98565
|
+
color: "green",
|
|
98566
|
+
children: [
|
|
98567
|
+
glyph,
|
|
98568
|
+
" ",
|
|
98569
|
+
seg.label
|
|
98570
|
+
]
|
|
98571
|
+
}, undefined, true, undefined, this) : seg.status === "current" ? /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98572
|
+
color: openspecPhaseColor(seg.phase),
|
|
98573
|
+
bold: true,
|
|
98574
|
+
children: [
|
|
98575
|
+
glyph,
|
|
98576
|
+
" ",
|
|
98577
|
+
seg.label
|
|
98578
|
+
]
|
|
98579
|
+
}, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98580
|
+
dimColor: true,
|
|
98581
|
+
children: [
|
|
98582
|
+
glyph,
|
|
98583
|
+
" ",
|
|
98584
|
+
seg.label
|
|
98585
|
+
]
|
|
98586
|
+
}, undefined, true, undefined, this);
|
|
98587
|
+
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
98588
|
+
children: [
|
|
98589
|
+
node2,
|
|
98590
|
+
i < arr.length - 1 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98591
|
+
dimColor: true,
|
|
98592
|
+
children: " \u2500 "
|
|
98593
|
+
}, undefined, false, undefined, this)
|
|
98594
|
+
]
|
|
98595
|
+
}, seg.phase, true, undefined, this);
|
|
98596
|
+
})
|
|
98597
|
+
}, undefined, false, undefined, this),
|
|
98598
|
+
shouldShowSubtasksPanel(openspecPhase, showPendingTasks, subtasks.length > 0) && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
98599
|
+
flexDirection: "column",
|
|
98600
|
+
marginTop: 0,
|
|
98601
|
+
children: [
|
|
98602
|
+
(() => {
|
|
98603
|
+
const header = `\u2500 SUBTASKS (${subtasks.length}) CTRL+T to close `;
|
|
98604
|
+
const pad2 = "\u2500".repeat(Math.max(4, termWidth - header.length - 4));
|
|
98605
|
+
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98606
|
+
dimColor: true,
|
|
98607
|
+
children: `${header}${pad2}`
|
|
98608
|
+
}, undefined, false, undefined, this);
|
|
98609
|
+
})(),
|
|
98610
|
+
(showAllSubtasks ? subtasks : orderSubtasksForCappedDisplay(subtasks).slice(0, MAX_PENDING_DISPLAY)).map((s, i, arr) => {
|
|
98611
|
+
const ord = `${i + 1}.`.padStart(`${arr.length}.`.length, " ");
|
|
98612
|
+
const reserved = ord.length + 5;
|
|
98613
|
+
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98614
|
+
children: [
|
|
98615
|
+
s.done ? /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98616
|
+
dimColor: true,
|
|
98617
|
+
children: `${ord} [x] `
|
|
98618
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98619
|
+
children: `${ord} [ ] `
|
|
98620
|
+
}, undefined, false, undefined, this),
|
|
98621
|
+
s.done ? /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98622
|
+
dimColor: true,
|
|
98623
|
+
children: trunc(s.text, termWidth - reserved)
|
|
98624
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98625
|
+
children: trunc(s.text, termWidth - reserved)
|
|
98626
|
+
}, undefined, false, undefined, this)
|
|
98627
|
+
]
|
|
98628
|
+
}, `${w.changeName}-subtask-${i}`, true, undefined, this);
|
|
98629
|
+
}),
|
|
98630
|
+
!showAllSubtasks && subtasks.length > MAX_PENDING_DISPLAY && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98631
|
+
dimColor: true,
|
|
98632
|
+
children: ` \u2026 +${subtasks.length - MAX_PENDING_DISPLAY} more (CTRL+ALT+T to expand)`
|
|
98633
|
+
}, undefined, false, undefined, this)
|
|
98634
|
+
]
|
|
98635
|
+
}, undefined, true, undefined, this),
|
|
98636
|
+
steeringActive && idx === safeFocusedIdx && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
98637
|
+
marginTop: 0,
|
|
98638
|
+
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(SteeringField, {
|
|
98639
|
+
active: steeringActive,
|
|
98640
|
+
width: termWidth - 2,
|
|
98641
|
+
initialBuffer: steeringBufferRef.current,
|
|
98642
|
+
initialCursor: steeringCursorRef.current,
|
|
98643
|
+
initialFocused: steeringFocusedInitRef.current,
|
|
98644
|
+
onFocusChange: (f2) => {
|
|
98645
|
+
steeringFocusedRef.current = f2;
|
|
98646
|
+
steeringFocusedInitRef.current = f2;
|
|
98647
|
+
},
|
|
98648
|
+
onStateChange: (s) => {
|
|
98649
|
+
steeringBufferRef.current = s.buffer;
|
|
98650
|
+
steeringCursorRef.current = s.cursor;
|
|
98651
|
+
},
|
|
98652
|
+
onSubmit: async (message) => {
|
|
98653
|
+
try {
|
|
98654
|
+
await appendSteering(join22(tasksDir, w.changeName), message);
|
|
98655
|
+
} catch (err) {
|
|
98656
|
+
appendLog(`! steering append failed for ${w.changeName}: ${err.message}`, "red");
|
|
98657
|
+
throw err;
|
|
98658
|
+
}
|
|
98659
|
+
const restarted = await coordRef.current?.restartWorker(w.changeName);
|
|
98660
|
+
if (restarted) {
|
|
98661
|
+
appendLog(` ${w.changeName}: steering applied, restarting worker`, "cyan");
|
|
98662
|
+
} else {
|
|
98663
|
+
appendLog(` ${w.changeName}: steering queued \u2014 will apply on next iteration`, "gray");
|
|
98664
|
+
}
|
|
98665
|
+
}
|
|
98666
|
+
}, undefined, false, undefined, this)
|
|
98667
|
+
}, undefined, false, undefined, this),
|
|
98668
|
+
shouldShowProgressBar(openspecPhase, showPendingTasks, taskProgress !== null) && taskProgress && (() => {
|
|
98669
|
+
const hint = " CTRL+T to open";
|
|
98670
|
+
const bar = calcProgressBar(taskProgress.checked, taskProgress.total, termWidth - 4 - hint.length);
|
|
98671
|
+
if (!bar)
|
|
98672
|
+
return null;
|
|
98673
|
+
const { countStr, filledLeft, leftSlot, filledRight, rightSlot } = bar;
|
|
98674
|
+
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
98675
|
+
marginTop: 0,
|
|
98676
|
+
children: [
|
|
98677
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98678
|
+
dimColor: true,
|
|
98679
|
+
children: "["
|
|
98680
|
+
}, undefined, false, undefined, this),
|
|
98681
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98682
|
+
color: "green",
|
|
98683
|
+
children: "\u2588".repeat(filledLeft)
|
|
98684
|
+
}, undefined, false, undefined, this),
|
|
98685
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98686
|
+
dimColor: true,
|
|
98687
|
+
children: "\u2591".repeat(leftSlot - filledLeft)
|
|
98688
|
+
}, undefined, false, undefined, this),
|
|
98689
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98690
|
+
color: "white",
|
|
98691
|
+
bold: true,
|
|
98692
|
+
children: countStr
|
|
98693
|
+
}, undefined, false, undefined, this),
|
|
98694
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98695
|
+
color: "green",
|
|
98696
|
+
children: "\u2588".repeat(filledRight)
|
|
98697
|
+
}, undefined, false, undefined, this),
|
|
98698
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98699
|
+
dimColor: true,
|
|
98700
|
+
children: "\u2591".repeat(rightSlot - filledRight)
|
|
98701
|
+
}, undefined, false, undefined, this),
|
|
98702
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98703
|
+
dimColor: true,
|
|
98704
|
+
children: "]"
|
|
98705
|
+
}, undefined, false, undefined, this),
|
|
98706
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
98707
|
+
dimColor: true,
|
|
98708
|
+
children: hint
|
|
98709
|
+
}, undefined, false, undefined, this)
|
|
98710
|
+
]
|
|
98711
|
+
}, undefined, true, undefined, this);
|
|
98712
|
+
})()
|
|
97330
98713
|
]
|
|
97331
98714
|
}, w.changeName, true, undefined, this);
|
|
97332
98715
|
})
|
|
97333
98716
|
]
|
|
97334
98717
|
}, undefined, true, undefined, this)
|
|
97335
98718
|
]
|
|
97336
|
-
},
|
|
98719
|
+
}, resizeKey, true, undefined, this);
|
|
97337
98720
|
}
|
|
97338
|
-
var
|
|
98721
|
+
var import_react61, jsx_dev_runtime10, lineCounter = 0, TAIL_BUFFER_SIZE = 30, CMD_DISPLAY_MAX = 80, MAX_PENDING_DISPLAY = 15, SPINNER_FRAMES, HYPERLINKS_SUPPORTED, ANSI_STRIP_RE, BOX_ONLY_RE, STATUS_BAR_LINE_RE, ITER_HEADER_LINE_RE, SESSION_START;
|
|
97339
98722
|
var init_AgentMode = __esm(async () => {
|
|
97340
98723
|
init_cli2();
|
|
97341
98724
|
init_config();
|
|
97342
98725
|
init_wire();
|
|
98726
|
+
init_tasks_md();
|
|
98727
|
+
init_phase();
|
|
97343
98728
|
init_log();
|
|
97344
|
-
|
|
97345
|
-
|
|
97346
|
-
|
|
98729
|
+
init_useTerminalSize2();
|
|
98730
|
+
init_loop();
|
|
98731
|
+
init_context();
|
|
98732
|
+
await __promiseAll([
|
|
98733
|
+
init_build2(),
|
|
98734
|
+
init_SteeringField()
|
|
98735
|
+
]);
|
|
98736
|
+
import_react61 = __toESM(require_react(), 1);
|
|
98737
|
+
jsx_dev_runtime10 = __toESM(require_jsx_dev_runtime(), 1);
|
|
97347
98738
|
SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
97348
98739
|
HYPERLINKS_SUPPORTED = !process.env["TMUX"];
|
|
97349
98740
|
ANSI_STRIP_RE = /\x1b(?:\[[0-9;]*[A-Za-z]|\][^\x07\x1b]*(?:\x07|\x1b\\)|.)/g;
|
|
@@ -97353,6 +98744,112 @@ var init_AgentMode = __esm(async () => {
|
|
|
97353
98744
|
SESSION_START = new Date().toISOString();
|
|
97354
98745
|
});
|
|
97355
98746
|
|
|
98747
|
+
// apps/agent/src/pr-status.ts
|
|
98748
|
+
function bucketChecks(rollup, prState) {
|
|
98749
|
+
if (rollup === null || rollup === undefined || rollup.length === 0) {
|
|
98750
|
+
return prState === "MERGED" ? "pass" : "pending";
|
|
98751
|
+
}
|
|
98752
|
+
let anyPending = false;
|
|
98753
|
+
let anyFail = false;
|
|
98754
|
+
for (const c of rollup) {
|
|
98755
|
+
const status = (c.status ?? "").toUpperCase();
|
|
98756
|
+
const conclusion = (c.conclusion ?? "").toUpperCase();
|
|
98757
|
+
const state = (c.state ?? "").toUpperCase();
|
|
98758
|
+
if (status && status !== "COMPLETED") {
|
|
98759
|
+
anyPending = true;
|
|
98760
|
+
continue;
|
|
98761
|
+
}
|
|
98762
|
+
if (state === "PENDING" || state === "EXPECTED") {
|
|
98763
|
+
anyPending = true;
|
|
98764
|
+
continue;
|
|
98765
|
+
}
|
|
98766
|
+
const settled = conclusion || state;
|
|
98767
|
+
if (settled === "FAILURE" || settled === "TIMED_OUT" || settled === "CANCELLED" || settled === "ERROR") {
|
|
98768
|
+
anyFail = true;
|
|
98769
|
+
}
|
|
98770
|
+
}
|
|
98771
|
+
if (anyPending)
|
|
98772
|
+
return "pending";
|
|
98773
|
+
if (anyFail)
|
|
98774
|
+
return "fail";
|
|
98775
|
+
return "pass";
|
|
98776
|
+
}
|
|
98777
|
+
async function fetchPrStatus(url2, runner, cwd2) {
|
|
98778
|
+
let stdout;
|
|
98779
|
+
try {
|
|
98780
|
+
const out = await runner.run(["gh", "pr", "view", url2, "--json", PR_VIEW_FIELDS], cwd2);
|
|
98781
|
+
stdout = out.stdout;
|
|
98782
|
+
} catch (err) {
|
|
98783
|
+
const e = err;
|
|
98784
|
+
const msg = (e.stderr?.trim().split(`
|
|
98785
|
+
`)[0] ?? e.message ?? "gh failed").slice(0, 200);
|
|
98786
|
+
return { kind: "error", message: msg };
|
|
98787
|
+
}
|
|
98788
|
+
let raw;
|
|
98789
|
+
try {
|
|
98790
|
+
raw = JSON.parse(stdout || "{}");
|
|
98791
|
+
} catch (err) {
|
|
98792
|
+
return { kind: "error", message: `parse error: ${err.message}` };
|
|
98793
|
+
}
|
|
98794
|
+
const stateUpper = (raw.state ?? "").toUpperCase();
|
|
98795
|
+
const state = stateUpper === "OPEN" || stateUpper === "CLOSED" || stateUpper === "MERGED" ? stateUpper : "OPEN";
|
|
98796
|
+
const mergeableUpper = (raw.mergeable ?? "UNKNOWN").toUpperCase();
|
|
98797
|
+
const mergeable = mergeableUpper === "MERGEABLE" || mergeableUpper === "CONFLICTING" ? mergeableUpper : "UNKNOWN";
|
|
98798
|
+
return {
|
|
98799
|
+
kind: "ok",
|
|
98800
|
+
state,
|
|
98801
|
+
isDraft: Boolean(raw.isDraft),
|
|
98802
|
+
mergeable,
|
|
98803
|
+
ciBucket: bucketChecks(raw.statusCheckRollup, state),
|
|
98804
|
+
autoMergeEnabled: raw.autoMergeRequest !== null && raw.autoMergeRequest !== undefined,
|
|
98805
|
+
createdAt: raw.createdAt ?? ""
|
|
98806
|
+
};
|
|
98807
|
+
}
|
|
98808
|
+
var PR_VIEW_FIELDS = "state,isDraft,mergeable,statusCheckRollup,autoMergeRequest,createdAt";
|
|
98809
|
+
|
|
98810
|
+
// apps/agent/src/list-sort.ts
|
|
98811
|
+
function assignTier(status) {
|
|
98812
|
+
if (status === null || status.kind === "error")
|
|
98813
|
+
return 5;
|
|
98814
|
+
const conflict = status.mergeable === "CONFLICTING";
|
|
98815
|
+
const failing = status.ciBucket === "fail";
|
|
98816
|
+
if (conflict && status.autoMergeEnabled)
|
|
98817
|
+
return 1;
|
|
98818
|
+
if (failing && status.autoMergeEnabled)
|
|
98819
|
+
return 2;
|
|
98820
|
+
if (conflict)
|
|
98821
|
+
return 3;
|
|
98822
|
+
if (failing)
|
|
98823
|
+
return 4;
|
|
98824
|
+
return 5;
|
|
98825
|
+
}
|
|
98826
|
+
function createdAtOf(status) {
|
|
98827
|
+
if (status && status.kind === "ok")
|
|
98828
|
+
return status.createdAt;
|
|
98829
|
+
return "";
|
|
98830
|
+
}
|
|
98831
|
+
function sortRows(rows) {
|
|
98832
|
+
const cmp = chain((a, b) => assignTier(a.status) - assignTier(b.status), (a, b) => {
|
|
98833
|
+
const ia = a.issueCreatedAt;
|
|
98834
|
+
const ib = b.issueCreatedAt;
|
|
98835
|
+
if (ia === ib)
|
|
98836
|
+
return 0;
|
|
98837
|
+
if (ia === "")
|
|
98838
|
+
return 1;
|
|
98839
|
+
if (ib === "")
|
|
98840
|
+
return -1;
|
|
98841
|
+
return ia < ib ? -1 : 1;
|
|
98842
|
+
}, (a, b) => {
|
|
98843
|
+
const ca = createdAtOf(a.status);
|
|
98844
|
+
const cb = createdAtOf(b.status);
|
|
98845
|
+
if (ca === cb)
|
|
98846
|
+
return 0;
|
|
98847
|
+
return ca < cb ? -1 : 1;
|
|
98848
|
+
}, (a, b) => a.bucketOrder - b.bucketOrder, (a, b) => a.identifier.localeCompare(b.identifier));
|
|
98849
|
+
return [...rows].sort(cmp);
|
|
98850
|
+
}
|
|
98851
|
+
var init_list_sort = () => {};
|
|
98852
|
+
|
|
97356
98853
|
// apps/agent/src/list.ts
|
|
97357
98854
|
var exports_list = {};
|
|
97358
98855
|
__export(exports_list, {
|
|
@@ -97484,40 +98981,100 @@ async function fetchBucketIssues(apiKey, bucket, team, assignee) {
|
|
|
97484
98981
|
};
|
|
97485
98982
|
return fetchOpenIssues(apiKey, spec);
|
|
97486
98983
|
}
|
|
97487
|
-
|
|
97488
|
-
if (
|
|
97489
|
-
return;
|
|
97490
|
-
|
|
97491
|
-
|
|
97492
|
-
|
|
97493
|
-
|
|
97494
|
-
|
|
97495
|
-
|
|
97496
|
-
|
|
98984
|
+
function formatPrStatusMarker(status) {
|
|
98985
|
+
if (status === null)
|
|
98986
|
+
return "(no PR)";
|
|
98987
|
+
if (status.kind === "error")
|
|
98988
|
+
return "?";
|
|
98989
|
+
if (status.state === "MERGED")
|
|
98990
|
+
return "merged";
|
|
98991
|
+
if (status.state === "CLOSED")
|
|
98992
|
+
return "closed";
|
|
98993
|
+
const parts = [];
|
|
98994
|
+
if (status.mergeable === "CONFLICTING")
|
|
98995
|
+
parts.push("\u2717conflict");
|
|
98996
|
+
if (status.ciBucket === "fail")
|
|
98997
|
+
parts.push("\u2717ci");
|
|
98998
|
+
if (status.ciBucket === "pending")
|
|
98999
|
+
parts.push("\u23F3ci");
|
|
99000
|
+
if (status.isDraft)
|
|
99001
|
+
parts.push("draft");
|
|
99002
|
+
if (status.autoMergeEnabled)
|
|
99003
|
+
parts.push("auto-merge");
|
|
99004
|
+
if (parts.length === 0)
|
|
99005
|
+
return "ok";
|
|
99006
|
+
return parts.join(" ");
|
|
99007
|
+
}
|
|
99008
|
+
async function fetchAndPrintLinear(apiKey, buckets, team, assignee, cwd2, runner) {
|
|
99009
|
+
const bucketResults = await Promise.all(buckets.map(async (bucket) => {
|
|
99010
|
+
if (!bucket.indicator || bucket.indicator.filter.length === 0) {
|
|
99011
|
+
return { bucket, issues: [], error: null };
|
|
99012
|
+
}
|
|
99013
|
+
try {
|
|
99014
|
+
const issues = await fetchBucketIssues(apiKey, bucket, team, assignee);
|
|
99015
|
+
return { bucket, issues, error: null };
|
|
99016
|
+
} catch (err) {
|
|
99017
|
+
return {
|
|
99018
|
+
bucket,
|
|
99019
|
+
issues: [],
|
|
99020
|
+
error: err instanceof Error ? err.message : String(err)
|
|
99021
|
+
};
|
|
99022
|
+
}
|
|
99023
|
+
}));
|
|
99024
|
+
for (const { bucket, error: error48 } of bucketResults) {
|
|
99025
|
+
if (error48) {
|
|
99026
|
+
process.stdout.write(`
|
|
99027
|
+
${bucket.label}: error fetching from Linear \u2014 ${error48}
|
|
97497
99028
|
`);
|
|
97498
|
-
|
|
99029
|
+
}
|
|
97499
99030
|
}
|
|
97500
|
-
const
|
|
99031
|
+
const seen = new Map;
|
|
99032
|
+
let order = 0;
|
|
99033
|
+
for (const { bucket, issues } of bucketResults) {
|
|
99034
|
+
for (const issue2 of issues) {
|
|
99035
|
+
if (seen.has(issue2.id))
|
|
99036
|
+
continue;
|
|
99037
|
+
seen.set(issue2.id, {
|
|
99038
|
+
issueId: issue2.id,
|
|
99039
|
+
identifier: issue2.identifier,
|
|
99040
|
+
status: null,
|
|
99041
|
+
bucketOrder: order++,
|
|
99042
|
+
issueCreatedAt: issue2.createdAt,
|
|
99043
|
+
bucketLabel: bucket.label,
|
|
99044
|
+
stateName: issue2.state.name,
|
|
99045
|
+
title: issue2.title.slice(0, 60),
|
|
99046
|
+
prUrl: null
|
|
99047
|
+
});
|
|
99048
|
+
}
|
|
99049
|
+
}
|
|
99050
|
+
const rows = [...seen.values()];
|
|
99051
|
+
await Promise.all(rows.map(async (row) => {
|
|
99052
|
+
try {
|
|
99053
|
+
const attachments = await fetchIssueAttachments(apiKey, row.issueId);
|
|
99054
|
+
row.prUrl = findPullRequestUrl(attachments);
|
|
99055
|
+
} catch {}
|
|
99056
|
+
}));
|
|
99057
|
+
await Promise.all(rows.map(async (row) => {
|
|
99058
|
+
if (!row.prUrl)
|
|
99059
|
+
return;
|
|
99060
|
+
row.status = await fetchPrStatus(row.prUrl, runner, cwd2);
|
|
99061
|
+
}));
|
|
99062
|
+
const sorted = sortRows(rows);
|
|
97501
99063
|
process.stdout.write(`
|
|
97502
|
-
|
|
99064
|
+
Linear tickets: ${sorted.length} issue(s)
|
|
97503
99065
|
`);
|
|
97504
|
-
if (
|
|
99066
|
+
if (sorted.length === 0)
|
|
97505
99067
|
return;
|
|
97506
|
-
const
|
|
97507
|
-
|
|
97508
|
-
|
|
97509
|
-
|
|
97510
|
-
|
|
97511
|
-
|
|
97512
|
-
|
|
97513
|
-
|
|
97514
|
-
|
|
97515
|
-
|
|
97516
|
-
for (let index = 0;index < issues.length; index += 1) {
|
|
97517
|
-
const issue2 = issues[index];
|
|
97518
|
-
const pr = prUrls[index];
|
|
97519
|
-
const title = issue2.title.slice(0, 60);
|
|
97520
|
-
process.stdout.write(` ${pad2(issue2.identifier, idWidth)} ${pad2(issue2.state.name, stateWidth)} ${pad2(title, 60)} ${pr ?? "(no PR)"}
|
|
99068
|
+
const idWidth = Math.max(10, ...sorted.map((r) => r.identifier.length));
|
|
99069
|
+
const bucketWidth = Math.max(6, ...sorted.map((r) => r.bucketLabel.length));
|
|
99070
|
+
const stateWidth = Math.max(5, ...sorted.map((r) => r.stateName.length));
|
|
99071
|
+
const markers = sorted.map((r) => formatPrStatusMarker(r.status));
|
|
99072
|
+
const markerWidth = Math.max(9, ...markers.map((m) => m.length));
|
|
99073
|
+
process.stdout.write(` ${pad2("Identifier", idWidth)} ${pad2("Bucket", bucketWidth)} ${pad2("State", stateWidth)} ${pad2("Title", 60)} ${pad2("PR Status", markerWidth)} PR URL
|
|
99074
|
+
`);
|
|
99075
|
+
for (let i = 0;i < sorted.length; i += 1) {
|
|
99076
|
+
const r = sorted[i];
|
|
99077
|
+
process.stdout.write(` ${pad2(r.identifier, idWidth)} ${pad2(r.bucketLabel, bucketWidth)} ${pad2(r.stateName, stateWidth)} ${pad2(r.title, 60)} ${pad2(markers[i], markerWidth)} ${r.prUrl ?? "(no PR)"}
|
|
97521
99078
|
`);
|
|
97522
99079
|
}
|
|
97523
99080
|
}
|
|
@@ -97566,18 +99123,14 @@ Linear: LINEAR_API_KEY not set \u2014 cannot fetch tickets. Configured buckets:
|
|
|
97566
99123
|
}
|
|
97567
99124
|
return;
|
|
97568
99125
|
}
|
|
97569
|
-
process.stdout.write(`
|
|
97570
|
-
Linear tickets:
|
|
97571
|
-
`);
|
|
97572
99126
|
if (team)
|
|
97573
|
-
process.stdout.write(`
|
|
99127
|
+
process.stdout.write(`
|
|
99128
|
+
team: ${team}
|
|
97574
99129
|
`);
|
|
97575
99130
|
if (assignee)
|
|
97576
|
-
process.stdout.write(`
|
|
99131
|
+
process.stdout.write(`assignee: ${assignee}
|
|
97577
99132
|
`);
|
|
97578
|
-
|
|
97579
|
-
await printBucket(apiKey, bucket, team, assignee);
|
|
97580
|
-
}
|
|
99133
|
+
await fetchAndPrintLinear(apiKey, buckets, team, assignee, projectRoot, localCmdRunner);
|
|
97581
99134
|
}
|
|
97582
99135
|
function normalizeIdentifier(input) {
|
|
97583
99136
|
const match = input.match(/^([A-Za-z]+)-(\d+)(?:-.*)?$/);
|
|
@@ -97724,12 +99277,27 @@ Per-bucket diagnostics:
|
|
|
97724
99277
|
}
|
|
97725
99278
|
}
|
|
97726
99279
|
}
|
|
97727
|
-
var RALPHY_ATTACHMENT_TITLE2 = "Ralphy";
|
|
99280
|
+
var localCmdRunner, RALPHY_ATTACHMENT_TITLE2 = "Ralphy";
|
|
97728
99281
|
var init_list = __esm(() => {
|
|
97729
99282
|
init_context();
|
|
97730
99283
|
init_types2();
|
|
97731
99284
|
init_worktree();
|
|
97732
99285
|
init_config();
|
|
99286
|
+
init_list_sort();
|
|
99287
|
+
localCmdRunner = {
|
|
99288
|
+
run: async (cmd, cwd2) => {
|
|
99289
|
+
const proc = Bun.spawn({ cmd, cwd: cwd2, stdout: "pipe", stderr: "pipe" });
|
|
99290
|
+
const stdout = await new Response(proc.stdout).text();
|
|
99291
|
+
const stderr = await new Response(proc.stderr).text();
|
|
99292
|
+
const code = await proc.exited;
|
|
99293
|
+
if (code !== 0) {
|
|
99294
|
+
const err = new Error(`\`${cmd.join(" ")}\` exited ${code}`);
|
|
99295
|
+
err.stderr = stderr;
|
|
99296
|
+
throw err;
|
|
99297
|
+
}
|
|
99298
|
+
return { stdout, stderr };
|
|
99299
|
+
}
|
|
99300
|
+
};
|
|
97733
99301
|
});
|
|
97734
99302
|
|
|
97735
99303
|
// apps/agent/src/agent/json-runner.ts
|
|
@@ -97773,7 +99341,7 @@ async function runAgentJson({
|
|
|
97773
99341
|
process.exitCode = 1;
|
|
97774
99342
|
return;
|
|
97775
99343
|
}
|
|
97776
|
-
const { coord, filterDesc, concurrency, pollInterval } = buildAgentCoordinator({
|
|
99344
|
+
const { coord, filterDesc, concurrency, pollInterval, runBaselineGate: runBaselineGate2 } = buildAgentCoordinator({
|
|
97777
99345
|
args,
|
|
97778
99346
|
cfg,
|
|
97779
99347
|
projectRoot,
|
|
@@ -97836,6 +99404,17 @@ async function runAgentJson({
|
|
|
97836
99404
|
if (cancelled)
|
|
97837
99405
|
return;
|
|
97838
99406
|
emit({ type: "poll_start" });
|
|
99407
|
+
try {
|
|
99408
|
+
await runBaselineGate2();
|
|
99409
|
+
} catch (err) {
|
|
99410
|
+
emit({
|
|
99411
|
+
type: "log",
|
|
99412
|
+
text: `baseline gate failed: ${err.message}`,
|
|
99413
|
+
color: "yellow"
|
|
99414
|
+
});
|
|
99415
|
+
}
|
|
99416
|
+
if (cancelled)
|
|
99417
|
+
return;
|
|
97839
99418
|
const { found, added, buckets, prStatus } = await coord.pollOnce();
|
|
97840
99419
|
if (cancelled)
|
|
97841
99420
|
return;
|
|
@@ -97949,12 +99528,12 @@ async function main2(argv) {
|
|
|
97949
99528
|
return typeof process.exitCode === "number" ? process.exitCode : 0;
|
|
97950
99529
|
}
|
|
97951
99530
|
await runWithContext(createDefaultContext(), async () => {
|
|
97952
|
-
const { waitUntilExit } = render_default(
|
|
99531
|
+
const { waitUntilExit } = render_default(import_react62.createElement(AgentMode, { args, projectRoot, statesDir, tasksDir }));
|
|
97953
99532
|
await waitUntilExit();
|
|
97954
99533
|
});
|
|
97955
99534
|
return typeof process.exitCode === "number" ? process.exitCode : 0;
|
|
97956
99535
|
}
|
|
97957
|
-
var
|
|
99536
|
+
var import_react62;
|
|
97958
99537
|
var init_src6 = __esm(async () => {
|
|
97959
99538
|
init_context();
|
|
97960
99539
|
init_layout();
|
|
@@ -97964,7 +99543,7 @@ var init_src6 = __esm(async () => {
|
|
|
97964
99543
|
init_build2(),
|
|
97965
99544
|
init_AgentMode()
|
|
97966
99545
|
]);
|
|
97967
|
-
|
|
99546
|
+
import_react62 = __toESM(require_react(), 1);
|
|
97968
99547
|
});
|
|
97969
99548
|
|
|
97970
99549
|
// apps/shell/src/index.ts
|
|
@@ -98027,7 +99606,12 @@ ${HELP}
|
|
|
98027
99606
|
setDefaultProperties({ subcommand });
|
|
98028
99607
|
capture("command_run", { subcommand });
|
|
98029
99608
|
try {
|
|
98030
|
-
|
|
99609
|
+
const code = await dispatch(subcommand, argv.slice(1));
|
|
99610
|
+
capture("command_exit", { subcommand, exit_code: code });
|
|
99611
|
+
return code;
|
|
99612
|
+
} catch (err) {
|
|
99613
|
+
captureError("command_error", err, { subcommand });
|
|
99614
|
+
throw err;
|
|
98031
99615
|
} finally {
|
|
98032
99616
|
await shutdown();
|
|
98033
99617
|
}
|