spec-and-loop 1.0.8 → 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/README.md CHANGED
@@ -4,53 +4,56 @@ OpenSpec + Ralph Loop integration for iterative development with opencode.
4
4
 
5
5
  ![CI Status](https://img.shields.io/github/actions/workflow/status/ncheaz/spec-and-loop/test.yml)
6
6
  ![Coverage](https://img.shields.io/badge/coverage-0%25-red)
7
- [![npm version](https://badge.fury.io/js/spec-and-loop.svg)](https://badge.fury.io/js/spec-and-loop)
7
+ [![npm version](https://badge.fury.io/js/spec-and-loop.svg)](https://badge.fury.io/js/spec-and-loop.svg)
8
8
 
9
- **[🚀 Quick Start Guide](./QUICKSTART.md)** - Get up and running in 5 minutes!
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. Ralph Wiggum's iterative development loop (execute → commit → repeat) is powerful but requires PRD format instead of OpenSpec specs.
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
- # Install OpenSpec and OpenCode (recommended)
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 (if you prefer):
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
- **[🚀 Get Started in 5 Minutes](./QUICKSTART.md)**
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. Fast-forward through artifact creation
53
- openspec ff add-user-auth
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
- **[📋 Testing Guide](./TESTING.md)** - Detailed instructions for running tests
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
- ```bash
177
- node --version # Should be >=24
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
- ```bash
182
- npm install -g @fission-ai/openspec@latest
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>` - Start a new change
213
- - `openspec ff <name>` - Fast-forward artifact creation
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
- - `ralph-run --change <name>` - Run the ralph loop for a specific change
221
- - `ralph-run` - Auto-detect most recent change and run
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 (for internal use)
258
- 3. **Task Execution**: For each incomplete task:
259
- - Generates context-rich prompt (task + specs + design + git history + errors)
260
- - Runs `opencode` with the prompt
261
- - Creates git commit with task description
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
- 4. **Completion**: All tasks done, errors cleared
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
- # See errors (if any failed)
275
- cat openspec/changes/my-feature/.ralph/errors.md
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. Plan feature with OpenSpec
282
- openspec new user-auth
283
- openspec ff user-auth
234
+ # 1. Initialize OpenSpec in your project
235
+ cd my-web-app
236
+ git init
237
+ openspec init
284
238
 
285
- # 2. Execute with Ralph
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
- # 3. Verify implementation
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
- | **Error Propagation** | Failures inform subsequent tasks |
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** | Inject custom instructions during execution |
312
-
313
- For detailed feature descriptions, see below.
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
- ### Ralph Wiggum + Agentic Coding
278
+ *Features available in spec-and-loop 2.0.0 with OpenSpec 1.2.0*
279
+
280
+ ### Mini Ralph Loop Engine
318
281
 
319
- - **Iterative refinement**: Each task builds on previous commits with full context
320
- - **Error propagation**: Failures inform subsequent iterations—don't repeat mistakes
321
- - **Granular history**: Commit per task makes debugging and rollback easy
322
- - **Context awareness**: AI sees proposal, specs, design, git history, and errors
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**: Inject custom instructions during execution
336
- - **Error recovery**: Errors propagate to guide subsequent tasks
337
- - **Bidirectional tracking**: Tasks.md and .ralph/tracking.json stay synced
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 during execution:
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
- # Create injection file
348
- echo "Use Redis instead of Memcached" > openspec/changes/my-feature/.ralph/.context_injection
335
+ ralph-run --status
336
+ ```
349
337
 
350
- # Next opencode invocation includes:
351
- ## Injected Context
352
- Use Redis instead of Memcached
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
- ### Manually Inject Context
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
- echo "Consider performance implications" > openspec/changes/my-feature/.ralph/.context_injection
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 Loop**: Iterative development with commits per task, error tracking
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
- - **Task description**: What to implement
386
- - **Proposal summary**: Why this change matters
387
- - **Relevant specs**: Requirements to satisfy
388
- - **Design decisions**: Architectural constraints
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
- Bidirectional synchronization:
395
- - **tasks.md**: Human-readable checkboxes `[ ]` → `[x]`
396
- - **.ralph/tracking.json**: Machine-readable state
397
- - **Atomic updates**: Both succeed or both fail
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
- └── specs/ # Your requirements
408
- ├── auth/
409
- │ └── spec.md
410
- └── api/
411
- └── spec.md
412
- └── .ralph/ # Internal state (auto-generated)
413
- ├── PRD.md # Generated from artifacts
414
- ├── tracking.json # Task completion state
415
- ├── errors.md # Failure history
416
- ├── context-injections.md # Manual injections log
417
- └── .context_injection # Pending injection
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 };