@neriros/ralphy 2.16.2 → 2.16.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +41 -70
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -35029,8 +35029,8 @@ import { readFileSync as readFileSync2 } from "fs";
|
|
|
35029
35029
|
import { resolve } from "path";
|
|
35030
35030
|
function getVersion() {
|
|
35031
35031
|
try {
|
|
35032
|
-
if ("2.16.
|
|
35033
|
-
return "2.16.
|
|
35032
|
+
if ("2.16.4")
|
|
35033
|
+
return "2.16.4";
|
|
35034
35034
|
} catch {}
|
|
35035
35035
|
const dirsToTry = [];
|
|
35036
35036
|
try {
|
|
@@ -59481,6 +59481,9 @@ var MarkerSchema, GetIndicatorSchema, SetIndicatorSchema, IndicatorsSchema, Ralp
|
|
|
59481
59481
|
// Seconds between CI status polls.
|
|
59482
59482
|
"ciPollIntervalSeconds": 30,
|
|
59483
59483
|
|
|
59484
|
+
// CI check names to ignore when polling PR status (case-insensitive).
|
|
59485
|
+
// "ignoreCiChecks": ["Vercel", "codeql"],
|
|
59486
|
+
|
|
59484
59487
|
// Underlying engine: "claude" or "codex".
|
|
59485
59488
|
"engine": "claude",
|
|
59486
59489
|
|
|
@@ -59591,6 +59594,7 @@ var init_config = __esm(() => {
|
|
|
59591
59594
|
fixCiOnFailure: exports_external.boolean().default(false),
|
|
59592
59595
|
maxCiFixAttempts: exports_external.number().int().positive().default(5),
|
|
59593
59596
|
ciPollIntervalSeconds: exports_external.number().int().positive().default(30),
|
|
59597
|
+
ignoreCiChecks: exports_external.array(exports_external.string()).default([]),
|
|
59594
59598
|
engine: exports_external.enum(["claude", "codex"]).default("claude"),
|
|
59595
59599
|
model: exports_external.enum(["haiku", "sonnet", "opus"]).default("opus"),
|
|
59596
59600
|
linear: exports_external.object({
|
|
@@ -60450,7 +60454,7 @@ ${e.stdout ?? ""}`;
|
|
|
60450
60454
|
}
|
|
60451
60455
|
throw lastErr;
|
|
60452
60456
|
}
|
|
60453
|
-
async function getPrChecksStatus(prRef, runner, cwd2, onTransientRetry) {
|
|
60457
|
+
async function getPrChecksStatus(prRef, runner, cwd2, onTransientRetry, ignoreCiChecks = []) {
|
|
60454
60458
|
let out;
|
|
60455
60459
|
try {
|
|
60456
60460
|
out = await runGhWithRetry(["gh", "pr", "checks", prRef, "--json", PR_CHECKS_FIELDS], runner, cwd2, onTransientRetry);
|
|
@@ -60463,7 +60467,8 @@ ${e.stdout ?? ""}`;
|
|
|
60463
60467
|
return { bucket: "pass", failedRunIds: [] };
|
|
60464
60468
|
throw err;
|
|
60465
60469
|
}
|
|
60466
|
-
const
|
|
60470
|
+
const ignoredLower = ignoreCiChecks.map((n) => n.toLowerCase());
|
|
60471
|
+
const checks = JSON.parse(out.stdout || "[]").filter((c) => !ignoredLower.includes(c.name.toLowerCase())).filter((c) => c.bucket !== "skipping");
|
|
60467
60472
|
if (checks.some((c) => c.bucket === "pending")) {
|
|
60468
60473
|
return { bucket: "pending", failedRunIds: [] };
|
|
60469
60474
|
}
|
|
@@ -60602,57 +60607,9 @@ ${pe.stderr ?? ""}`;
|
|
|
60602
60607
|
}
|
|
60603
60608
|
}
|
|
60604
60609
|
}
|
|
60605
|
-
async function
|
|
60606
|
-
let hookFixAttempt = 0;
|
|
60607
|
-
while (true) {
|
|
60608
|
-
ctx.emit("committing", "git status");
|
|
60609
|
-
let dirty = "";
|
|
60610
|
-
try {
|
|
60611
|
-
const status = await ctx.cmd.run(["git", "status", "--porcelain"], ctx.cwd);
|
|
60612
|
-
dirty = status.stdout.trim();
|
|
60613
|
-
} catch (err) {
|
|
60614
|
-
ctx.log(`! git status failed for ${ctx.changeName}: ${err.message}`, "yellow");
|
|
60615
|
-
break;
|
|
60616
|
-
}
|
|
60617
|
-
if (!dirty)
|
|
60618
|
-
break;
|
|
60619
|
-
try {
|
|
60620
|
-
ctx.emit("committing", "git add -A");
|
|
60621
|
-
await ctx.cmd.run(["git", "add", "-A"], ctx.cwd);
|
|
60622
|
-
ctx.emit("committing", "git commit");
|
|
60623
|
-
await ctx.cmd.run(["git", "commit", "-m", `chore(ralph): residual changes for ${ctx.changeName}`], ctx.cwd);
|
|
60624
|
-
ctx.log(` committed residual changes for ${ctx.changeName}`, "gray");
|
|
60625
|
-
break;
|
|
60626
|
-
} catch (err) {
|
|
60627
|
-
const e = err;
|
|
60628
|
-
const detail = e.stderr?.trim() || e.message;
|
|
60629
|
-
const combined = `${e.stdout ?? ""}
|
|
60630
|
-
${e.stderr ?? ""}`;
|
|
60631
|
-
if (/nothing to commit/i.test(combined) || /empty git commit/i.test(combined))
|
|
60632
|
-
break;
|
|
60633
|
-
if (hookFixAttempt >= maxAttempts) {
|
|
60634
|
-
ctx.log(`! commit rejected for ${ctx.changeName} after ${hookFixAttempt} hook-fix attempts (host pre-commit hook still failing) \u2014 worktree preserved at ${ctx.cwd}`, "red");
|
|
60635
|
-
ctx.log(` detail: ${detail}`, "red");
|
|
60636
|
-
return { gaveUp: true, hookFixAttempt };
|
|
60637
|
-
}
|
|
60638
|
-
hookFixAttempt += 1;
|
|
60639
|
-
ctx.emit("commit-retry", `${hookFixAttempt}/${maxAttempts}`);
|
|
60640
|
-
ctx.log(`! commit rejected for ${ctx.changeName} \u2014 prepending fix task and re-running loop (attempt ${hookFixAttempt}/${maxAttempts})`, "yellow");
|
|
60641
|
-
ctx.log(` detail: ${detail}`, "yellow");
|
|
60642
|
-
const retryCode = await runWorkerWithFixTask(ctx, "Fix host pre-commit hook rejection", `Committing residual changes was rejected by the host repo's pre-commit hook. ` + `Fix the underlying problem, then the commit will be retried.
|
|
60643
|
-
|
|
60644
|
-
` + combined.trim());
|
|
60645
|
-
if (retryCode !== 0) {
|
|
60646
|
-
ctx.log(`! worker re-run after commit rejection exited code ${retryCode} \u2014 giving up`, "red");
|
|
60647
|
-
return { gaveUp: true, hookFixAttempt };
|
|
60648
|
-
}
|
|
60649
|
-
}
|
|
60650
|
-
}
|
|
60651
|
-
return { gaveUp: false, hookFixAttempt };
|
|
60652
|
-
}
|
|
60653
|
-
async function createPrWithRetry(ctx, issue, initialHookFixAttempt) {
|
|
60610
|
+
async function createPrWithRetry(ctx, issue) {
|
|
60654
60611
|
const maxAttempts = ctx.cfg.maxCiFixAttempts;
|
|
60655
|
-
let hookFixAttempt =
|
|
60612
|
+
let hookFixAttempt = 0;
|
|
60656
60613
|
let nonFfRebaseAttempted = false;
|
|
60657
60614
|
let pr = null;
|
|
60658
60615
|
while (true) {
|
|
@@ -60688,12 +60645,16 @@ ${re.stderr ?? ""}`;
|
|
|
60688
60645
|
ctx.emit("rebasing", "conflicts detected \u2014 aborting + queueing fix task");
|
|
60689
60646
|
try {
|
|
60690
60647
|
await ctx.cmd.run(["git", "rebase", "--abort"], ctx.cwd);
|
|
60691
|
-
} catch {
|
|
60648
|
+
} catch (err2) {
|
|
60649
|
+
ctx.log(`! git rebase --abort failed (worktree may already be clean): ${err2.message}`, "yellow");
|
|
60650
|
+
}
|
|
60692
60651
|
let conflictedFiles = "";
|
|
60693
60652
|
try {
|
|
60694
60653
|
const r = await ctx.cmd.run(["git", "diff", "--name-only", `HEAD..origin/${ctx.branch}`], ctx.cwd);
|
|
60695
60654
|
conflictedFiles = r.stdout.trim();
|
|
60696
|
-
} catch {
|
|
60655
|
+
} catch (err2) {
|
|
60656
|
+
ctx.log(`! could not list conflicted files: ${err2.message}`, "yellow");
|
|
60657
|
+
}
|
|
60697
60658
|
if (hookFixAttempt >= maxAttempts) {
|
|
60698
60659
|
ctx.log(`! merge conflict on rebase of ${ctx.branch} after ${hookFixAttempt} attempts \u2014 worktree preserved at ${ctx.cwd}`, "red");
|
|
60699
60660
|
ctx.log(` detail: ${reBlob.trim().split(`
|
|
@@ -60789,7 +60750,7 @@ async function fixConflictsAndCiLoop(ctx, prUrl, wantFixCi, checkPrConflict) {
|
|
|
60789
60750
|
ctx.emit("ci-poll", "starting");
|
|
60790
60751
|
const result2 = await fixCiUntilGreen({
|
|
60791
60752
|
onPhase: (p, d) => ctx.emit(p, d),
|
|
60792
|
-
getStatus: () => getPrChecksStatus(prUrl, ctx.cmd, ctx.cwd, (n, ms, why) => ctx.log(` gh transient (try ${n}) \u2014 retry in ${Math.round(ms / 1000)}s \xB7 ${why}`, "yellow")),
|
|
60753
|
+
getStatus: () => getPrChecksStatus(prUrl, ctx.cmd, ctx.cwd, (n, ms, why) => ctx.log(` gh transient (try ${n}) \u2014 retry in ${Math.round(ms / 1000)}s \xB7 ${why}`, "yellow"), ctx.cfg.ignoreCiChecks),
|
|
60793
60754
|
getFailedLogs: (ids) => fetchFailedRunLogs(ids, ctx.cmd, ctx.cwd),
|
|
60794
60755
|
runTaskWithSteering: (steering) => runWorkerWithFixTask(ctx, "Fix failing CI checks", steering),
|
|
60795
60756
|
pushBranch: async () => {
|
|
@@ -60855,11 +60816,16 @@ async function runPostTask(input, deps) {
|
|
|
60855
60816
|
emit,
|
|
60856
60817
|
respawnWorker
|
|
60857
60818
|
};
|
|
60858
|
-
|
|
60859
|
-
|
|
60860
|
-
|
|
60861
|
-
|
|
60862
|
-
|
|
60819
|
+
try {
|
|
60820
|
+
const status = await cmd.run(["git", "status", "--porcelain"], cwd2);
|
|
60821
|
+
if (status.stdout.trim()) {
|
|
60822
|
+
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.`, "yellow");
|
|
60823
|
+
}
|
|
60824
|
+
} catch (err) {
|
|
60825
|
+
log2(`! git status check failed for ${changeName}: ${err.message}`, "yellow");
|
|
60826
|
+
}
|
|
60827
|
+
{
|
|
60828
|
+
const { pr, gaveUp: prGaveUp } = await createPrWithRetry(ctx, issue);
|
|
60863
60829
|
if (prGaveUp) {
|
|
60864
60830
|
effectiveCode = PR_FAILED_EXIT;
|
|
60865
60831
|
} else if (!pr) {
|
|
@@ -60882,7 +60848,9 @@ async function runPostTask(input, deps) {
|
|
|
60882
60848
|
emit("teardown", cfg.teardownScript);
|
|
60883
60849
|
try {
|
|
60884
60850
|
await runScript("teardown", cfg.teardownScript, cwd2);
|
|
60885
|
-
} catch {
|
|
60851
|
+
} catch (err) {
|
|
60852
|
+
log2(`! teardown script threw: ${err.message}`, "yellow");
|
|
60853
|
+
}
|
|
60886
60854
|
}
|
|
60887
60855
|
if (useWorktree && cwd2 !== projectRoot) {
|
|
60888
60856
|
emit("cleanup", "checking worktree safety");
|
|
@@ -61385,7 +61353,8 @@ PR: ${prUrl}` : ""
|
|
|
61385
61353
|
prBaseBranch: cfg.prBaseBranch,
|
|
61386
61354
|
maxCiFixAttempts: cfg.maxCiFixAttempts,
|
|
61387
61355
|
ciPollIntervalSeconds: cfg.ciPollIntervalSeconds,
|
|
61388
|
-
cleanupWorktreeOnSuccess: cfg.cleanupWorktreeOnSuccess
|
|
61356
|
+
cleanupWorktreeOnSuccess: cfg.cleanupWorktreeOnSuccess,
|
|
61357
|
+
ignoreCiChecks: cfg.ignoreCiChecks
|
|
61389
61358
|
},
|
|
61390
61359
|
respawnWorker: respawn
|
|
61391
61360
|
}, {
|
|
@@ -71880,6 +71849,8 @@ function buildTaskPrompt(state, taskDir) {
|
|
|
71880
71849
|
|
|
71881
71850
|
`;
|
|
71882
71851
|
prompt += `Run \`bunx openspec validate ${state.name}\` before committing.
|
|
71852
|
+
`;
|
|
71853
|
+
prompt += `Commit all changed files yourself before finishing \u2014 stage files individually (e.g. \`git add path/to/file\`), never \`git add -A\` or \`git commit -am\`. Nothing is committed automatically after you exit.
|
|
71883
71854
|
`;
|
|
71884
71855
|
return prompt;
|
|
71885
71856
|
}
|
|
@@ -72551,8 +72522,6 @@ function phaseColor(phase) {
|
|
|
72551
72522
|
return "cyan";
|
|
72552
72523
|
case "scaffolding":
|
|
72553
72524
|
return "magenta";
|
|
72554
|
-
case "committing":
|
|
72555
|
-
case "commit-retry":
|
|
72556
72525
|
case "pushing":
|
|
72557
72526
|
case "push-retry":
|
|
72558
72527
|
case "rebasing":
|
|
@@ -72577,8 +72546,6 @@ function workerBorderColor(phase) {
|
|
|
72577
72546
|
case "working":
|
|
72578
72547
|
case "scaffolding":
|
|
72579
72548
|
return "cyan";
|
|
72580
|
-
case "committing":
|
|
72581
|
-
case "commit-retry":
|
|
72582
72549
|
case "pushing":
|
|
72583
72550
|
case "push-retry":
|
|
72584
72551
|
case "rebasing":
|
|
@@ -72796,7 +72763,9 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
72796
72763
|
const json = await file.json();
|
|
72797
72764
|
meta.iter = json.iteration ?? meta.iter;
|
|
72798
72765
|
}
|
|
72799
|
-
} catch {
|
|
72766
|
+
} catch (err) {
|
|
72767
|
+
console.error(`Failed to read state file for worker '${changeName}' (may not exist yet):`, err);
|
|
72768
|
+
}
|
|
72800
72769
|
if (meta.changeDir) {
|
|
72801
72770
|
try {
|
|
72802
72771
|
const tasksFile = Bun.file(join16(meta.changeDir, "tasks.md"));
|
|
@@ -72805,7 +72774,9 @@ function AgentMode({ args, projectRoot, statesDir, tasksDir }) {
|
|
|
72805
72774
|
const match = text.match(/^- \[ \] (.+)$/m);
|
|
72806
72775
|
meta.currentTask = match?.[1]?.trim() ?? null;
|
|
72807
72776
|
}
|
|
72808
|
-
} catch {
|
|
72777
|
+
} catch (err) {
|
|
72778
|
+
console.error(`Failed to read tasks.md for worker '${changeName}' (may not exist yet):`, err);
|
|
72779
|
+
}
|
|
72809
72780
|
}
|
|
72810
72781
|
}
|
|
72811
72782
|
if (!cancelled)
|