@neriros/ralphy 2.9.1 → 2.9.2
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 +9 -2
- package/dist/cli/index.js +70 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Ralphy
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@neriros/ralphy)
|
|
4
|
+
[](https://www.npmjs.com/package/@neriros/ralphy)
|
|
5
|
+
[](https://github.com/NeriRos/ralphy/blob/main/LICENSE)
|
|
6
|
+
[](https://github.com/NeriRos/ralphy)
|
|
7
|
+
[](https://github.com/NeriRos/ralphy/issues)
|
|
8
|
+
[](https://bun.sh)
|
|
9
|
+
|
|
3
10
|
An iterative AI task execution framework. Ralphy orchestrates multi-phase autonomous work using Claude or Codex engines, with built-in state management, progress tracking, and cost safeguards.
|
|
4
11
|
|
|
5
12
|
## How It Works
|
|
@@ -19,9 +26,9 @@ Each iteration reads the `## Steering` section of `proposal.md`, picks the first
|
|
|
19
26
|
### npm (global)
|
|
20
27
|
|
|
21
28
|
```bash
|
|
22
|
-
npm install -g ralphy
|
|
29
|
+
npm install -g @neriros/ralphy
|
|
23
30
|
# or
|
|
24
|
-
bunx ralphy
|
|
31
|
+
bunx @neriros/ralphy
|
|
25
32
|
```
|
|
26
33
|
|
|
27
34
|
Requires [Bun](https://bun.sh) as the runtime.
|
package/dist/cli/index.js
CHANGED
|
@@ -56407,7 +56407,7 @@ function log(msg) {
|
|
|
56407
56407
|
// package.json
|
|
56408
56408
|
var package_default = {
|
|
56409
56409
|
name: "@neriros/ralphy",
|
|
56410
|
-
version: "2.9.
|
|
56410
|
+
version: "2.9.2",
|
|
56411
56411
|
description: "An iterative AI task execution framework. Orchestrates multi-phase autonomous work using Claude or Codex engines.",
|
|
56412
56412
|
keywords: [
|
|
56413
56413
|
"agent",
|
|
@@ -70606,6 +70606,42 @@ async function createWorktree(projectRoot, changeName, runner) {
|
|
|
70606
70606
|
async function removeWorktree(projectRoot, cwd2, runner) {
|
|
70607
70607
|
await runner.run(["worktree", "remove", "--force", cwd2], projectRoot);
|
|
70608
70608
|
}
|
|
70609
|
+
async function isWorktreeSafeToRemove(cwd2, base2, runner) {
|
|
70610
|
+
const status = await runner.run(["status", "--porcelain"], cwd2);
|
|
70611
|
+
const dirty = status.stdout.trim();
|
|
70612
|
+
let unpushedCommits = "";
|
|
70613
|
+
try {
|
|
70614
|
+
const log2 = await runner.run(["log", "--oneline", `${base2}..HEAD`, "--no-merges"], cwd2);
|
|
70615
|
+
unpushedCommits = log2.stdout.trim();
|
|
70616
|
+
} catch {
|
|
70617
|
+
unpushedCommits = "<unknown: failed to compare against base>";
|
|
70618
|
+
}
|
|
70619
|
+
if (dirty && unpushedCommits) {
|
|
70620
|
+
return {
|
|
70621
|
+
safe: false,
|
|
70622
|
+
reason: "uncommitted changes AND unpushed commits present",
|
|
70623
|
+
dirty,
|
|
70624
|
+
unpushedCommits
|
|
70625
|
+
};
|
|
70626
|
+
}
|
|
70627
|
+
if (dirty) {
|
|
70628
|
+
return {
|
|
70629
|
+
safe: false,
|
|
70630
|
+
reason: "uncommitted or untracked files present",
|
|
70631
|
+
dirty,
|
|
70632
|
+
unpushedCommits
|
|
70633
|
+
};
|
|
70634
|
+
}
|
|
70635
|
+
if (unpushedCommits) {
|
|
70636
|
+
return {
|
|
70637
|
+
safe: false,
|
|
70638
|
+
reason: `commits ahead of ${base2} were not pushed/PR'd`,
|
|
70639
|
+
dirty,
|
|
70640
|
+
unpushedCommits
|
|
70641
|
+
};
|
|
70642
|
+
}
|
|
70643
|
+
return { safe: true, dirty, unpushedCommits };
|
|
70644
|
+
}
|
|
70609
70645
|
|
|
70610
70646
|
// apps/cli/src/agent/pr.ts
|
|
70611
70647
|
function defaultTitle(issue) {
|
|
@@ -71012,18 +71048,45 @@ ${stamped}
|
|
|
71012
71048
|
} catch (err) {
|
|
71013
71049
|
const e = err;
|
|
71014
71050
|
const detail = e.stderr?.trim() || e.message;
|
|
71015
|
-
|
|
71051
|
+
const combined = `${e.stdout ?? ""}
|
|
71052
|
+
${e.stderr ?? ""}`;
|
|
71053
|
+
const pushRejected = /failed to push some refs|pre-push hook|hook declined/i.test(combined);
|
|
71054
|
+
if (pushRejected) {
|
|
71055
|
+
appendLog(`! push rejected for ${changeName} (host repo pre-push hook failed) \u2014 worktree preserved at ${cwd2}`, "red");
|
|
71056
|
+
appendLog(` detail: ${detail}`, "red");
|
|
71057
|
+
} else {
|
|
71058
|
+
appendLog(`! PR create failed for ${changeName}: ${detail}`, "red");
|
|
71059
|
+
}
|
|
71016
71060
|
effectiveCode = PR_FAILED_EXIT;
|
|
71017
71061
|
}
|
|
71018
71062
|
}
|
|
71019
71063
|
}
|
|
71020
71064
|
if (useWorktree && cwd2 !== projectRoot) {
|
|
71021
71065
|
if (effectiveCode === 0 && cfg.cleanupWorktreeOnSuccess) {
|
|
71022
|
-
|
|
71023
|
-
|
|
71024
|
-
|
|
71025
|
-
|
|
71026
|
-
|
|
71066
|
+
const check = await isWorktreeSafeToRemove(cwd2, cfg.prBaseBranch, bunGitRunner).catch((err) => ({
|
|
71067
|
+
safe: false,
|
|
71068
|
+
reason: `safety check failed: ${err.message}`,
|
|
71069
|
+
dirty: "",
|
|
71070
|
+
unpushedCommits: ""
|
|
71071
|
+
}));
|
|
71072
|
+
if (!check.safe) {
|
|
71073
|
+
appendLog(`! preserving worktree for ${changeName}: ${check.reason}`, "yellow");
|
|
71074
|
+
if (check.dirty) {
|
|
71075
|
+
appendLog(` uncommitted:
|
|
71076
|
+
${check.dirty}`, "yellow");
|
|
71077
|
+
}
|
|
71078
|
+
if (check.unpushedCommits) {
|
|
71079
|
+
appendLog(` commits:
|
|
71080
|
+
${check.unpushedCommits}`, "yellow");
|
|
71081
|
+
}
|
|
71082
|
+
appendLog(` path: ${cwd2}`, "yellow");
|
|
71083
|
+
} else {
|
|
71084
|
+
try {
|
|
71085
|
+
await removeWorktree(projectRoot, cwd2, bunGitRunner);
|
|
71086
|
+
appendLog(` removed worktree ${cwd2}`, "gray");
|
|
71087
|
+
} catch (err) {
|
|
71088
|
+
appendLog(`! worktree remove failed for ${changeName}: ${err.message}`, "yellow");
|
|
71089
|
+
}
|
|
71027
71090
|
}
|
|
71028
71091
|
}
|
|
71029
71092
|
}
|