spec-and-loop 1.0.7 → 1.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/QUICKSTART.md +265 -53
- package/README.md +210 -175
- package/lib/mini-ralph/context.js +99 -0
- package/lib/mini-ralph/errors.js +112 -0
- package/lib/mini-ralph/history.js +99 -0
- package/lib/mini-ralph/index.js +93 -0
- package/lib/mini-ralph/invoker.js +243 -0
- package/lib/mini-ralph/prompt.js +116 -0
- package/lib/mini-ralph/runner.js +495 -0
- package/lib/mini-ralph/state.js +93 -0
- package/lib/mini-ralph/status.js +238 -0
- package/lib/mini-ralph/tasks.js +209 -0
- package/package.json +3 -3
- package/scripts/mini-ralph-cli.js +226 -0
- package/scripts/ralph-monitor.sh +53 -6
- package/scripts/ralph-run.sh +248 -71
- package/scripts/setup.js +39 -31
package/README.md
CHANGED
|
@@ -4,53 +4,56 @@ OpenSpec + Ralph Loop integration for iterative development with opencode.
|
|
|
4
4
|
|
|
5
5
|

|
|
6
6
|

|
|
7
|
-
[](https://badge.fury.io/js/spec-and-loop)
|
|
7
|
+
[](https://badge.fury.io/js/spec-and-loop.svg)
|
|
8
8
|
|
|
9
|
-
**
|
|
9
|
+
**Version:** spec-and-loop 2.0.0 + OpenSpec 1.2.0
|
|
10
|
+
|
|
11
|
+
**[Quick Start Guide](./QUICKSTART.md)** - Get up and running in 5 minutes!
|
|
10
12
|
|
|
11
13
|
## Why This Exists
|
|
12
14
|
|
|
13
|
-
OpenSpec provides excellent structure for planning (proposal → specs → design → tasks) but leaves execution manual.
|
|
15
|
+
OpenSpec provides excellent structure for planning (proposal → specs → design → tasks) but leaves execution manual. This package provides an iterative development loop — execute → commit → repeat — driven by an internal mini Ralph implementation that works with OpenCode and eliminates the need for any external Ralph runtime.
|
|
16
|
+
|
|
17
|
+
The runtime prompt is self-contained: it does not depend on Cursor-only slash commands or editor-local skills.
|
|
18
|
+
|
|
19
|
+
**Version Requirements:** This documentation applies to OpenSpec 1.2.0 and spec-and-loop 2.0.0.
|
|
14
20
|
|
|
15
21
|
## Installation
|
|
16
22
|
|
|
17
23
|
```bash
|
|
18
|
-
npm install -g spec-and-loop
|
|
24
|
+
npm install -g spec-and-loop@2.0.0
|
|
19
25
|
```
|
|
20
26
|
|
|
21
27
|
**Prerequisites:** You need OpenSpec and the OpenCode AI agent installed:
|
|
22
28
|
|
|
23
29
|
```bash
|
|
24
|
-
|
|
25
|
-
npm install -g @fission-ai/openspec@latest opencode-ai
|
|
30
|
+
npm install -g @fission-ai/openspec@1.2.0 opencode-ai
|
|
26
31
|
```
|
|
27
32
|
|
|
28
|
-
Alternative OpenCode install methods
|
|
33
|
+
Alternative OpenCode install methods:
|
|
29
34
|
|
|
30
35
|
```bash
|
|
31
|
-
# npm (recommended)
|
|
32
|
-
npm install -g opencode-ai
|
|
33
|
-
|
|
34
36
|
# Install script (general use)
|
|
35
37
|
curl -fsSL https://opencode.ai/install | bash
|
|
36
38
|
|
|
37
39
|
# Homebrew (macOS / Linux)
|
|
38
40
|
brew install anomalyco/tap/opencode
|
|
39
|
-
|
|
40
|
-
# Windows: use WSL and install via one of the Linux methods above
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
**[
|
|
43
|
+
**[Get Started in 5 Minutes](./QUICKSTART.md)**
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
46
|
# 1. Initialize OpenSpec in your project
|
|
47
47
|
openspec init
|
|
48
48
|
|
|
49
49
|
# 2. Create a new change
|
|
50
|
-
openspec new add-user-auth
|
|
50
|
+
openspec new change add-user-auth
|
|
51
51
|
|
|
52
|
-
# 3.
|
|
53
|
-
openspec
|
|
52
|
+
# 3. Review and complete the OpenSpec artifacts
|
|
53
|
+
# (openspec/changes/add-user-auth/proposal.md)
|
|
54
|
+
# (openspec/changes/add-user-auth/design.md)
|
|
55
|
+
# (openspec/changes/add-user-auth/specs/*/spec.md)
|
|
56
|
+
# (openspec/changes/add-user-auth/tasks.md)
|
|
54
57
|
|
|
55
58
|
# 4. Run the ralph loop (executes tasks with opencode)
|
|
56
59
|
ralph-run --change add-user-auth
|
|
@@ -58,13 +61,13 @@ ralph-run --change add-user-auth
|
|
|
58
61
|
|
|
59
62
|
For detailed step-by-step instructions, see [QUICKSTART.md](./QUICKSTART.md).
|
|
60
63
|
|
|
61
|
-
<!-- Duplicate Quick Start removed; see QUICKSTART.md for full instructions -->
|
|
62
|
-
|
|
63
64
|
## Testing
|
|
64
65
|
|
|
66
|
+
*Testing suite for spec-and-loop 2.0.0*
|
|
67
|
+
|
|
65
68
|
Spec-and-loop includes a comprehensive test suite to ensure reliability and cross-platform compatibility.
|
|
66
69
|
|
|
67
|
-
**[
|
|
70
|
+
**[Testing Guide](./TESTING.md)** - Detailed instructions for running tests
|
|
68
71
|
|
|
69
72
|
### Quick Test Commands
|
|
70
73
|
|
|
@@ -93,98 +96,24 @@ npm run lint
|
|
|
93
96
|
|
|
94
97
|
All tests are run automatically via GitHub Actions on every push and pull request.
|
|
95
98
|
|
|
96
|
-
### CI/CD Workflow
|
|
97
|
-
|
|
98
|
-
The CI/CD pipeline is defined in `.github/workflows/test.yml` and performs the following steps:
|
|
99
|
-
|
|
100
|
-
1. **Checkout Code**: Pulls the latest code from the repository
|
|
101
|
-
2. **Setup Node.js**: Installs Node.js version 24 with npm caching
|
|
102
|
-
3. **Install System Dependencies**:
|
|
103
|
-
- Linux: `apt-get install bats-core jq shellcheck`
|
|
104
|
-
- macOS: `brew install bats-core jq shellcheck`
|
|
105
|
-
4. **Install npm Dependencies**: Runs `npm ci` to install dependencies
|
|
106
|
-
5. **Install Global CLIs**: Installs openspec, ralph, and opencode globally
|
|
107
|
-
6. **Run Shellcheck Linting**: Checks bash scripts for errors and best practices
|
|
108
|
-
7. **Run Unit Tests**: Executes bash and JavaScript unit tests
|
|
109
|
-
8. **Run Integration Tests**: Validates full workflow end-to-end
|
|
110
|
-
9. **Upload Artifacts**: Uploads test logs and coverage reports
|
|
111
|
-
|
|
112
|
-
### Triggering CI/CD
|
|
113
|
-
|
|
114
|
-
The workflow runs automatically on:
|
|
115
|
-
- Push to `main` or `develop` branches
|
|
116
|
-
- Pull requests to `main` or `develop` branches
|
|
117
|
-
- Manual trigger via GitHub Actions UI
|
|
118
|
-
|
|
119
|
-
To manually trigger:
|
|
120
|
-
1. Go to Actions tab in GitHub
|
|
121
|
-
2. Select "Test Suite" workflow
|
|
122
|
-
3. Click "Run workflow"
|
|
123
|
-
4. Select branch and test suite (all/unit/integration)
|
|
124
|
-
|
|
125
|
-
### Troubleshooting CI/CD
|
|
126
|
-
|
|
127
|
-
**Tests Failing on One Platform**
|
|
128
|
-
|
|
129
|
-
If tests pass on Linux but fail on macOS (or vice versa):
|
|
130
|
-
- Check for platform-specific command differences (GNU vs BSD tools)
|
|
131
|
-
- Review platform-specific tests in `test-symlink-linux.bats`, `test-symlink-macos.bats`, etc.
|
|
132
|
-
- Verify stat, md5sum/md5, and other commands use correct flags
|
|
133
|
-
|
|
134
|
-
**Coverage Below Threshold**
|
|
135
|
-
|
|
136
|
-
If coverage drops below 80%:
|
|
137
|
-
- Review coverage reports uploaded as artifacts
|
|
138
|
-
- Identify which functions lost coverage
|
|
139
|
-
- Add tests to cover the missing code paths
|
|
140
|
-
|
|
141
|
-
**Linting Failures**
|
|
142
|
-
|
|
143
|
-
If shellcheck finds issues:
|
|
144
|
-
- Review the warnings in the CI logs
|
|
145
|
-
- Fix the issues locally: `npm run lint`
|
|
146
|
-
- Commit the fixes
|
|
147
|
-
|
|
148
|
-
**Timeout Issues**
|
|
149
|
-
|
|
150
|
-
If tests timeout:
|
|
151
|
-
- Integration tests may take longer than expected
|
|
152
|
-
- Check for infinite loops or hanging processes
|
|
153
|
-
- Review test fixture setup/teardown
|
|
154
|
-
|
|
155
|
-
**Artifact Access**
|
|
156
|
-
|
|
157
|
-
Download test logs and coverage reports:
|
|
158
|
-
1. Go to the failed workflow run
|
|
159
|
-
2. Scroll to "Artifacts" section
|
|
160
|
-
3. Download relevant artifacts (test logs, coverage reports)
|
|
161
|
-
4. Analyze locally to identify issues
|
|
162
|
-
|
|
163
|
-
### Test Coverage
|
|
164
|
-
|
|
165
|
-
Critical functions have >80% test coverage. View detailed coverage reports:
|
|
166
|
-
```bash
|
|
167
|
-
npm run test:coverage
|
|
168
|
-
open coverage/index.html
|
|
169
|
-
```
|
|
170
|
-
|
|
171
99
|
## Prerequisites
|
|
172
100
|
|
|
101
|
+
*Required for spec-and-loop 2.0.0 with OpenSpec 1.2.0*
|
|
102
|
+
|
|
173
103
|
Before using spec-and-loop, ensure you have:
|
|
174
104
|
|
|
175
|
-
1. **Node.js** - For package installation
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
105
|
+
1. **Node.js** - For package installation (requires >=24.0.0)
|
|
106
|
+
```bash
|
|
107
|
+
node --version # Should be >=24.0.0
|
|
108
|
+
```
|
|
179
109
|
|
|
180
|
-
2. **openspec** - OpenSpec CLI for specification workflow
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
110
|
+
2. **openspec** - OpenSpec CLI for specification workflow (requires 1.2.0)
|
|
111
|
+
```bash
|
|
112
|
+
npm install -g @fission-ai/openspec@1.2.0
|
|
113
|
+
```
|
|
184
114
|
|
|
185
115
|
3. **opencode** - Agentic coding assistant
|
|
186
116
|
```bash
|
|
187
|
-
# Install via npm
|
|
188
117
|
npm install -g opencode-ai
|
|
189
118
|
```
|
|
190
119
|
|
|
@@ -206,27 +135,40 @@ For complete installation instructions, see [QUICKSTART.md](./QUICKSTART.md).
|
|
|
206
135
|
|
|
207
136
|
## Commands
|
|
208
137
|
|
|
138
|
+
*Documentation applies to OpenSpec 1.2.0 and spec-and-loop 2.0.0*
|
|
139
|
+
|
|
209
140
|
### OpenSpec Commands
|
|
210
141
|
|
|
211
142
|
- `openspec init` - Initialize OpenSpec in current directory
|
|
212
|
-
- `openspec new <name>` -
|
|
213
|
-
- `openspec
|
|
214
|
-
- `openspec continue <name>` - Continue working on change
|
|
215
|
-
- `openspec apply <name>` - Apply change (implementation)
|
|
216
|
-
- `openspec archive <name>` - Archive a completed change
|
|
143
|
+
- `openspec new change <name>` - Create a new change with artifact templates
|
|
144
|
+
- `openspec --help` - View all available commands and their syntax
|
|
217
145
|
|
|
218
146
|
### Ralph Loop Commands
|
|
219
147
|
|
|
220
|
-
|
|
221
|
-
|
|
148
|
+
```
|
|
149
|
+
ralph-run [OPTIONS]
|
|
150
|
+
|
|
151
|
+
OPTIONS:
|
|
152
|
+
--change <name> Specify the OpenSpec change to execute (default: auto-detect)
|
|
153
|
+
--max-iterations <n> Maximum iterations for Ralph loop (default: 50)
|
|
154
|
+
--no-commit Suppress automatic git commits during the loop
|
|
155
|
+
--verbose, -v Enable verbose mode for debugging
|
|
156
|
+
--help, -h Show this help message
|
|
157
|
+
|
|
158
|
+
OBSERVABILITY AND CONTROL:
|
|
159
|
+
--status Print the current loop status dashboard and exit
|
|
160
|
+
--add-context <text> Add pending context to inject into the next iteration and exit
|
|
161
|
+
--clear-context Clear any pending context and exit
|
|
162
|
+
```
|
|
222
163
|
|
|
223
164
|
## How It Works
|
|
224
165
|
|
|
166
|
+
*Workflow for OpenSpec 1.2.0 + spec-and-loop 2.0.0*
|
|
167
|
+
|
|
225
168
|
### Step 1: Create Spec with OpenSpec
|
|
226
169
|
|
|
227
170
|
```bash
|
|
228
|
-
openspec new my-feature
|
|
229
|
-
openspec ff my-feature
|
|
171
|
+
openspec new change my-feature
|
|
230
172
|
```
|
|
231
173
|
|
|
232
174
|
This creates:
|
|
@@ -235,6 +177,8 @@ This creates:
|
|
|
235
177
|
- **design.md**: Technical decisions and architecture
|
|
236
178
|
- **tasks.md**: Implementation tasks as checkboxes
|
|
237
179
|
|
|
180
|
+
After creating the change, manually complete the OpenSpec artifacts by filling in proposal.md, design.md, specs/*/spec.md, and tasks.md.
|
|
181
|
+
|
|
238
182
|
**Example tasks.md:**
|
|
239
183
|
```markdown
|
|
240
184
|
## Implementation
|
|
@@ -253,47 +197,61 @@ ralph-run --change my-feature
|
|
|
253
197
|
|
|
254
198
|
**What happens:**
|
|
255
199
|
|
|
256
|
-
1. **Validation**: Checks for required OpenSpec artifacts
|
|
257
|
-
2. **PRD Generation**: Converts proposal + specs + design → PRD format
|
|
258
|
-
3. **
|
|
259
|
-
|
|
260
|
-
-
|
|
261
|
-
-
|
|
200
|
+
1. **Validation**: Checks for required OpenSpec artifacts and git repository
|
|
201
|
+
2. **PRD Generation**: Converts proposal + specs + design → PRD format for internal use
|
|
202
|
+
3. **Setup**: Creates .ralph directory, syncs tasks symlink, and sets up output capture
|
|
203
|
+
4. **Task Execution**: For each incomplete task:
|
|
204
|
+
- Generates context-rich prompt (full OpenSpec artifacts + a fresh task snapshot + recent loop signals)
|
|
205
|
+
- Runs `opencode` with the prompt via the internal mini Ralph engine
|
|
206
|
+
- Captures output to temp directory for review and debugging
|
|
207
|
+
- Logs any errors to `.ralph/errors.md` with timestamps
|
|
208
|
+
- Creates git commit with task description (unless `--no-commit`)
|
|
262
209
|
- Marks task complete in tasks.md
|
|
263
|
-
|
|
210
|
+
5. **Cleanup**: Automatically removes old output directories (older than 7 days)
|
|
211
|
+
6. **Completion**: All tasks done
|
|
264
212
|
|
|
265
213
|
### Step 3: Monitor Progress
|
|
266
214
|
|
|
267
215
|
```bash
|
|
216
|
+
# Check loop status
|
|
217
|
+
ralph-run --status
|
|
218
|
+
|
|
268
219
|
# Check remaining tasks
|
|
269
220
|
grep "^- \[ \]" openspec/changes/my-feature/tasks.md
|
|
270
221
|
|
|
271
222
|
# View git commits
|
|
272
223
|
git log --oneline
|
|
273
224
|
|
|
274
|
-
#
|
|
275
|
-
|
|
225
|
+
# Inject context into next iteration
|
|
226
|
+
ralph-run --add-context "Prefer async/await over callbacks"
|
|
276
227
|
```
|
|
277
228
|
|
|
278
229
|
## Example Workflow
|
|
279
230
|
|
|
231
|
+
*Example workflow for OpenSpec 1.2.0 and spec-and-loop 2.0.0*
|
|
232
|
+
|
|
280
233
|
```bash
|
|
281
|
-
# 1.
|
|
282
|
-
|
|
283
|
-
|
|
234
|
+
# 1. Initialize OpenSpec in your project
|
|
235
|
+
cd my-web-app
|
|
236
|
+
git init
|
|
237
|
+
openspec init
|
|
284
238
|
|
|
285
|
-
# 2.
|
|
239
|
+
# 2. Create a new change
|
|
240
|
+
openspec new change user-auth
|
|
241
|
+
|
|
242
|
+
# 3. Complete OpenSpec artifacts manually or use opencode skills
|
|
243
|
+
# (review and fill in proposal.md, design.md, specs/*/spec.md, tasks.md)
|
|
244
|
+
|
|
245
|
+
# 4. Execute with Ralph
|
|
286
246
|
ralph-run --change user-auth
|
|
287
247
|
|
|
288
248
|
# Output:
|
|
289
249
|
# [INFO] Found 15 tasks to execute
|
|
290
250
|
# [INFO] Executing task 1/15: Create User model with password field
|
|
291
|
-
# ✓ Complete
|
|
292
251
|
# [INFO] Executing task 2/15: Implement password hashing
|
|
293
|
-
# ✓ Complete
|
|
294
252
|
# ...
|
|
295
253
|
|
|
296
|
-
#
|
|
254
|
+
# 5. Verify implementation
|
|
297
255
|
git log --oneline # 15 commits, one per task
|
|
298
256
|
git diff HEAD~15 # See full implementation
|
|
299
257
|
```
|
|
@@ -305,21 +263,33 @@ git diff HEAD~15 # See full implementation
|
|
|
305
263
|
| **Structured Planning** | OpenSpec workflow: proposal → specs → design → tasks |
|
|
306
264
|
| **Agentic Execution** | opencode executes tasks with full context |
|
|
307
265
|
| **Iterative Loop** | Each task builds on previous commits |
|
|
308
|
-
| **
|
|
266
|
+
| **Iteration Feedback** | Recent failures and no-progress iterations inform the next pass |
|
|
309
267
|
| **Granular History** | One git commit per task |
|
|
310
|
-
| **Auto-Resume** | Interrupted? Run again—picks up where left off |
|
|
311
|
-
| **Context Injection** |
|
|
312
|
-
|
|
313
|
-
|
|
268
|
+
| **Auto-Resume** | Interrupted? Run again — picks up where left off |
|
|
269
|
+
| **Context Injection** | `--add-context` injects guidance into the next iteration |
|
|
270
|
+
| **Loop Status** | `--status` shows active state, history, and struggle indicators |
|
|
271
|
+
| **Error Tracking** | Automatic error logging and archiving for debugging |
|
|
272
|
+
| **Output Capture** | Loop output captured to temp directories for review |
|
|
273
|
+
| **Cross-Platform** | Full support for Linux and macOS with portable operations |
|
|
274
|
+
| **No External Ralph** | Self-contained mini Ralph engine — no external `ralph` CLI needed |
|
|
314
275
|
|
|
315
276
|
## Features
|
|
316
277
|
|
|
317
|
-
|
|
278
|
+
*Features available in spec-and-loop 2.0.0 with OpenSpec 1.2.0*
|
|
279
|
+
|
|
280
|
+
### Mini Ralph Loop Engine
|
|
318
281
|
|
|
319
|
-
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
- **
|
|
282
|
+
`spec-and-loop` includes a first-party mini Ralph implementation (`lib/mini-ralph/`) that
|
|
283
|
+
provides the core iterative loop without any external Ralph dependency:
|
|
284
|
+
|
|
285
|
+
- **Iterative execution**: Each task builds on previous commits with full context
|
|
286
|
+
- **State and history**: Loop state, iteration history, and struggle indicators stored in each change's `.ralph/`
|
|
287
|
+
- **Prompt templates**: Context-aware prompts generated from OpenSpec artifacts
|
|
288
|
+
- **Completion promises**: Loop exits when a completion signal is detected
|
|
289
|
+
- **Task progression**: Synchronized with `tasks.md` checkboxes as the source of truth
|
|
290
|
+
|
|
291
|
+
The supported subset intentionally excludes upstream features that are out of scope for
|
|
292
|
+
this repository's OpenSpec-first workflow (multi-agent rotation, plugin toggles, etc.).
|
|
323
293
|
|
|
324
294
|
### OpenSpec + opencode Synergy
|
|
325
295
|
|
|
@@ -331,25 +301,49 @@ For detailed feature descriptions, see below.
|
|
|
331
301
|
|
|
332
302
|
### Script Features
|
|
333
303
|
|
|
334
|
-
- **Auto-resume**: Interrupted? Run again—picks up where left off
|
|
335
|
-
- **Context injection**:
|
|
336
|
-
- **Error recovery**:
|
|
337
|
-
- **
|
|
304
|
+
- **Auto-resume**: Interrupted? Run again — picks up where left off
|
|
305
|
+
- **Context injection**: `--add-context` / `--clear-context` via each change's `.ralph/ralph-context.md`
|
|
306
|
+
- **Error recovery**: Recent loop signals help guide subsequent tasks
|
|
307
|
+
- **Error tracking**: Automatic error logging to `.ralph/errors.md` with timestamps and archiving
|
|
308
|
+
- **Task synchronization**: `tasks.md` and the per-change `.ralph/ralph-tasks.md` symlink stay in sync
|
|
309
|
+
- **Output capture**: Loop output captured to temp directories for review and debugging
|
|
310
|
+
- **Cross-platform**: Portable operations for Linux and macOS (stat, md5sum, realpath)
|
|
311
|
+
- **Cleanup**: Automatic cleanup of old output directories (older than 7 days)
|
|
338
312
|
- **Idempotent**: Run multiple times safely
|
|
339
313
|
|
|
340
314
|
## Advanced Usage
|
|
341
315
|
|
|
316
|
+
*Advanced features for spec-and-loop 2.0.0*
|
|
317
|
+
|
|
342
318
|
### Context Injection
|
|
343
319
|
|
|
344
|
-
Inject custom instructions
|
|
320
|
+
Inject custom instructions into the next iteration:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
ralph-run --add-context "Use Redis instead of Memcached"
|
|
324
|
+
|
|
325
|
+
# Check current pending context
|
|
326
|
+
ralph-run --status
|
|
327
|
+
|
|
328
|
+
# Clear pending context
|
|
329
|
+
ralph-run --clear-context
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Loop Status Dashboard
|
|
345
333
|
|
|
346
334
|
```bash
|
|
347
|
-
|
|
348
|
-
|
|
335
|
+
ralph-run --status
|
|
336
|
+
```
|
|
349
337
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
338
|
+
Shows: active loop state, current task, prompt summary, pending context, iteration history,
|
|
339
|
+
and struggle indicators if the loop appears stuck.
|
|
340
|
+
|
|
341
|
+
### No-Commit Mode
|
|
342
|
+
|
|
343
|
+
Run without automatic git commits (useful for reviewing changes before committing):
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
ralph-run --change my-feature --no-commit
|
|
353
347
|
```
|
|
354
348
|
|
|
355
349
|
### Verbose Mode
|
|
@@ -366,36 +360,52 @@ ralph-run --verbose --change my-feature
|
|
|
366
360
|
cat openspec/changes/my-feature/.ralph/PRD.md
|
|
367
361
|
```
|
|
368
362
|
|
|
369
|
-
###
|
|
363
|
+
### Review Loop Output
|
|
364
|
+
|
|
365
|
+
```bash
|
|
366
|
+
# Find the latest output directory path
|
|
367
|
+
cat openspec/changes/my-feature/.ralph/.output_dir
|
|
368
|
+
|
|
369
|
+
# View stdout and stderr logs
|
|
370
|
+
cat openspec/changes/my-feature/.ralph/.output_dir/ralph-stdout.log
|
|
371
|
+
cat openspec/changes/my-feature/.ralph/.output_dir/ralph-stderr.log
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
Output is captured to temporary directories for debugging. Old output directories are automatically cleaned up after 7 days.
|
|
375
|
+
|
|
376
|
+
### View Error Logs
|
|
370
377
|
|
|
371
378
|
```bash
|
|
372
|
-
|
|
379
|
+
# View recent errors
|
|
380
|
+
cat openspec/changes/my-feature/.ralph/errors.md
|
|
381
|
+
|
|
382
|
+
# Archived errors are saved with timestamps
|
|
383
|
+
ls openspec/changes/my-feature/.ralph/errors_*.md
|
|
373
384
|
```
|
|
374
385
|
|
|
375
386
|
## Architecture
|
|
376
387
|
|
|
388
|
+
*Architecture for spec-and-loop 2.0.0 with OpenSpec 1.2.0*
|
|
389
|
+
|
|
377
390
|
This package integrates:
|
|
378
391
|
- **OpenSpec**: Structured specification workflow
|
|
379
392
|
- **opencode**: Agentic coding assistant for task execution
|
|
380
|
-
- **Ralph
|
|
393
|
+
- **Mini Ralph** (`lib/mini-ralph/`): Internal iterative loop engine
|
|
381
394
|
|
|
382
395
|
### Context Propagation
|
|
383
396
|
|
|
384
397
|
Each task execution includes:
|
|
385
|
-
- **
|
|
386
|
-
- **
|
|
387
|
-
- **
|
|
388
|
-
- **
|
|
389
|
-
- **Git history**: Last 10 commits (what's already done)
|
|
390
|
-
- **Previous errors**: What failed before (to avoid repeating)
|
|
398
|
+
- **OpenSpec artifacts**: Proposal, design, and spec content from the generated PRD
|
|
399
|
+
- **Fresh task snapshot**: Raw `tasks.md` content plus the current task and completed-task summary rendered each iteration
|
|
400
|
+
- **Recent loop signals**: Compact reminders about prior failed or no-progress iterations
|
|
401
|
+
- **Pending context**: Any `--add-context` injection
|
|
391
402
|
|
|
392
403
|
### Task Tracking
|
|
393
404
|
|
|
394
|
-
|
|
395
|
-
- **tasks.md**: Human-readable checkboxes `[ ]` → `[x]`
|
|
396
|
-
- **.ralph/
|
|
397
|
-
- **Atomic updates**:
|
|
398
|
-
- **Stable IDs**: Line numbers persist across script runs
|
|
405
|
+
Synchronized tracking:
|
|
406
|
+
- **tasks.md**: Human-readable checkboxes `[ ]` → `[x]` (source of truth)
|
|
407
|
+
- **.ralph/ralph-tasks.md**: Symlink to `tasks.md` for the loop engine
|
|
408
|
+
- **Atomic updates**: Checkboxes updated after each completed task
|
|
399
409
|
|
|
400
410
|
### File Structure
|
|
401
411
|
|
|
@@ -403,22 +413,48 @@ Bidirectional synchronization:
|
|
|
403
413
|
openspec/changes/<name>/
|
|
404
414
|
├── proposal.md # Your "why"
|
|
405
415
|
├── design.md # Your "how"
|
|
406
|
-
├── tasks.md # Your "what" (checkboxes)
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
└── .ralph/
|
|
413
|
-
├── PRD.md # Generated
|
|
414
|
-
├──
|
|
415
|
-
├──
|
|
416
|
-
├──
|
|
417
|
-
|
|
416
|
+
├── tasks.md # Your "what" (checkboxes, source of truth)
|
|
417
|
+
├── specs/ # Your requirements
|
|
418
|
+
│ ├── auth/
|
|
419
|
+
│ │ └── spec.md
|
|
420
|
+
│ └── api/
|
|
421
|
+
│ └── spec.md
|
|
422
|
+
└── .ralph/ # Internal loop state (auto-generated, per change)
|
|
423
|
+
├── PRD.md # Generated product requirements document
|
|
424
|
+
├── prompt-template.md # Template used for generating prompts
|
|
425
|
+
├── ralph-history.json # Iteration history and state
|
|
426
|
+
├── ralph-loop.state.json # Current loop state and iteration count
|
|
427
|
+
├── ralph-tasks.md # Symlink to ../tasks.md (syncs task state)
|
|
428
|
+
├── .output_dir # Path to latest output capture directory
|
|
429
|
+
├── ralph-context.md # (Optional) Pending context for next iteration
|
|
430
|
+
├── errors.md # (Optional) Error logs with timestamps
|
|
431
|
+
├── errors_*.md # (Optional) Archived error logs
|
|
432
|
+
└── *.md # (Optional) Research artifacts created during task execution
|
|
418
433
|
```
|
|
419
434
|
|
|
435
|
+
**Note:** Files marked as (Optional) are created only when needed:
|
|
436
|
+
- `ralph-context.md`: Created when you use `--add-context`
|
|
437
|
+
- `errors.md` and `errors_*.md`: Created when errors occur during loop execution
|
|
438
|
+
- Additional `*.md` files: Research artifacts created by opencode during task execution (e.g., verification outputs, analysis documents)
|
|
439
|
+
|
|
440
|
+
### Cross-Platform Support
|
|
441
|
+
|
|
442
|
+
*Cross-platform support verified for spec-and-loop 2.0.0*
|
|
443
|
+
|
|
444
|
+
`spec-and-loop` is designed to work seamlessly on both Linux and macOS. The script includes portable implementations for:
|
|
445
|
+
|
|
446
|
+
- **File modification times**: Uses `stat -f %m` on macOS and `stat -c %Y` on Linux
|
|
447
|
+
- **MD5 hashing**: Supports both `md5sum` (Linux) and `md5 -q` (macOS)
|
|
448
|
+
- **Path resolution**: Falls back from `realpath` to `readlink -f` to manual path construction
|
|
449
|
+
- **Temp directories**: Uses `TMPDIR` environment variable or `/tmp` as fallback
|
|
450
|
+
- **Cleanup**: Portable `find` and `rm` operations for old output directories
|
|
451
|
+
|
|
452
|
+
All features work identically on both platforms without requiring platform-specific configuration.
|
|
453
|
+
|
|
420
454
|
## Troubleshooting
|
|
421
455
|
|
|
456
|
+
*Troubleshooting guide for spec-and-loop 2.0.0 with OpenSpec 1.2.0*
|
|
457
|
+
|
|
422
458
|
For common issues and solutions, see [QUICKSTART.md#troubleshooting](./QUICKSTART.md#troubleshooting).
|
|
423
459
|
|
|
424
460
|
**Quick fixes:**
|
|
@@ -440,7 +476,6 @@ export PATH="$PATH:$(npm root -g)/.bin"
|
|
|
440
476
|
## Resources
|
|
441
477
|
|
|
442
478
|
- [OpenSpec](https://openspec.ai) - Structured specification workflow
|
|
443
|
-
- [open-ralph-wiggum](https://github.com/Th0rgal/open-ralph-wiggum) - Iterative execution loop
|
|
444
479
|
- [opencode](https://opencode.ai) - Agentic coding assistant
|
|
445
480
|
|
|
446
481
|
## License
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* context.js - Pending context management for mini-ralph.
|
|
5
|
+
*
|
|
6
|
+
* Manages reading, writing, adding, clearing, and consuming pending context
|
|
7
|
+
* from .ralph/ralph-context.md. Context is injected into the next iteration's
|
|
8
|
+
* prompt and then consumed (removed) so it does not carry forward indefinitely.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
const CONTEXT_FILE = 'ralph-context.md';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Return the absolute path to the context file.
|
|
18
|
+
*
|
|
19
|
+
* @param {string} ralphDir
|
|
20
|
+
* @returns {string}
|
|
21
|
+
*/
|
|
22
|
+
function contextPath(ralphDir) {
|
|
23
|
+
return path.join(ralphDir, CONTEXT_FILE);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Read the current pending context. Returns empty string if none.
|
|
28
|
+
*
|
|
29
|
+
* @param {string} ralphDir
|
|
30
|
+
* @returns {string}
|
|
31
|
+
*/
|
|
32
|
+
function read(ralphDir) {
|
|
33
|
+
const file = contextPath(ralphDir);
|
|
34
|
+
if (!fs.existsSync(file)) return '';
|
|
35
|
+
return fs.readFileSync(file, 'utf8').trim();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Append text to the pending context file.
|
|
40
|
+
*
|
|
41
|
+
* @param {string} ralphDir
|
|
42
|
+
* @param {string} text
|
|
43
|
+
*/
|
|
44
|
+
function add(ralphDir, text) {
|
|
45
|
+
if (!text || !text.trim()) return;
|
|
46
|
+
_ensureDir(ralphDir);
|
|
47
|
+
const file = contextPath(ralphDir);
|
|
48
|
+
const existing = fs.existsSync(file) ? fs.readFileSync(file, 'utf8') : '';
|
|
49
|
+
const separator = existing && !existing.endsWith('\n') ? '\n\n' : (existing ? '\n' : '');
|
|
50
|
+
fs.writeFileSync(file, `${existing}${separator}${text.trim()}`, 'utf8');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Clear all pending context.
|
|
55
|
+
*
|
|
56
|
+
* @param {string} ralphDir
|
|
57
|
+
*/
|
|
58
|
+
function clear(ralphDir) {
|
|
59
|
+
const file = contextPath(ralphDir);
|
|
60
|
+
if (fs.existsSync(file)) {
|
|
61
|
+
fs.unlinkSync(file);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Read pending context and then clear it (consume it for one iteration).
|
|
67
|
+
* Returns the context string, or null if there was nothing pending.
|
|
68
|
+
*
|
|
69
|
+
* @param {string} ralphDir
|
|
70
|
+
* @returns {string|null}
|
|
71
|
+
*/
|
|
72
|
+
function consume(ralphDir) {
|
|
73
|
+
const text = read(ralphDir);
|
|
74
|
+
if (!text) return null;
|
|
75
|
+
clear(ralphDir);
|
|
76
|
+
return text;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Check whether there is pending context.
|
|
81
|
+
*
|
|
82
|
+
* @param {string} ralphDir
|
|
83
|
+
* @returns {boolean}
|
|
84
|
+
*/
|
|
85
|
+
function hasPending(ralphDir) {
|
|
86
|
+
return !!read(ralphDir);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
// Internal helpers
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
|
|
93
|
+
function _ensureDir(ralphDir) {
|
|
94
|
+
if (!fs.existsSync(ralphDir)) {
|
|
95
|
+
fs.mkdirSync(ralphDir, { recursive: true });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
module.exports = { read, add, clear, consume, hasPending, contextPath };
|