@lnilluv/pi-ralph-loop 0.2.1 → 0.3.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/.github/workflows/ci.yml +5 -2
- package/.github/workflows/release.yml +7 -4
- package/README.md +64 -16
- package/package.json +12 -4
- package/src/index.ts +433 -245
- package/src/ralph.ts +642 -0
- package/tests/ralph.test.ts +470 -0
- package/tsconfig.json +3 -2
package/.github/workflows/ci.yml
CHANGED
|
@@ -17,13 +17,16 @@ jobs:
|
|
|
17
17
|
- name: Checkout
|
|
18
18
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
|
|
19
19
|
|
|
20
|
-
- name: Setup Node.js 22
|
|
20
|
+
- name: Setup Node.js 22.22.1
|
|
21
21
|
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af
|
|
22
22
|
with:
|
|
23
|
-
node-version: 22
|
|
23
|
+
node-version: 22.22.1
|
|
24
24
|
|
|
25
25
|
- name: Install dependencies
|
|
26
26
|
run: npm ci --ignore-scripts
|
|
27
27
|
|
|
28
|
+
- name: Test
|
|
29
|
+
run: npm test
|
|
30
|
+
|
|
28
31
|
- name: Typecheck
|
|
29
32
|
run: npm run typecheck
|
|
@@ -24,15 +24,18 @@ jobs:
|
|
|
24
24
|
with:
|
|
25
25
|
fetch-depth: 0
|
|
26
26
|
|
|
27
|
-
- name: Setup Node.js 24
|
|
27
|
+
- name: Setup Node.js 24.14.1
|
|
28
28
|
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af
|
|
29
29
|
with:
|
|
30
|
-
node-version: 24
|
|
30
|
+
node-version: 24.14.1
|
|
31
31
|
registry-url: https://registry.npmjs.org
|
|
32
32
|
|
|
33
33
|
- name: Install dependencies
|
|
34
34
|
run: npm ci --ignore-scripts
|
|
35
35
|
|
|
36
|
+
- name: Test
|
|
37
|
+
run: npm test
|
|
38
|
+
|
|
36
39
|
- name: Typecheck
|
|
37
40
|
run: npm run typecheck
|
|
38
41
|
|
|
@@ -119,11 +122,11 @@ jobs:
|
|
|
119
122
|
|
|
120
123
|
- name: Publish (main)
|
|
121
124
|
if: steps.bump.outputs.should_release == 'true' && github.ref_name == 'main'
|
|
122
|
-
run: npx npm@11 publish --access public --provenance
|
|
125
|
+
run: npx -y npm@11.12.1 publish --access public --provenance
|
|
123
126
|
|
|
124
127
|
- name: Publish (dev prerelease)
|
|
125
128
|
if: steps.bump.outputs.should_release == 'true' && github.ref_name == 'dev'
|
|
126
|
-
run: npx npm@11 publish --access public --provenance --tag dev
|
|
129
|
+
run: npx -y npm@11.12.1 publish --access public --provenance --tag dev
|
|
127
130
|
|
|
128
131
|
- name: Commit version bump and tag
|
|
129
132
|
if: steps.bump.outputs.should_release == 'true'
|
package/README.md
CHANGED
|
@@ -10,12 +10,14 @@ pi install npm:@lnilluv/pi-ralph-loop
|
|
|
10
10
|
|
|
11
11
|
## Quick start
|
|
12
12
|
|
|
13
|
+
### Run an existing task folder
|
|
14
|
+
|
|
13
15
|
```md
|
|
14
16
|
# my-task/RALPH.md
|
|
15
17
|
---
|
|
16
18
|
commands:
|
|
17
19
|
- name: tests
|
|
18
|
-
run: npm test
|
|
20
|
+
run: npm test
|
|
19
21
|
timeout: 60
|
|
20
22
|
---
|
|
21
23
|
Fix failing tests using this output:
|
|
@@ -23,11 +25,57 @@ Fix failing tests using this output:
|
|
|
23
25
|
{{ commands.tests }}
|
|
24
26
|
```
|
|
25
27
|
|
|
26
|
-
Run
|
|
28
|
+
Run:
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
/ralph my-task
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Draft a loop from natural language
|
|
35
|
+
|
|
36
|
+
```text
|
|
37
|
+
/ralph reverse engineer this app
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
pi drafts `./reverse-engineer-this-app/RALPH.md`, shows a short Mission Brief, lets you edit the file, and only starts after you confirm.
|
|
41
|
+
|
|
42
|
+
### Draft without starting
|
|
43
|
+
|
|
44
|
+
```text
|
|
45
|
+
/ralph-draft fix flaky auth tests
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
That saves the draft but does not launch the loop.
|
|
27
49
|
|
|
28
50
|
## How it works
|
|
29
51
|
|
|
30
|
-
On each iteration, pi-ralph reads `RALPH.md`, runs the configured commands, injects their output into the prompt through `{{ commands.<name> }}` placeholders, starts a fresh session, sends the prompt, and waits for completion. Failed
|
|
52
|
+
On each iteration, pi-ralph reads `RALPH.md`, runs the configured commands, injects their output into the prompt through `{{ commands.<name> }}` placeholders, starts a fresh session, sends the prompt, and waits for completion. Failed command output appears in the next iteration, which creates a self-healing loop.
|
|
53
|
+
|
|
54
|
+
## Smart `/ralph` behavior
|
|
55
|
+
|
|
56
|
+
`/ralph` is path-first:
|
|
57
|
+
|
|
58
|
+
- task folder with `RALPH.md` -> runs it
|
|
59
|
+
- direct `RALPH.md` path -> runs it
|
|
60
|
+
- no args in a folder without `RALPH.md` -> asks what the loop should work on, drafts `./RALPH.md`, then asks before starting
|
|
61
|
+
- natural-language task -> drafts `./<slug>/RALPH.md`, then asks before starting
|
|
62
|
+
- unresolved path-like input like `foo/bar` or `notes.md` -> offers recovery choices and normalizes missing markdown targets to `./<folder>/RALPH.md`
|
|
63
|
+
- arbitrary markdown files like `README.md` -> rejected instead of auto-run
|
|
64
|
+
|
|
65
|
+
### Explicit flags
|
|
66
|
+
|
|
67
|
+
Use these when you want to skip heuristics:
|
|
68
|
+
|
|
69
|
+
```text
|
|
70
|
+
/ralph --path my-task
|
|
71
|
+
/ralph --task "reverse engineer the billing flow"
|
|
72
|
+
/ralph-draft --path my-task
|
|
73
|
+
/ralph-draft --task "fix flaky auth tests"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Interactive review
|
|
77
|
+
|
|
78
|
+
Draft flows require an interactive UI because the extension uses a Mission Brief and editor dialog before saving or starting. In non-interactive contexts, pass an existing task folder or `RALPH.md` path instead.
|
|
31
79
|
|
|
32
80
|
## RALPH.md format
|
|
33
81
|
|
|
@@ -35,7 +83,7 @@ On each iteration, pi-ralph reads `RALPH.md`, runs the configured commands, inje
|
|
|
35
83
|
---
|
|
36
84
|
commands:
|
|
37
85
|
- name: tests
|
|
38
|
-
run: npm test
|
|
86
|
+
run: npm test
|
|
39
87
|
timeout: 90
|
|
40
88
|
- name: lint
|
|
41
89
|
run: npm run lint
|
|
@@ -75,7 +123,7 @@ Apply the smallest safe fix and explain why it works.
|
|
|
75
123
|
| `timeout` | number | `300` | Per-iteration timeout in seconds; stops the loop if the agent is stuck |
|
|
76
124
|
| `completion_promise` | string | — | Agent signals completion by sending `<promise>DONE</promise>`; loop breaks on match |
|
|
77
125
|
| `guardrails.block_commands` | string[] | `[]` | Regex patterns to block in bash |
|
|
78
|
-
| `guardrails.protected_files` | string[] | `[]` | Glob patterns
|
|
126
|
+
| `guardrails.protected_files` | string[] | `[]` | Glob patterns enforced on `write`/`edit` tool calls |
|
|
79
127
|
|
|
80
128
|
### Placeholders
|
|
81
129
|
|
|
@@ -83,20 +131,21 @@ Apply the smallest safe fix and explain why it works.
|
|
|
83
131
|
|-------------|-------------|
|
|
84
132
|
| `{{ commands.<name> }}` | Output from the named command |
|
|
85
133
|
| `{{ ralph.iteration }}` | Current 1-based iteration number |
|
|
86
|
-
| `{{ ralph.name }}` | Directory name containing the RALPH.md |
|
|
134
|
+
| `{{ ralph.name }}` | Directory name containing the `RALPH.md` |
|
|
87
135
|
|
|
88
|
-
HTML comments (`<!-- ... -->`) are stripped from the prompt body after placeholder resolution, so you can annotate your RALPH.md freely.
|
|
136
|
+
HTML comments (`<!-- ... -->`) are stripped from the prompt body after placeholder resolution, so you can annotate your `RALPH.md` freely. Generated drafts also escape literal `<!--` and `-->` in the visible task line, and the leading metadata comment is URL-encoded so task text can safely contain comment-like sequences.
|
|
89
137
|
|
|
90
138
|
## Commands
|
|
91
139
|
|
|
92
|
-
- `/ralph
|
|
93
|
-
- `/ralph-
|
|
140
|
+
- `/ralph [path-or-task]` - Start Ralph from a task folder or `RALPH.md`, or draft a new loop from natural language.
|
|
141
|
+
- `/ralph-draft [path-or-task]` - Draft or edit a Ralph task without starting it.
|
|
142
|
+
- `/ralph-stop` - Request a graceful stop after the current iteration.
|
|
94
143
|
|
|
95
144
|
## Pi-only features
|
|
96
145
|
|
|
97
146
|
### Guardrails
|
|
98
147
|
|
|
99
|
-
`guardrails.block_commands` and `guardrails.protected_files` come from RALPH frontmatter. The extension enforces them in the `tool_call` hook — but only for sessions created by the loop, so they don't leak into unrelated conversations. Matching bash commands are blocked, and
|
|
148
|
+
`guardrails.block_commands` and `guardrails.protected_files` come from RALPH frontmatter. The extension enforces them in the `tool_call` hook — but only for sessions created by the loop, so they don't leak into unrelated conversations. Matching bash commands are blocked, and `write`/`edit` tool calls targeting protected file globs are denied.
|
|
100
149
|
|
|
101
150
|
### Cross-iteration memory
|
|
102
151
|
|
|
@@ -108,11 +157,11 @@ In the `tool_result` hook, bash outputs are scanned for failure patterns. After
|
|
|
108
157
|
|
|
109
158
|
### Completion promise
|
|
110
159
|
|
|
111
|
-
When `completion_promise` is set (
|
|
160
|
+
When `completion_promise` is set (for example, `"DONE"`), the loop scans the agent's messages for `<promise>DONE</promise>` after each iteration. If found, the loop stops early.
|
|
112
161
|
|
|
113
162
|
### Iteration timeout
|
|
114
163
|
|
|
115
|
-
Each iteration has a configurable timeout (default 300 seconds). If the agent is stuck and doesn't become idle within the timeout, the loop stops with a warning.
|
|
164
|
+
Each iteration has a configurable timeout (default 300 seconds). If the agent is stuck and doesn't become idle within the timeout, the loop stops with a warning.
|
|
116
165
|
|
|
117
166
|
### Input validation
|
|
118
167
|
|
|
@@ -121,20 +170,19 @@ The extension validates `RALPH.md` frontmatter before starting and on each re-pa
|
|
|
121
170
|
## Comparison table
|
|
122
171
|
|
|
123
172
|
| Feature | **@lnilluv/pi-ralph-loop** | pi-ralph | pi-ralph-wiggum | ralphi | ralphify |
|
|
124
|
-
|
|
173
|
+
|---------|----------------------------|----------|-----------------|--------|----------|
|
|
125
174
|
| Command output injection | ✓ | ✗ | ✗ | ✗ | ✓ |
|
|
126
175
|
| Fresh-context sessions | ✓ | ✓ | ✗ | ✓ | ✓ |
|
|
127
176
|
| Mid-turn guardrails | ✓ | ✗ | ✗ | ✗ | ✗ |
|
|
128
177
|
| Cross-iteration memory | ✓ | ✗ | ✗ | ✗ | ✗ |
|
|
129
178
|
| Mid-turn steering | ✓ | ✗ | ✗ | ✗ | ✗ |
|
|
130
|
-
|
|
|
179
|
+
| Guided task drafting | ✓ | ✗ | ✗ | ✗ | separate scaffold |
|
|
131
180
|
| Completion promise | ✓ | ✗ | ✗ | ✗ | ✓ |
|
|
132
181
|
| Iteration timeout | ✓ | ✗ | ✗ | ✗ | ✗ |
|
|
133
182
|
| Session-scoped hooks | ✓ | ✗ | ✗ | ✗ | ✗ |
|
|
134
183
|
| Input validation | ✓ | ✗ | ✗ | ✗ | ✗ |
|
|
135
|
-
| Setup required |
|
|
184
|
+
| Setup required | task folder or draft flow | config | RALPH.md | PRD pipeline | scaffold + RALPH.md |
|
|
136
185
|
|
|
137
186
|
## License
|
|
138
187
|
|
|
139
188
|
MIT
|
|
140
|
-
# CI provenance test
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lnilluv/pi-ralph-loop",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Pi-native ralph loop — autonomous coding iterations with mid-turn supervision",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"pi": {
|
|
@@ -8,7 +8,11 @@
|
|
|
8
8
|
"./src/index.ts"
|
|
9
9
|
]
|
|
10
10
|
},
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": "22.22.1 || 24.14.1"
|
|
13
|
+
},
|
|
11
14
|
"scripts": {
|
|
15
|
+
"test": "node --test --experimental-strip-types $(find tests -type f -name '*.ts' | sort)",
|
|
12
16
|
"typecheck": "tsc --noEmit"
|
|
13
17
|
},
|
|
14
18
|
"repository": {
|
|
@@ -16,8 +20,8 @@
|
|
|
16
20
|
"url": "git+https://github.com/lnilluv/pi-ralph-loop.git"
|
|
17
21
|
},
|
|
18
22
|
"dependencies": {
|
|
19
|
-
"
|
|
20
|
-
"
|
|
23
|
+
"minimatch": "10.2.3",
|
|
24
|
+
"yaml": "2.8.3"
|
|
21
25
|
},
|
|
22
26
|
"peerDependencies": {
|
|
23
27
|
"@mariozechner/pi-coding-agent": "*"
|
|
@@ -29,5 +33,9 @@
|
|
|
29
33
|
"autonomous",
|
|
30
34
|
"loop"
|
|
31
35
|
],
|
|
32
|
-
"license": "MIT"
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "25.6.0",
|
|
39
|
+
"typescript": "6.0.2"
|
|
40
|
+
}
|
|
33
41
|
}
|