agentic-loop 3.14.1 → 3.16.1

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.
@@ -64,6 +64,12 @@ Help the user flesh out the idea through conversation:
64
64
  - Caching needed? How fresh must data be?
65
65
  - Database indexes: What will be queried/sorted frequently?
66
66
 
67
+ **Migration/Refactoring (IMPORTANT - ask if moving or restructuring code):**
68
+ - Source paths: Where does the code currently live?
69
+ - Destination paths: Where should it end up? (be explicit, not vague)
70
+ - Phases: What's the logical order? (move files → update imports → verify)
71
+ - Verification: What commands prove each phase worked?
72
+
67
73
  ### Step 3: Summarize Before Writing
68
74
 
69
75
  When you have enough information, summarize what you've learned:
@@ -132,6 +138,36 @@ Once the user confirms, write the idea file:
132
138
  - **Caching**: What can be cached? For how long?
133
139
  - **Database**: What indexes are needed?
134
140
 
141
+ ## Migration Mapping (if moving/restructuring code)
142
+ For refactoring or migration tasks, explicitly map source to destination:
143
+
144
+ | Source | Destination |
145
+ |--------|-------------|
146
+ | `~/Sites/old-project/src/` | `apps/new-location/src/` |
147
+ | `~/Sites/old-project/tests/` | `apps/new-location/tests/` |
148
+
149
+ ## Phases & Verification
150
+ Break complex work into phases with explicit verification commands:
151
+
152
+ ### Phase 1: [Name]
153
+ **What:** Description of what this phase accomplishes
154
+ **Exit Criteria:**
155
+ ```bash
156
+ # These commands must pass before phase is complete
157
+ test -d apps/new-location/src
158
+ cd apps/new-location && uv run pytest -x
159
+ cd apps/new-location && npm run build
160
+ ```
161
+
162
+ ### Phase 2: [Name]
163
+ **What:** Description
164
+ **Exit Criteria:**
165
+ ```bash
166
+ # Verification commands for phase 2
167
+ docker-compose config | grep -q 'service-name:'
168
+ curl -s http://localhost:8000/health | jq -e '.status == "ok"'
169
+ ```
170
+
135
171
  ## UI Mockup (if applicable)
136
172
  ```
137
173
  ┌─────────────────────────────────┐
@@ -190,6 +226,26 @@ A good idea file has:
190
226
  - **Specific solution** - Not vague ("improve UX") but concrete ("add inline validation")
191
227
  - **Scope boundaries** - What's explicitly out of scope?
192
228
  - **Architecture hints** - Where do files go? What patterns to follow?
229
+ - **Verification commands** - How do we know it worked? (executable commands, not prose)
230
+
231
+ ### Migration/Refactoring Ideas
232
+
233
+ For ideas that involve moving or restructuring code, MUST include:
234
+
235
+ 1. **Explicit path mapping** - Source → Destination for every directory
236
+ ```
237
+ ❌ "Move GOPA to apps folder"
238
+ ✅ "~/Sites/gopa/src/gopa/ → apps/gopa/src/gopa/"
239
+ ```
240
+
241
+ 2. **Phase-based verification** - Each phase has exit criteria with commands
242
+ ```
243
+ ❌ "Verify everything still works"
244
+ ✅ "cd apps/gopa && uv run pytest -x && uv run python -c 'from gopa.server import mcp'"
245
+ ```
246
+
247
+ 3. **Order of operations** - What must happen before what?
248
+ - Move files → Update imports → Update configs → Verify
193
249
 
194
250
  ### ASCII Art for UI
195
251
 
@@ -61,6 +61,8 @@ cat package.json 2>/dev/null | jq '{name, dependencies}' || true
61
61
  cat pyproject.toml 2>/dev/null | head -20 || true
62
62
  ```
63
63
 
64
+ Use the detected tech stack, test runners, and constraints when building each story — these go into each story's `techStack`, `constraints`, and `testing.runner` fields (not at the PRD root).
65
+
64
66
  Then say: "I'll create a PRD for: **{description}**
65
67
 
66
68
  Before I generate stories, quick questions:
