ralph-prd 1.0.11 → 1.1.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/install.sh +10 -13
- package/package.json +2 -2
- package/ralph/lib/prompts/commit.md +35 -0
- package/ralph/lib/prompts/implementation.md +41 -0
- package/ralph/lib/prompts/implementation_closing_commit.md +1 -0
- package/ralph/lib/prompts/implementation_closing_no_commit.md +1 -0
- package/ralph/lib/prompts/repair.md +31 -0
- package/ralph/lib/prompts/ship_check.md +11 -0
- package/ralph/lib/prompts/ship_check_repair.md +14 -0
- package/ralph/lib/prompts/verification.md +48 -0
- package/ralph/lib/prompts.mjs +25 -182
- package/ralph/lib/ship-checker.mjs +11 -43
- package/ralph/ralph-claude.mjs +1 -1
- package/ralph/prompts.json +0 -159
package/install.sh
CHANGED
|
@@ -95,20 +95,17 @@ if [ -f "$SOURCE_DIR/package.json" ]; then
|
|
|
95
95
|
info "Stamped version: $VERSION"
|
|
96
96
|
fi
|
|
97
97
|
|
|
98
|
-
#
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
GITIGNORE
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if [ ! -f "$GITIGNORE" ] || ! grep -qF "# ralph-prd" "$GITIGNORE"; then
|
|
105
|
-
printf '\n# ralph-prd (installed via install.sh)\n' >> "$GITIGNORE"
|
|
106
|
-
fi
|
|
107
|
-
echo "$entry" >> "$GITIGNORE"
|
|
108
|
-
ok "Added $entry to .gitignore"
|
|
98
|
+
# Add required entries to .gitignore (idempotent — skips entries already present).
|
|
99
|
+
GITIGNORE="$PROJECT_ROOT/.gitignore"
|
|
100
|
+
for entry in ".claude/ralph/" ".claude/skills/" "logs/"; do
|
|
101
|
+
if [ ! -f "$GITIGNORE" ] || ! grep -qxF "$entry" "$GITIGNORE"; then
|
|
102
|
+
if [ ! -f "$GITIGNORE" ] || ! grep -qF "# ralph-prd" "$GITIGNORE"; then
|
|
103
|
+
printf '\n# ralph-prd (installed via install.sh)\n' >> "$GITIGNORE"
|
|
109
104
|
fi
|
|
110
|
-
|
|
111
|
-
|
|
105
|
+
echo "$entry" >> "$GITIGNORE"
|
|
106
|
+
ok "Added $entry to .gitignore"
|
|
107
|
+
fi
|
|
108
|
+
done
|
|
112
109
|
|
|
113
110
|
# Summary
|
|
114
111
|
echo ""
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ralph-prd",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "AI-powered phased implementation runner for Claude Code — from PRD to shipped code",
|
|
5
5
|
"bin": {
|
|
6
6
|
"ralph-prd": "./bin/install.mjs"
|
|
@@ -29,4 +29,4 @@
|
|
|
29
29
|
"engines": {
|
|
30
30
|
"node": ">=18"
|
|
31
31
|
}
|
|
32
|
-
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
You are Ralph's commit agent. A phase has been implemented and verified.
|
|
2
|
+
Your job is to decide which changed files belong to this phase and commit them.
|
|
3
|
+
|
|
4
|
+
## Phase just completed
|
|
5
|
+
|
|
6
|
+
### {{phaseTitle}}
|
|
7
|
+
|
|
8
|
+
{{phaseBody}}
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Changed repositories
|
|
13
|
+
|
|
14
|
+
{{repoSections}}
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
For each repository listed above, output a commit plan using EXACTLY this format (one block per repo):
|
|
19
|
+
|
|
20
|
+
REPO: <repo name>
|
|
21
|
+
FILES:
|
|
22
|
+
- <relative/path/to/file>
|
|
23
|
+
COMMIT: ralph: <imperative summary, max 72 chars>
|
|
24
|
+
DESCRIPTION:
|
|
25
|
+
- <bullet: what changed and why — focus on intent, not mechanics>
|
|
26
|
+
- <add one bullet per logical group of changes>
|
|
27
|
+
END_COMMIT
|
|
28
|
+
|
|
29
|
+
Rules:
|
|
30
|
+
- Only include files shown in the git status above that are relevant to this phase.
|
|
31
|
+
- Use paths exactly as shown in the git status output (relative to repo root).
|
|
32
|
+
- COMMIT line: start with "ralph: " then a short imperative verb phrase (≤72 chars total).
|
|
33
|
+
- DESCRIPTION bullets: explain *what* moved or changed and *why*, not line-by-line mechanics.
|
|
34
|
+
- If a repository has no files relevant to this phase, output: REPO: <name>\nSKIP
|
|
35
|
+
- Do not output anything outside the structured REPO / END_COMMIT blocks.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
You are Ralph, an automated software implementation assistant.
|
|
2
|
+
Your job is to implement exactly the phase described below and nothing more.
|
|
3
|
+
|
|
4
|
+
## Repositories in scope
|
|
5
|
+
|
|
6
|
+
{{repoLines}}{{writableLines}}
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Full plan (for context)
|
|
11
|
+
|
|
12
|
+
{{planContent}}
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Phase to implement now
|
|
17
|
+
|
|
18
|
+
### {{phaseTitle}}
|
|
19
|
+
|
|
20
|
+
{{phaseBody}}
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Implementation approach
|
|
25
|
+
|
|
26
|
+
For **backend code** (server logic, API routes, business logic, database layers, services, data models, utilities):
|
|
27
|
+
Follow a strict red → green → refactor cycle, one behaviour at a time:
|
|
28
|
+
|
|
29
|
+
1. **RED** — Write one failing test for a single behaviour. Run it to confirm it fails before writing any production code.
|
|
30
|
+
2. **GREEN** — Write the minimum production code to make that one test pass. Nothing more.
|
|
31
|
+
3. **REFACTOR** — Clean up without changing behaviour. Re-run tests to confirm they still pass.
|
|
32
|
+
4. Repeat for the next behaviour.
|
|
33
|
+
|
|
34
|
+
Work in tracer-bullet style: one thin slice end-to-end before moving to the next.
|
|
35
|
+
Do NOT write multiple tests upfront. Do NOT write production code before a failing test exists.
|
|
36
|
+
|
|
37
|
+
**Frontend code** (UI components, CSS, HTML, browser JS, view templates) is exempt — implement it directly without the TDD cycle.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
Implement the phase above in the repositories listed. Make all necessary file changes. Do not implement other phases.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
When you are done with all file changes, commit everything with a clear commit message in the format: "ralph: <short imperative summary>" followed by a blank line and a bullet list describing what changed and why. Then output a brief summary of what you changed.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
When you are done, output a brief summary of what you changed.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
You are Ralph, an automated software repair assistant.
|
|
2
|
+
A previous implementation attempt for the phase below failed verification.
|
|
3
|
+
Your job is to fix exactly the issues listed in the failure notes and nothing more.
|
|
4
|
+
|
|
5
|
+
## Failure notes from the verifier
|
|
6
|
+
|
|
7
|
+
{{failureNotes}}
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Repositories in scope
|
|
12
|
+
|
|
13
|
+
{{repoLines}}{{writableLines}}
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Full plan (for context)
|
|
18
|
+
|
|
19
|
+
{{planContent}}
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Phase to repair
|
|
24
|
+
|
|
25
|
+
### {{phaseTitle}}
|
|
26
|
+
|
|
27
|
+
{{phaseBody}}
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
Fix only the issues described in the failure notes above. Make the minimum changes necessary to satisfy the failing criteria. When done, output a brief summary of what you changed.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
The ship-check reviewer found issues with the implementation of phase "{{phaseTitle}}".
|
|
2
|
+
Please address the following remarks, then the phase will be re-checked.
|
|
3
|
+
|
|
4
|
+
## Reviewer findings
|
|
5
|
+
|
|
6
|
+
{{findings}}
|
|
7
|
+
|
|
8
|
+
## Phase being reviewed
|
|
9
|
+
|
|
10
|
+
{{phaseBody}}
|
|
11
|
+
|
|
12
|
+
## Current repository state
|
|
13
|
+
|
|
14
|
+
{{repoState}}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
You are Ralph's verification agent. Your only job is to check whether the implementation for the phase below satisfies each acceptance criterion.
|
|
2
|
+
|
|
3
|
+
## Phase being verified
|
|
4
|
+
|
|
5
|
+
### {{phaseTitle}}
|
|
6
|
+
|
|
7
|
+
{{phaseBody}}
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Acceptance criteria to verify
|
|
12
|
+
|
|
13
|
+
{{criteriaList}}
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Full plan (for context)
|
|
18
|
+
|
|
19
|
+
{{planContent}}
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Current repository state
|
|
24
|
+
|
|
25
|
+
{{repoState}}
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Implementation session output
|
|
30
|
+
|
|
31
|
+
{{implementationOutput}}
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
Review the repository state and implementation output against each acceptance criterion.
|
|
36
|
+
|
|
37
|
+
At the end of your response you MUST output one of the following verdict lines exactly:
|
|
38
|
+
|
|
39
|
+
VERDICT: PASS
|
|
40
|
+
|
|
41
|
+
or
|
|
42
|
+
|
|
43
|
+
VERDICT: FAIL
|
|
44
|
+
FAILURE_NOTES_START
|
|
45
|
+
<bullet list of which criteria failed and why>
|
|
46
|
+
FAILURE_NOTES_END
|
|
47
|
+
|
|
48
|
+
Do not output anything after FAILURE_NOTES_END.
|
package/ralph/lib/prompts.mjs
CHANGED
|
@@ -3,12 +3,10 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Prompt templates system.
|
|
5
5
|
*
|
|
6
|
-
* Reads
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* When prompts.json is present, its keys are merged over the defaults,
|
|
11
|
-
* so individual keys can be overridden without replacing the entire file.
|
|
6
|
+
* Reads prompt templates from lib/prompts/*.md. Each file's basename (without
|
|
7
|
+
* .md) becomes the prompt key. If prompts.json is present in the ralph root,
|
|
8
|
+
* its keys are merged on top as overrides — useful for local customisation
|
|
9
|
+
* without touching the source files.
|
|
12
10
|
*
|
|
13
11
|
* Public API:
|
|
14
12
|
* render(key, vars) → string
|
|
@@ -20,183 +18,14 @@
|
|
|
20
18
|
* _resetCache() — clear module cache and reset path (test use only)
|
|
21
19
|
*/
|
|
22
20
|
|
|
23
|
-
import { readFileSync, existsSync } from 'fs';
|
|
21
|
+
import { readFileSync, existsSync, readdirSync } from 'fs';
|
|
24
22
|
import { join, dirname } from 'path';
|
|
25
23
|
import { fileURLToPath } from 'url';
|
|
26
24
|
|
|
27
25
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
26
|
+
const PROMPTS_DIR = join(__dirname, 'prompts');
|
|
28
27
|
const DEFAULT_PROMPTS_PATH = join(__dirname, '..', 'prompts.json');
|
|
29
28
|
|
|
30
|
-
// ─── Built-in defaults ────────────────────────────────────────────────────────
|
|
31
|
-
|
|
32
|
-
const DEFAULTS = {
|
|
33
|
-
implementation: [
|
|
34
|
-
'You are Ralph, an automated software implementation assistant.',
|
|
35
|
-
'Your job is to implement exactly the phase described below and nothing more.',
|
|
36
|
-
'',
|
|
37
|
-
'## Repositories in scope',
|
|
38
|
-
'',
|
|
39
|
-
'{{repoLines}}{{writableLines}}',
|
|
40
|
-
'',
|
|
41
|
-
'---',
|
|
42
|
-
'',
|
|
43
|
-
'## Full plan (for context)',
|
|
44
|
-
'',
|
|
45
|
-
'{{planContent}}',
|
|
46
|
-
'',
|
|
47
|
-
'---',
|
|
48
|
-
'',
|
|
49
|
-
'## Phase to implement now',
|
|
50
|
-
'',
|
|
51
|
-
'### {{phaseTitle}}',
|
|
52
|
-
'',
|
|
53
|
-
'{{phaseBody}}',
|
|
54
|
-
'',
|
|
55
|
-
'---',
|
|
56
|
-
'',
|
|
57
|
-
'Implement the phase above in the repositories listed. Make all necessary file changes. Do not implement other phases. ',
|
|
58
|
-
],
|
|
59
|
-
|
|
60
|
-
implementation_closing_commit: [
|
|
61
|
-
'When you are done with all file changes, commit everything with a clear commit message ' +
|
|
62
|
-
'in the format: "ralph: <short imperative summary>" followed by a blank line and a bullet ' +
|
|
63
|
-
'list describing what changed and why. Then output a brief summary of what you changed.',
|
|
64
|
-
'',
|
|
65
|
-
],
|
|
66
|
-
|
|
67
|
-
implementation_closing_no_commit: [
|
|
68
|
-
'When you are done, output a brief summary of what you changed.',
|
|
69
|
-
'',
|
|
70
|
-
],
|
|
71
|
-
|
|
72
|
-
verification: [
|
|
73
|
-
"You are Ralph's verification agent. Your only job is to check whether the " +
|
|
74
|
-
'implementation for the phase below satisfies each acceptance criterion.',
|
|
75
|
-
'',
|
|
76
|
-
'## Phase being verified',
|
|
77
|
-
'',
|
|
78
|
-
'### {{phaseTitle}}',
|
|
79
|
-
'',
|
|
80
|
-
'{{phaseBody}}',
|
|
81
|
-
'',
|
|
82
|
-
'---',
|
|
83
|
-
'',
|
|
84
|
-
'## Acceptance criteria to verify',
|
|
85
|
-
'',
|
|
86
|
-
'{{criteriaList}}',
|
|
87
|
-
'',
|
|
88
|
-
'---',
|
|
89
|
-
'',
|
|
90
|
-
'## Full plan (for context)',
|
|
91
|
-
'',
|
|
92
|
-
'{{planContent}}',
|
|
93
|
-
'',
|
|
94
|
-
'---',
|
|
95
|
-
'',
|
|
96
|
-
'## Current repository state',
|
|
97
|
-
'',
|
|
98
|
-
'{{repoState}}',
|
|
99
|
-
'',
|
|
100
|
-
'---',
|
|
101
|
-
'',
|
|
102
|
-
'## Implementation session output',
|
|
103
|
-
'',
|
|
104
|
-
'{{implementationOutput}}',
|
|
105
|
-
'',
|
|
106
|
-
'---',
|
|
107
|
-
'',
|
|
108
|
-
'Review the repository state and implementation output against each acceptance criterion.',
|
|
109
|
-
'',
|
|
110
|
-
'At the end of your response you MUST output one of the following verdict lines exactly:',
|
|
111
|
-
'',
|
|
112
|
-
' VERDICT: PASS',
|
|
113
|
-
'',
|
|
114
|
-
'or',
|
|
115
|
-
'',
|
|
116
|
-
' VERDICT: FAIL',
|
|
117
|
-
' FAILURE_NOTES_START',
|
|
118
|
-
' <bullet list of which criteria failed and why>',
|
|
119
|
-
' FAILURE_NOTES_END',
|
|
120
|
-
'',
|
|
121
|
-
'Do not output anything after FAILURE_NOTES_END.',
|
|
122
|
-
'',
|
|
123
|
-
],
|
|
124
|
-
|
|
125
|
-
repair: [
|
|
126
|
-
'You are Ralph, an automated software repair assistant.',
|
|
127
|
-
'A previous implementation attempt for the phase below failed verification.',
|
|
128
|
-
'Your job is to fix exactly the issues listed in the failure notes and nothing more.',
|
|
129
|
-
'',
|
|
130
|
-
'## Failure notes from the verifier',
|
|
131
|
-
'',
|
|
132
|
-
'{{failureNotes}}',
|
|
133
|
-
'',
|
|
134
|
-
'---',
|
|
135
|
-
'',
|
|
136
|
-
'## Repositories in scope',
|
|
137
|
-
'',
|
|
138
|
-
'{{repoLines}}{{writableLines}}',
|
|
139
|
-
'',
|
|
140
|
-
'---',
|
|
141
|
-
'',
|
|
142
|
-
'## Full plan (for context)',
|
|
143
|
-
'',
|
|
144
|
-
'{{planContent}}',
|
|
145
|
-
'',
|
|
146
|
-
'---',
|
|
147
|
-
'',
|
|
148
|
-
'## Phase to repair',
|
|
149
|
-
'',
|
|
150
|
-
'### {{phaseTitle}}',
|
|
151
|
-
'',
|
|
152
|
-
'{{phaseBody}}',
|
|
153
|
-
'',
|
|
154
|
-
'---',
|
|
155
|
-
'',
|
|
156
|
-
'Fix only the issues described in the failure notes above. Make the minimum changes necessary to satisfy the failing criteria. When done, output a brief summary of what you changed.',
|
|
157
|
-
'',
|
|
158
|
-
],
|
|
159
|
-
|
|
160
|
-
commit: [
|
|
161
|
-
"You are Ralph's commit agent. A phase has been implemented and verified.",
|
|
162
|
-
'Your job is to decide which changed files belong to this phase and commit them.',
|
|
163
|
-
'',
|
|
164
|
-
'## Phase just completed',
|
|
165
|
-
'',
|
|
166
|
-
'### {{phaseTitle}}',
|
|
167
|
-
'',
|
|
168
|
-
'{{phaseBody}}',
|
|
169
|
-
'',
|
|
170
|
-
'---',
|
|
171
|
-
'',
|
|
172
|
-
'## Changed repositories',
|
|
173
|
-
'',
|
|
174
|
-
'{{repoSections}}',
|
|
175
|
-
'',
|
|
176
|
-
'---',
|
|
177
|
-
'',
|
|
178
|
-
'For each repository listed above, output a commit plan using EXACTLY this format (one block per repo):',
|
|
179
|
-
'',
|
|
180
|
-
' REPO: <repo name>',
|
|
181
|
-
' FILES:',
|
|
182
|
-
' - <relative/path/to/file>',
|
|
183
|
-
' COMMIT: ralph: <imperative summary, max 72 chars>',
|
|
184
|
-
' DESCRIPTION:',
|
|
185
|
-
' - <bullet: what changed and why — focus on intent, not mechanics>',
|
|
186
|
-
' - <add one bullet per logical group of changes>',
|
|
187
|
-
' END_COMMIT',
|
|
188
|
-
'',
|
|
189
|
-
'Rules:',
|
|
190
|
-
'- Only include files shown in the git status above that are relevant to this phase.',
|
|
191
|
-
'- Use paths exactly as shown in the git status output (relative to repo root).',
|
|
192
|
-
'- COMMIT line: start with "ralph: " then a short imperative verb phrase (\u226472 chars total).',
|
|
193
|
-
'- DESCRIPTION bullets: explain *what* moved or changed and *why*, not line-by-line mechanics.',
|
|
194
|
-
'- If a repository has no files relevant to this phase, output: REPO: <name>\\nSKIP',
|
|
195
|
-
'- Do not output anything outside the structured REPO / END_COMMIT blocks.',
|
|
196
|
-
'',
|
|
197
|
-
],
|
|
198
|
-
};
|
|
199
|
-
|
|
200
29
|
// ─── Cache & path ─────────────────────────────────────────────────────────────
|
|
201
30
|
|
|
202
31
|
let _cache = null;
|
|
@@ -204,12 +33,27 @@ let _promptsPath = DEFAULT_PROMPTS_PATH;
|
|
|
204
33
|
|
|
205
34
|
function loadPrompts() {
|
|
206
35
|
if (_cache !== null) return _cache;
|
|
36
|
+
|
|
37
|
+
// Load defaults from lib/prompts/*.md — key = filename without .md
|
|
38
|
+
const prompts = {};
|
|
39
|
+
if (existsSync(PROMPTS_DIR)) {
|
|
40
|
+
for (const file of readdirSync(PROMPTS_DIR)) {
|
|
41
|
+
if (!file.endsWith('.md')) continue;
|
|
42
|
+
const key = file.slice(0, -3);
|
|
43
|
+
prompts[key] = readFileSync(join(PROMPTS_DIR, file), 'utf8');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Merge prompts.json overrides on top (backward compat)
|
|
207
48
|
if (existsSync(_promptsPath)) {
|
|
208
49
|
const raw = readFileSync(_promptsPath, 'utf8');
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
50
|
+
const overrides = JSON.parse(raw);
|
|
51
|
+
for (const [k, v] of Object.entries(overrides)) {
|
|
52
|
+
prompts[k] = Array.isArray(v) ? v.join('\n') : v;
|
|
53
|
+
}
|
|
212
54
|
}
|
|
55
|
+
|
|
56
|
+
_cache = prompts;
|
|
213
57
|
return _cache;
|
|
214
58
|
}
|
|
215
59
|
|
|
@@ -229,8 +73,7 @@ export function render(key, vars = {}) {
|
|
|
229
73
|
const available = Object.keys(prompts).filter(k => !k.startsWith('_')).join(', ');
|
|
230
74
|
throw new Error(`Prompt key "${key}" not found. Available keys: ${available}`);
|
|
231
75
|
}
|
|
232
|
-
const
|
|
233
|
-
const template = Array.isArray(entry) ? entry.join('\n') : entry;
|
|
76
|
+
const template = prompts[key];
|
|
234
77
|
return template.replace(/\{\{(\w+)\}\}/g, (_, name) => (name in vars ? String(vars[name]) : ''));
|
|
235
78
|
}
|
|
236
79
|
|
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
import { readFileSync } from 'fs';
|
|
28
28
|
import { join } from 'path';
|
|
29
29
|
|
|
30
|
+
import { render } from './prompts.mjs';
|
|
31
|
+
|
|
30
32
|
// ─── Error type ───────────────────────────────────────────────────────────────
|
|
31
33
|
|
|
32
34
|
export class ShipCheckError extends Error {
|
|
@@ -132,56 +134,22 @@ function parseVerdict(text) {
|
|
|
132
134
|
|
|
133
135
|
// ─── Prompt builders ──────────────────────────────────────────────────────────
|
|
134
136
|
|
|
135
|
-
/**
|
|
136
|
-
* Build the ship-check prompt by combining the skill body with phase context
|
|
137
|
-
* and the current repository state.
|
|
138
|
-
*
|
|
139
|
-
* @param {string} skillBody - Skill content with frontmatter stripped
|
|
140
|
-
* @param {import('./plan-parser.mjs').Phase} phase
|
|
141
|
-
* @param {string} repoState - Pre-computed git status / diff summary
|
|
142
|
-
* @returns {string}
|
|
143
|
-
*/
|
|
144
137
|
function buildShipCheckPrompt(skillBody, phase, repoState) {
|
|
145
|
-
return
|
|
138
|
+
return render('ship_check', {
|
|
146
139
|
skillBody,
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
'',
|
|
150
|
-
`## Phase under review: ${phase.title}`,
|
|
151
|
-
'',
|
|
152
|
-
phase.body.trim(),
|
|
153
|
-
'',
|
|
154
|
-
'## Current repository state',
|
|
155
|
-
'',
|
|
140
|
+
phaseTitle: phase.title,
|
|
141
|
+
phaseBody: phase.body.trim(),
|
|
156
142
|
repoState,
|
|
157
|
-
|
|
143
|
+
});
|
|
158
144
|
}
|
|
159
145
|
|
|
160
|
-
/**
|
|
161
|
-
* Build the repair prompt sent after a REMARKS verdict.
|
|
162
|
-
*
|
|
163
|
-
* @param {import('./plan-parser.mjs').Phase} phase
|
|
164
|
-
* @param {string} repoState
|
|
165
|
-
* @param {string} findings - Findings text from the ship-check session
|
|
166
|
-
* @returns {string}
|
|
167
|
-
*/
|
|
168
146
|
function buildRepairPrompt(phase, repoState, findings) {
|
|
169
|
-
return
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
'',
|
|
173
|
-
'## Reviewer findings',
|
|
174
|
-
'',
|
|
175
|
-
findings || '(No specific findings provided.)',
|
|
176
|
-
'',
|
|
177
|
-
'## Phase being reviewed',
|
|
178
|
-
'',
|
|
179
|
-
phase.body.trim(),
|
|
180
|
-
'',
|
|
181
|
-
'## Current repository state',
|
|
182
|
-
'',
|
|
147
|
+
return render('ship_check_repair', {
|
|
148
|
+
phaseTitle: phase.title,
|
|
149
|
+
phaseBody: phase.body.trim(),
|
|
183
150
|
repoState,
|
|
184
|
-
|
|
151
|
+
findings: findings || '(No specific findings provided.)',
|
|
152
|
+
});
|
|
185
153
|
}
|
|
186
154
|
|
|
187
155
|
// ─── Session helper ───────────────────────────────────────────────────────────
|
package/ralph/ralph-claude.mjs
CHANGED
|
@@ -363,7 +363,7 @@ async function main() {
|
|
|
363
363
|
// Derive branch name and log directory
|
|
364
364
|
const branch = deriveBranchName(planPath);
|
|
365
365
|
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
|
366
|
-
const logsBaseDir = resolve(__dirname, 'logs');
|
|
366
|
+
const logsBaseDir = resolve(__dirname, '../..', 'logs');
|
|
367
367
|
let logsDir;
|
|
368
368
|
if (isDryRun) {
|
|
369
369
|
// Dry runs always get a fresh folder
|
package/ralph/prompts.json
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"implementation": [
|
|
3
|
-
"You are Ralph, an automated software implementation assistant.",
|
|
4
|
-
"Your job is to implement exactly the phase described below and nothing more.",
|
|
5
|
-
"",
|
|
6
|
-
"## Repositories in scope",
|
|
7
|
-
"",
|
|
8
|
-
"{{repoLines}}{{writableLines}}",
|
|
9
|
-
"",
|
|
10
|
-
"---",
|
|
11
|
-
"",
|
|
12
|
-
"## Full plan (for context)",
|
|
13
|
-
"",
|
|
14
|
-
"{{planContent}}",
|
|
15
|
-
"",
|
|
16
|
-
"---",
|
|
17
|
-
"",
|
|
18
|
-
"## Phase to implement now",
|
|
19
|
-
"",
|
|
20
|
-
"### {{phaseTitle}}",
|
|
21
|
-
"",
|
|
22
|
-
"{{phaseBody}}",
|
|
23
|
-
"",
|
|
24
|
-
"---",
|
|
25
|
-
"",
|
|
26
|
-
"Implement the phase above in the repositories listed. Make all necessary file changes. Do not implement other phases. "
|
|
27
|
-
],
|
|
28
|
-
"implementation_closing_commit": [
|
|
29
|
-
"When you are done with all file changes, commit everything with a clear commit message in the format: \"ralph: <short imperative summary>\" followed by a blank line and a bullet list describing what changed and why. Then output a brief summary of what you changed.",
|
|
30
|
-
""
|
|
31
|
-
],
|
|
32
|
-
"implementation_closing_no_commit": [
|
|
33
|
-
"When you are done, output a brief summary of what you changed.",
|
|
34
|
-
""
|
|
35
|
-
],
|
|
36
|
-
"verification": [
|
|
37
|
-
"You are Ralph's verification agent. Your only job is to check whether the implementation for the phase below satisfies each acceptance criterion.",
|
|
38
|
-
"",
|
|
39
|
-
"## Phase being verified",
|
|
40
|
-
"",
|
|
41
|
-
"### {{phaseTitle}}",
|
|
42
|
-
"",
|
|
43
|
-
"{{phaseBody}}",
|
|
44
|
-
"",
|
|
45
|
-
"---",
|
|
46
|
-
"",
|
|
47
|
-
"## Acceptance criteria to verify",
|
|
48
|
-
"",
|
|
49
|
-
"{{criteriaList}}",
|
|
50
|
-
"",
|
|
51
|
-
"---",
|
|
52
|
-
"",
|
|
53
|
-
"## Full plan (for context)",
|
|
54
|
-
"",
|
|
55
|
-
"{{planContent}}",
|
|
56
|
-
"",
|
|
57
|
-
"---",
|
|
58
|
-
"",
|
|
59
|
-
"## Current repository state",
|
|
60
|
-
"",
|
|
61
|
-
"{{repoState}}",
|
|
62
|
-
"",
|
|
63
|
-
"---",
|
|
64
|
-
"",
|
|
65
|
-
"## Implementation session output",
|
|
66
|
-
"",
|
|
67
|
-
"{{implementationOutput}}",
|
|
68
|
-
"",
|
|
69
|
-
"---",
|
|
70
|
-
"",
|
|
71
|
-
"Review the repository state and implementation output against each acceptance criterion.",
|
|
72
|
-
"",
|
|
73
|
-
"At the end of your response you MUST output one of the following verdict lines exactly:",
|
|
74
|
-
"",
|
|
75
|
-
" VERDICT: PASS",
|
|
76
|
-
"",
|
|
77
|
-
"or",
|
|
78
|
-
"",
|
|
79
|
-
" VERDICT: FAIL",
|
|
80
|
-
" FAILURE_NOTES_START",
|
|
81
|
-
" <bullet list of which criteria failed and why>",
|
|
82
|
-
" FAILURE_NOTES_END",
|
|
83
|
-
"",
|
|
84
|
-
"Do not output anything after FAILURE_NOTES_END.",
|
|
85
|
-
""
|
|
86
|
-
],
|
|
87
|
-
"repair": [
|
|
88
|
-
"You are Ralph, an automated software repair assistant.",
|
|
89
|
-
"A previous implementation attempt for the phase below failed verification.",
|
|
90
|
-
"Your job is to fix exactly the issues listed in the failure notes and nothing more.",
|
|
91
|
-
"",
|
|
92
|
-
"## Failure notes from the verifier",
|
|
93
|
-
"",
|
|
94
|
-
"{{failureNotes}}",
|
|
95
|
-
"",
|
|
96
|
-
"---",
|
|
97
|
-
"",
|
|
98
|
-
"## Repositories in scope",
|
|
99
|
-
"",
|
|
100
|
-
"{{repoLines}}{{writableLines}}",
|
|
101
|
-
"",
|
|
102
|
-
"---",
|
|
103
|
-
"",
|
|
104
|
-
"## Full plan (for context)",
|
|
105
|
-
"",
|
|
106
|
-
"{{planContent}}",
|
|
107
|
-
"",
|
|
108
|
-
"---",
|
|
109
|
-
"",
|
|
110
|
-
"## Phase to repair",
|
|
111
|
-
"",
|
|
112
|
-
"### {{phaseTitle}}",
|
|
113
|
-
"",
|
|
114
|
-
"{{phaseBody}}",
|
|
115
|
-
"",
|
|
116
|
-
"---",
|
|
117
|
-
"",
|
|
118
|
-
"Fix only the issues described in the failure notes above. Make the minimum changes necessary to satisfy the failing criteria. When done, output a brief summary of what you changed.",
|
|
119
|
-
""
|
|
120
|
-
],
|
|
121
|
-
"commit": [
|
|
122
|
-
"You are Ralph's commit agent. A phase has been implemented and verified.",
|
|
123
|
-
"Your job is to decide which changed files belong to this phase and commit them.",
|
|
124
|
-
"",
|
|
125
|
-
"## Phase just completed",
|
|
126
|
-
"",
|
|
127
|
-
"### {{phaseTitle}}",
|
|
128
|
-
"",
|
|
129
|
-
"{{phaseBody}}",
|
|
130
|
-
"",
|
|
131
|
-
"---",
|
|
132
|
-
"",
|
|
133
|
-
"## Changed repositories",
|
|
134
|
-
"",
|
|
135
|
-
"{{repoSections}}",
|
|
136
|
-
"",
|
|
137
|
-
"---",
|
|
138
|
-
"",
|
|
139
|
-
"For each repository listed above, output a commit plan using EXACTLY this format (one block per repo):",
|
|
140
|
-
"",
|
|
141
|
-
" REPO: <repo name>",
|
|
142
|
-
" FILES:",
|
|
143
|
-
" - <relative/path/to/file>",
|
|
144
|
-
" COMMIT: ralph: <imperative summary, max 72 chars>",
|
|
145
|
-
" DESCRIPTION:",
|
|
146
|
-
" - <bullet: what changed and why — focus on intent, not mechanics>",
|
|
147
|
-
" - <add one bullet per logical group of changes>",
|
|
148
|
-
" END_COMMIT",
|
|
149
|
-
"",
|
|
150
|
-
"Rules:",
|
|
151
|
-
"- Only include files shown in the git status above that are relevant to this phase.",
|
|
152
|
-
"- Use paths exactly as shown in the git status output (relative to repo root).",
|
|
153
|
-
"- COMMIT line: start with \"ralph: \" then a short imperative verb phrase (≤72 chars total).",
|
|
154
|
-
"- DESCRIPTION bullets: explain *what* moved or changed and *why*, not line-by-line mechanics.",
|
|
155
|
-
"- If a repository has no files relevant to this phase, output: REPO: <name>\\nSKIP",
|
|
156
|
-
"- Do not output anything outside the structured REPO / END_COMMIT blocks.",
|
|
157
|
-
""
|
|
158
|
-
]
|
|
159
|
-
}
|