@@ -101,6 +103,7 @@ Break the idea into small, executable stories:
101
103
  - Max 3-4 acceptance criteria per story
102
104
  - Max 10 stories (suggest phases if more needed)
103
105
  - If appending, start IDs from the next available number
106
+ - **Each story must include its own `techStack`, `constraints`, and `contextFiles`.** Include only what's relevant to that story — don't copy-paste identical context into every story.
104
107
 
105
108
  ### Step 5: Write Draft PRD
106
109
 
@@ -152,10 +155,13 @@ Does acceptanceCriteria include:
152
155
  - Query params → "Accepts ?page=N&limit=N"
153
156
  - Large datasets → "Database query uses index on [column]"
154
157
 
155
- #### 6e. Context (for frontend stories)
158
+ #### 6e. Context (for all stories)
156
159
  - Does `contextFiles` include the idea file (has ASCII mockups)?
157
160
  - Does `contextFiles` include styleguide (if exists)?
158
- - Is `testUrl` set?
161
+ - Does `techStack` include the relevant stack for this story?
162
+ - Does `constraints` include any rules this story must follow?
163
+ - For frontend: Is `testUrl` set?
164
+ - For frontend: Is `mcp` set to `["playwright", "devtools"]`?
159
165
 
160
166
  **Fix any issues you find:**
161
167
 
@@ -168,6 +174,9 @@ Does acceptanceCriteria include:
168
174
  | List endpoint missing pagination | Add pagination criteria to acceptanceCriteria |
169
175
  | Frontend missing contextFiles | Add idea file + styleguide paths |
170
176
  | Frontend missing testUrl | Add URL from config |
177
+ | Frontend missing mcp | Add `"mcp": ["playwright", "devtools"]` |
178
+ | Story missing techStack | Add relevant subset of detected tech |
179
+ | Story missing constraints | Add applicable rules for this story |
171
180
 
172
181
  ### Step 7: Reorder if Needed
173
182
 
@@ -229,45 +238,6 @@ Ralph will work through each story, running tests and committing as it goes."
229
238
  "status": "pending"
230
239
  },
231
240
 
232
- "originalContext": "docs/ideas/{feature-name}.md",
233
-
234
- "techStack": {
235
- "frontend": "{detected from package.json}",
236
- "backend": "{detected from pyproject.toml/go.mod}",
237
- "database": "{detected or asked}"
238
- },
239
-
240
- "testing": {
241
- "approach": "TDD",
242
- "unit": {
243
- "frontend": "{vitest|jest - detected from package.json}",
244
- "backend": "{pytest|go test - detected from project}"
245
- },
246
- "integration": "{playwright|cypress}",
247
- "e2e": "{playwright|cypress}",
248
- "coverage": {
249
- "minimum": 80,
250
- "enforced": false
251
- }
252
- },
253
-
254
- "architecture": {
255
- "frontend": "src/components",
256
- "backend": "src/api",
257
- "doNotCreate": ["new database tables without migration"]
258
- },
259
-
260
- "globalConstraints": [
261
- "All API calls must have error handling",
262
- "No console.log in production code",
263
- "Use existing UI components from src/components/ui"
264
- ],
265
-
266
- "testUsers": {
267
- "admin": {"email": "admin@test.com", "password": "test123"},
268
- "user": {"email": "user@test.com", "password": "test123"}
269
- },
270
-
271
241
  "metadata": {
272
242
  "createdAt": "ISO timestamp",
273
243
  "estimatedStories": 5,
@@ -282,6 +252,17 @@ Ralph will work through each story, running tests and committing as it goes."
282
252
  "priority": 1,
283
253
  "passes": false,
284
254
 
255
+ "techStack": {
256
+ "frontend": "{detected from package.json}",
257
+ "backend": "{detected from pyproject.toml/go.mod}",
258
+ "database": "{detected or asked}"
259
+ },
260
+
261
+ "constraints": [
262
+ "Rules that apply to this story",
263
+ "E.g. Use existing UI components from src/components/ui"
264
+ ],
265
+
285
266
  "files": {
286
267
  "create": ["paths to new files"],
287
268
  "modify": ["paths to existing files"],
@@ -299,6 +280,7 @@ Ralph will work through each story, running tests and committing as it goes."
299
280
  "testing": {
300
281
  "types": ["unit", "integration"],
301
282
  "approach": "TDD",
283
+ "runner": "vitest|jest|pytest|go test",
302
284
  "files": {
303
285
  "unit": ["src/components/Dashboard.test.tsx"],
304
286
  "integration": ["tests/integration/dashboard.test.ts"],
@@ -330,6 +312,10 @@ Ralph will work through each story, running tests and committing as it goes."
330
312
  "response": {"field": "type"}
331
313
  },
332
314
 
315
+ "testUsers": {
316
+ "admin": {"email": "admin@test.com", "password": "test123"}
317
+ },
318
+
333
319
  "prerequisites": [
334
320
  "Backend server running",
335
321
  "Database seeded"
@@ -358,19 +344,15 @@ Ralph will work through each story, running tests and committing as it goes."
358
344
 
359
345
  | Field | Required | Description |
360
346
  |-------|----------|-------------|
361
- | `feature` | Yes | Feature name, branch, status |
362
- | `originalContext` | Yes | Path to idea file (Claude reads this for full context) |
363
- | `techStack` | No | Technologies in use (auto-detect from project) |
364
- | `testing` | Yes | Testing strategy, tools, coverage requirements |
365
- | `architecture` | No | Directory structure, patterns, constraints |
366
- | `globalConstraints` | No | Rules that apply to ALL stories |
367
- | `testUsers` | No | Test accounts for auth flows |
368
- | `metadata` | Yes | Created date, complexity estimate |
347
+ | `feature` | Yes | Feature name, ideaFile, branch, status |
348
+ | `metadata` | Yes | Created date, estimated stories, complexity |
369
349
 
370
350
  **Note:** URLs come from `.ralph/config.json`, not the PRD. Use `{config.urls.backend}` in testSteps.
371
351
 
372
352
  ### Story-Level Fields
373
353
 
354
+ Each story is **self-contained** with all the context it needs. No global defaults — include only what's relevant to that story.
355
+
374
356
  | Field | Required | Description |
375
357
  |-------|----------|-------------|
376
358
  | `id` | Yes | Unique ID (TASK-001, TASK-002, etc.) |
@@ -378,16 +360,19 @@ Ralph will work through each story, running tests and committing as it goes."
378
360
  | `title` | Yes | Short description |
379
361
  | `priority` | No | Order of importance (1 = highest) |
380
362
  | `passes` | Yes | Always starts as `false` |
363
+ | `techStack` | Yes | Technologies relevant to this story (auto-detect from project) |
364
+ | `constraints` | No | Rules/constraints specific to this story |
381
365
  | `files` | Yes | create, modify, reuse arrays |
382
366
  | `acceptanceCriteria` | Yes | What must be true when done |
383
367
  | `errorHandling` | Yes | How to handle failures |
384
- | `testing` | Yes | Test types, approach, and files for this story |
368
+ | `testing` | Yes | Test types, approach, runner, and files for this story |
385
369
  | `testSteps` | Yes | Executable shell commands |
386
370
  | `testUrl` | Frontend | URL to verify the feature |
387
371
  | `mcp` | Frontend | MCP tools for verification |
388
372
  | `contextFiles` | No | Files Claude should read (idea files, styleguides) |
389
373
  | `skills` | No | Relevant skills with usage hints |
390
374
  | `apiContract` | Backend | Expected request/response format |
375
+ | `testUsers` | No | Test accounts (only for auth stories that need them) |
391
376
  | `prerequisites` | No | What must be running/ready |
392
377
  | `notes` | No | Human guidance for Claude |
393
378
  | `scale` | No | small, medium, large |
@@ -398,49 +383,22 @@ Ralph will work through each story, running tests and committing as it goes."
398
383
 
399
384
  ## Testing Strategy
400
385
 
401
- ### PRD-Level Testing Config
402
-
403
- Define the overall testing strategy for the feature. **Auto-detect tools from project config files:**
386
+ ### Story-Level Testing Config
404
387
 
405
- ```json
406
- "testing": {
407
- "approach": "TDD",
408
- "unit": {
409
- "frontend": "vitest",
410
- "backend": "pytest"
411
- },
412
- "integration": "playwright",
413
- "e2e": "playwright",
414
- "coverage": {
415
- "minimum": 80,
416
- "enforced": false
417
- }
418
- }
419
- ```
388
+ Each story defines its own testing configuration. **Auto-detect tools from project config files** and include the relevant runner in each story:
420
389
 
421
390
  **Detection hints:**
422
391
  - Check `package.json` for `vitest`, `jest`, `playwright`, `cypress`
423
392
  - Check `pyproject.toml` for `pytest`
424
393
  - Check `go.mod` for Go projects (use `go test`)
425
394
 
426
- | Field | Values | Description |
427
- |-------|--------|-------------|
428
- | `approach` | `TDD`, `test-after` | Write tests first (TDD) or after implementation |
429
- | `unit.frontend` | `vitest`, `jest` | Frontend unit test runner (detect from package.json) |
430
- | `unit.backend` | `pytest`, `go test` | Backend unit test runner (detect from project) |
431
- | `integration` | `playwright`, `cypress` | Integration test tool |
432
- | `e2e` | `playwright`, `cypress` | End-to-end test tool |
433
- | `coverage.minimum` | `0-100` | Minimum coverage percentage |
434
- | `coverage.enforced` | `true/false` | Fail if coverage not met |
435
-
436
- ### Story-Level Testing Config
437
-
438
- Specify what tests each story needs:
395
+ **Note:** Coverage thresholds (`minimum`, `enforced`) belong in `.ralph/config.json`, not in the PRD.
439
396
 
440
397
  ```json
441
398
  "testing": {
442
399
  "types": ["unit", "integration"],
443
400
  "approach": "TDD",
401
+ "runner": "vitest",
444
402
  "files": {
445
403
  "unit": ["src/components/Dashboard.test.tsx"],
446
404
  "integration": ["tests/integration/dashboard.test.ts"],
@@ -452,7 +410,8 @@ Specify what tests each story needs:
452
410
  | Field | Description |
453
411
  |-------|-------------|
454
412
  | `types` | Required test types: `unit`, `integration`, `e2e` |
455
- | `approach` | Override PRD-level approach for this story |
413
+ | `approach` | TDD or test-after for this story |
414
+ | `runner` | Test runner command (vitest, jest, pytest, go test — detected from project) |
456
415
  | `files.unit` | Unit test files to create |
457
416
  | `files.integration` | Integration test files to create |
458
417
  | `files.e2e` | E2E test files to create |
@@ -0,0 +1,48 @@
1
+ ---
2
+ description: Run PRD validation to check story quality, test coverage, and structure.
3
+ ---
4
+
5
+ # PRD Check
6
+
7
+ Run PRD validation on demand to check story quality, test coverage, and structure before starting the autonomous loop.
8
+
9
+ ## Instructions
10
+
11
+ When the user runs `/prd-check`, validate their PRD file.
12
+
13
+ ### Step 1: Check PRD Exists
14
+
15
+ ```bash
16
+ ls -la .ralph/prd.json 2>/dev/null || echo "NOT_FOUND"
17
+ ```
18
+
19
+ If no PRD exists, tell the user:
20
+ > No PRD found at `.ralph/prd.json`. Generate one first with `/idea` or `/prd`.
21
+
22
+ **STOP** if no PRD found.
23
+
24
+ ### Step 2: Run Validation (dry-run)
25
+
26
+ Run validation without auto-fix so you can present results and let the user decide:
27
+
28
+ ```bash
29
+ npx ralph prd-check --dry-run 2>&1
30
+ ```
31
+
32
+ ### Step 3: Present Results
33
+
34
+ Show the validation output to the user. If there are issues, summarize them clearly.
35
+
36
+ If issues were found, ask:
37
+ > "Would you like me to fix these issues in the PRD?"
38
+
39
+ **STOP and wait for user response.**
40
+
41
+ If the user says yes, read `.ralph/prd.json`, fix the issues following PRD best practices (executable testSteps with curl/pytest/playwright, apiContract for backends, testUrl for frontends, security criteria for auth stories, pagination for list endpoints), and write the fixed file back.
42
+
43
+ ## Notes
44
+
45
+ - This is the same validation that runs automatically at `ralph run` startup
46
+ - `--dry-run` skips auto-fix so you have control over what changes
47
+ - Custom checks in `.ralph/checks/prd/` are also evaluated
48
+ - Run this before `ralph run` to catch and fix issues interactively
package/README.md CHANGED
@@ -75,11 +75,14 @@ npx agentic-loop run # Execute PRDs autonomously
75
75
 
76
76
  > **Tip:** Use two terminals. Plan with Claude in one, run Ralph in the other.
77
77
 
78
+ For the full step-by-step walkthrough, see **[Getting Started](docs/GETTING-STARTED.md)**.
79
+
78
80
  ---
79
81
 
80
82
  ## Docs
81
83
 
82
- - **[Beginners Guide](docs/BEGINNERS.md)** - New to this? Start here (no coding experience required)
84
+ - **[Getting Started](docs/GETTING-STARTED.md)** - Full walkthrough from zero to your first loop run
85
+ - [Beginners Guide](docs/BEGINNERS.md) - New to this? Start here (no coding experience required)
83
86
  - [PRD Check](docs/PRD-CHECK.md) - Story validation before coding starts
84
87
  - [Code Check](docs/CODE-CHECK.md) - Verification pipeline after each story
85
88
  - [Customization](docs/CUSTOMIZATION.md) - Personalization and guardrails
package/bin/ralph.sh CHANGED
@@ -148,6 +148,9 @@ main() {
148
148
  check)
149
149
  ralph_check "$@"
150
150
  ;;
151
+ prd-check|prdcheck)
152
+ ralph_prd_check "$@"
153
+ ;;
151
154
  verify)
152
155
  if [[ $# -lt 1 ]]; then
153
156
  print_error "Usage: ralph verify <story-id>"
@@ -6,6 +6,8 @@ interface Story {
6
6
  acceptanceCriteria: string[];
7
7
  testSteps: string[];
8
8
  status: 'pending' | 'in_progress' | 'completed' | 'failed';
9
+ techStack?: Record<string, string>;
10
+ constraints?: string[];
9
11
  }
10
12
  /**
11
13
  * Generate PRD stories from a conversation
@@ -1 +1 @@
1
- {"version":3,"file":"prd-generator.d.ts","sourceRoot":"","sources":["../../src/loopgram/prd-generator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAI1C,UAAU,KAAK;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,WAAW,GAAG,QAAQ,CAAC;CAC5D;AAmCD;;GAEG;AACH,wBAAsB,eAAe,CACnC,YAAY,EAAE,OAAO,EAAE,EACvB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,KAAK,EAAE,CAAA;CAAE,CAAC,CAwChF;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,kBAAkB,EAAE,MAAM,EAC1B,UAAU,EAAE,KAAK,EAAE,GAClB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA4CnD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG;IACjD,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,IAAI,CAwBP"}
1
+ {"version":3,"file":"prd-generator.d.ts","sourceRoot":"","sources":["../../src/loopgram/prd-generator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAI1C,UAAU,KAAK;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAqCD;;GAEG;AACH,wBAAsB,eAAe,CACnC,YAAY,EAAE,OAAO,EAAE,EACvB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,KAAK,EAAE,CAAA;CAAE,CAAC,CAwChF;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,kBAAkB,EAAE,MAAM,EAC1B,UAAU,EAAE,KAAK,EAAE,GAClB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA4CnD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG;IACjD,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,IAAI,CAwBP"}
@@ -15,6 +15,8 @@ Output ONLY valid JSON in this exact format:
15
15
  "id": "kebab-case-id",
16
16
  "title": "Short title",
17
17
  "description": "What needs to be built",
18
+ "techStack": {"backend": "detected tech"},
19
+ "constraints": ["relevant rules for this story"],
18
20
  "acceptanceCriteria": ["Criterion 1", "Criterion 2"],
19
21
  "testSteps": ["npm test", "npm run lint"]
20
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"prd-generator.js","sourceRoot":"","sources":["../../src/loopgram/prd-generator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prd-generator.js","sourceRoot":"","sources":["../../src/loopgram/prd-generator.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-loop",
3
- "version": "3.14.1",
3
+ "version": "3.16.1",
4
4
  "description": "Autonomous AI coding loop - PRD-driven development with Claude Code",
5
5
  "author": "Allie Jones <allie@allthrive.ai>",
6
6
  "license": "MIT",
@@ -21,7 +21,7 @@ if [[ "$FILE_PATH" == *"prd.json"* ]]; then
21
21
  exit 2 # Exit code 2 = blocking error
22
22
  fi
23
23
 
24
- # Allow all other prd.json edits (adding mcp, originalContext, fixing testSteps, etc.)
24
+ # Allow all other prd.json edits (adding mcp, constraints, fixing testSteps, etc.)
25
25
  echo '{"continue": true}'
26
26
  exit 0
27
27
  fi
package/ralph/loop.sh CHANGED
@@ -181,9 +181,9 @@ run_loop() {
181
181
  local consecutive_timeouts=0
182
182
  local max_story_retries
183
183
  local max_timeouts=5 # Skip after 5 consecutive timeouts (likely too large/complex)
184
- # Default to 15 retries - generous enough for transient issues, catches infinite loops
185
- # Override with config.json: "maxStoryRetries": 25
186
- max_story_retries=$(get_config '.maxStoryRetries' "15")
184
+ # Default to 8 retries - enough for transient issues, catches infinite loops
185
+ # Override with config.json: "maxStoryRetries": 12
186
+ max_story_retries=$(get_config '.maxStoryRetries' "8")
187
187
  local total_attempts=0
188
188
  local skipped_stories=()
189
189
  local start_time
@@ -265,7 +265,7 @@ run_loop() {
265
265
  "$RALPH_DIR/prd.json" > "$RALPH_DIR/prd.json.tmp" && mv "$RALPH_DIR/prd.json.tmp" "$RALPH_DIR/prd.json"
266
266
 
267
267
  # Circuit breaker: skip to next story after max retries (prevents infinite loops)
268
- # Note: This is NOT meant to stop legitimate retrying - 15 attempts is generous.
268
+ # Note: This is NOT meant to stop legitimate retrying - 8 attempts is enough.
269
269
  # If a story consistently fails after this many tries, it likely needs manual review
270
270
  # (vague test steps, missing prerequisites, or fundamentally broken requirements).
271
271
  if [[ $consecutive_failures -gt $max_story_retries ]]; then
@@ -381,23 +381,42 @@ run_loop() {
381
381
  fi
382
382
 
383
383
  # Run Claude with crash detection and retry logic
384
- local claude_output_log claude_exit_code max_crash_retries=3 crash_attempt=0
384
+ local claude_output_log claude_exit_code max_crash_retries=5 crash_attempt=0
385
385
  claude_output_log=$(create_temp_file ".log") || { rm -f "$prompt_file"; return 1; }
386
386
 
387
+ # Filter to hide ugly CLI crash messages from terminal (still captured in log)
388
+ # Strips: "This error originated...", "Error: No messages", stack traces
389
+ _filter_cli_noise() {
390
+ grep -v -E \
391
+ -e "This error originated either by throwing" \
392
+ -e "a catch block, or by rejecting a promise" \
393
+ -e "The promise rejected with the reason:" \
394
+ -e "Error: No messages returned" \
395
+ -e "at [A-Za-z0-9_]+ \(/\\\$bunfs/" \
396
+ -e "at processTicksAndRejections" \
397
+ -e "unhandled.*promise.*rejection" \
398
+ || true # Don't fail if no lines pass filter
399
+ }
400
+
387
401
  while [[ $crash_attempt -lt $max_crash_retries ]]; do
388
402
  claude_exit_code=0
389
403
  # Use pipefail to capture Claude's exit code, not tee's
390
404
  set -o pipefail
391
- cat "$prompt_file" | run_with_timeout "$timeout_seconds" claude "${claude_args[@]}" 2>&1 | tee "$claude_output_log" || claude_exit_code=$?
405
+ # Capture full output to log, show filtered output to terminal
406
+ cat "$prompt_file" | run_with_timeout "$timeout_seconds" claude "${claude_args[@]}" 2>&1 | tee "$claude_output_log" | _filter_cli_noise || claude_exit_code=$?
392
407
  set +o pipefail
393
408
 
394
- # Check for recoverable CLI crashes
409
+ # Check for recoverable CLI crashes (transient API failures)
395
410
  if grep -qE "(No messages returned|unhandled.*promise.*rejection)" "$claude_output_log" 2>/dev/null; then
396
411
  ((crash_attempt++))
397
- print_warning "Claude CLI crashed (attempt $crash_attempt/$max_crash_retries) - retrying..."
398
- log_progress "$story" "CLI_CRASH" "Claude crashed, retry $crash_attempt"
412
+ # Exponential backoff: 5s, 10s, 20s, 40s, 80s
413
+ local backoff_seconds=$((5 * (2 ** (crash_attempt - 1))))
414
+ echo "" # Clean line after any partial output
415
+ print_warning "API returned empty response - retrying in ${backoff_seconds}s (attempt $crash_attempt/$max_crash_retries)"
416
+ print_info "This is usually a transient issue with the Claude API"
417
+ log_progress "$story" "CLI_CRASH" "API empty response, retry $crash_attempt (backoff ${backoff_seconds}s)"
399
418
  session_started=false # Reset session on crash
400
- sleep 2 # Brief pause before retry
419
+ sleep "$backoff_seconds"
401
420
  continue
402
421
  fi
403
422
 
@@ -408,12 +427,13 @@ run_loop() {
408
427
  rm -f "$claude_output_log"
409
428
 
410
429
  if [[ $crash_attempt -ge $max_crash_retries ]]; then
411
- print_error "Claude CLI crashed $max_crash_retries times - stopping loop"
412
- log_progress "$story" "CLI_CRASH" "Gave up after $max_crash_retries crashes"
413
- rm -f "$prompt_file"
414
430
  echo ""
415
- echo "Claude CLI is unstable. Try again with: ralph run $story"
416
- return 1
431
+ print_warning "Claude API unavailable after $max_crash_retries attempts"
432
+ print_info "Waiting 60s before retrying... (Ctrl+C to stop, then 'npx agentic-loop run' to restart)"
433
+ log_progress "$story" "CLI_CRASH" "API unavailable, waiting 60s before next iteration"
434
+ rm -f "$prompt_file"
435
+ sleep 60 # Longer cooldown before retrying
436
+ continue # Continue main loop instead of stopping
417
437
  fi
418
438
 
419
439
  if [[ $claude_exit_code -ne 0 ]]; then
@@ -683,6 +703,8 @@ build_prompt() {
683
703
  echo "## Current Story: $story"
684
704
  echo ""
685
705
  echo "Read full story details from \`.ralph/prd.json\` - it contains everything you need:"
706
+ echo "- \`story.techStack\` - technologies relevant to this story"
707
+ echo "- \`story.constraints\` - rules for this story"
686
708
  echo "- \`story.files\` - which files to create/modify"
687
709
  echo "- \`story.acceptanceCriteria\` - what must be true"
688
710
  echo "- \`story.testSteps\` - verification commands"
@@ -691,8 +713,6 @@ build_prompt() {
691
713
  echo "- \`story.skills\` - relevant skills to reference"
692
714
  echo ""
693
715
  echo "Also read:"
694
- echo "- \`prd.techStack\` - technologies in use"
695
- echo "- \`prd.globalConstraints\` - rules for all stories"
696
716
  echo "- \`.ralph/config.json\` - URLs and directories"
697
717
 
698
718
  # Failure context if retrying