ralph-teams 1.0.0 → 1.0.2

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.
@@ -44,10 +44,11 @@ For Claude subagents, choose the model based on task difficulty unless the envir
44
44
  - When spawning: use `subagent_type: "planner"`. If `RALPH_MODEL_PLANNER_EXPLICIT=1`, use `RALPH_MODEL_PLANNER`. Otherwise choose `haiku`/`sonnet`/`opus` based on task difficulty.
45
45
  - When you delegate planning, explicitly tell the Planner the exact output path for the epic plan file, for example `plans/plan-EPIC-001.md`, and require it to write the plan there before replying.
46
46
  - Wait for the Planner to finish, then read the plan file it wrote before moving on.
47
- 3. **Spawn the Builder** Spawn a **Builder** agent (`name: "builder"`, `subagent_type: "sonnet-coder"`) provide the full epic context, the implementation plan (if one was written), and instruct it to wait for story assignments from you via direct messages.
48
- - If `RALPH_MODEL_BUILDER_EXPLICIT=1`, use `RALPH_MODEL_BUILDER`.
49
- - Otherwise choose `haiku` for straightforward file edits, `sonnet` for normal implementation work, and `opus` only when the build task is unusually complex or risky.
50
- 4. **Validator only spawn if truly needed.** Ask: "Can I verify this story is correct just by reading the file and checking the build output?" If YES **do NOT spawn the Validator** — self-verify instead. If NO → spawn it.
47
+ 3. **Do NOT create a long-lived Builder mailbox.** For Claude, treat Builder and Validator as one-shot subagents, not persistent teammates. Do NOT ask them to wait for future direct messages. Do NOT use `SendMessage` or `shutdown_request` to coordinate story execution.
48
+ 4. **Builder/Validator policy.**
49
+ - For each story, spawn a fresh **Builder** with `subagent_type: "builder"` and give it the complete assignment for that one story.
50
+ - If `RALPH_MODEL_BUILDER_EXPLICIT=1`, use `RALPH_MODEL_BUILDER`. Otherwise choose `haiku` for straightforward file edits, `sonnet` for normal implementation work, and `opus` only when the build task is unusually complex or risky.
51
+ - **Validator — only spawn if truly needed.** Ask: "Can I verify this story is correct just by reading the file and checking the build output?" If YES → **do NOT spawn the Validator** — self-verify instead. If NO → spawn a fresh Validator for that one story.
51
52
  - DO NOT spawn for: "add X to file Y" (read the file, check X is there), build/typecheck checks (run the command yourself or trust Builder's output)
52
53
  - SPAWN for: logic correctness, new behaviour, API contracts, anything requiring judgment to verify
53
54
  - When self-verifying: read the changed file(s), check each criterion, decide PASS or FAIL.
@@ -64,16 +65,17 @@ Before starting a story, check the `passes` field in the PRD file (at the path p
64
65
 
65
66
  ### Build Phase
66
67
  1. Before assigning the story, check whether a guidance file exists at `guidance/guidance-{story-id}.md` (substituting the actual story ID, e.g. `guidance/guidance-US-003.md`).
67
- 2. Send Builder a direct message with:
68
+ 2. Spawn a fresh Builder subagent for this story with:
68
69
  - Story ID and title
69
70
  - Full acceptance criteria
70
71
  - The relevant section from the implementation plan
71
72
  - Any context from previous stories or prior validator feedback
72
73
  - **If the guidance file exists**, include this line explicitly: `Guidance file for this story: guidance/guidance-{story-id}.md — read it before implementing and follow the instructions in it.`
73
- 3. Wait for Builder to complete and message back with the commit SHA
74
+ 3. Wait for that Builder to finish and inspect its final response.
75
+ 4. Do not treat task lifecycle notifications, idle output, or a generic completion message as success. The Builder result is only usable if it includes a concrete commit SHA in the required format.
74
76
 
75
77
  ### Validate Phase
76
- 4. **If Validator was spawned:** Send Validator a direct message with: the story's acceptance criteria + the commit SHA from Builder + "verify the implementation. Use `git diff <sha>~1 <sha>` to see exactly what changed." Wait for Validator verdict.
78
+ 5. **If Validator was spawned:** Spawn a fresh Validator subagent for this story with: the story's acceptance criteria + the commit SHA from Builder + "verify the implementation. Use `git diff <sha>~1 <sha>` to see exactly what changed." Wait for Validator verdict.
77
79
  **If no Validator:** Verify yourself — read the changed files, check each acceptance criterion is met, and determine PASS or FAIL.
78
80
 
79
81
  ### Pushback Loop (max 2 total build+validate cycles)
@@ -83,7 +85,7 @@ The first build+validate cycle is attempt 1. If it fails, you get one retry (att
83
85
  8. If Validator reports **PASS** → mark story as passed in PRD, move to next story
84
86
  9. If Validator reports **FAIL**:
85
87
  - Increment attempt counter for this story
86
- - If attempt count < 2: send Builder the failure details, reassign the story task (this is the retry)
88
+ - If attempt count < 2: spawn a new Builder for the retry and include the failure details from validation
87
89
  - If attempt count = 2: **document the failure and move on** (see Failure Documentation below)
88
90
 
89
91
  ## Failure Documentation
@@ -137,6 +139,7 @@ After processing ALL stories in the epic (none left to attempt):
137
139
  ## Rules
138
140
 
139
141
  - NEVER write code yourself
142
+ - For Claude, Builder and Validator must be one-shot story-scoped subagents. Do NOT keep them alive across stories.
140
143
  - Only skip the Planner for genuinely simple epics — when in doubt, run it
141
144
  - Only skip the Validator for genuinely simple stories — when in doubt, spawn it; for complex stories the Validator must always run
142
145
  - NEVER exceed 2 total build+validate cycles per story (first attempt + 1 retry = 2 total)
@@ -145,3 +148,4 @@ After processing ALL stories in the epic (none left to attempt):
145
148
  - ALWAYS document failures before moving on
146
149
  - Keep Builder and Validator unaware of each other's reasoning — Validator should only see the code (via commit SHA), not Builder's explanation of what it did
147
150
  - ALWAYS pass the commit SHA from Builder to Validator
151
+ - NEVER treat task notifications, idle teammate output, or summary prose as a substitute for a real Builder result and PRD update
package/README.md CHANGED
@@ -37,7 +37,6 @@ The runtime is file-based. During a run, Ralph treats these files as the working
37
37
  - `plans/`: implementation plans for epics that were explicitly planned
38
38
  - `progress.txt`: narrative progress log
39
39
  - `logs/`: raw backend logs
40
- - `results/`: per-epic final result markers
41
40
  - `ralph-state.json`: interrupt/resume state
42
41
 
43
42
  ## Flow
@@ -74,7 +73,7 @@ flowchart TB
74
73
  SP[Mark story passed in PRD]
75
74
  F[Record failure]
76
75
  M{More stories}
77
- RF[Write result file]
76
+ RF[Print DONE summary]
78
77
 
79
78
  TL --> PP
80
79
  PP -->|Yes| Q
@@ -440,7 +439,7 @@ Example:
440
439
  Notes:
441
440
 
442
441
  - Ralph enables Codex multi-agent mode per run, so no global `~/.codex/config.toml` edits are required
443
- - Codex runs from each epic worktree and is granted write access to the repo root so it can update the shared PRD and result files
442
+ - Codex runs from each epic worktree and is granted write access to the repo root so it can update the shared PRD
444
443
  - Codex does not use a separate repo-local Team Lead role file; the Team Lead policy comes from the runtime prompt assembled in `ralph.sh`, while `.codex/agents/*.toml` define the spawned planner, builder, validator, and merger roles
445
444
 
446
445
  ## PRD Format
@@ -501,7 +500,6 @@ During a run, Ralph writes:
501
500
  - `progress.txt`: high-level run log
502
501
  - `plans/plan-EPIC-xxx.md`: planner output for an epic
503
502
  - planned epics are expected to use these files as their implementation contract
504
- - `results/result-EPIC-xxx.txt`: final pass/partial/fail result per epic
505
503
  - `logs/epic-EPIC-xxx-<timestamp>.log`: raw backend session log
506
504
  - `ralph-state.json`: saved interrupt/resume state
507
505
  - `guidance/guidance-US-xxx.md`: retry guidance captured from discuss flows
@@ -527,7 +525,7 @@ The current execution contract is:
527
525
  - rerunning Ralph automatically resets `failed` and `partial` epics back to `pending` so only unfinished work is retried
528
526
  - each story gets at most two build/validate cycles
529
527
  - the validator checks output independently from the builder's reasoning
530
- - after writing `results/result-EPIC-xxx.txt`, the team lead must print the same result and exit the session immediately
528
+ - after updating `prd.json` for all attempted stories, the team lead must print `DONE: X/Y stories passed` and exit the session immediately
531
529
  - pressing `Ctrl-C` writes `ralph-state.json` so the run can be resumed later with `ralph-teams resume`
532
530
 
533
531
  ## Troubleshooting
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ralph-teams",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "CLI tool for Ralph Teams",
5
5
  "bin": {
6
6
  "ralph-teams": "dist/index.js",
package/ralph.sh CHANGED
@@ -871,10 +871,8 @@ spawn_epic_bg() {
871
871
  PENDING_STORIES_JSON=$(rjq read "$PRD_FILE" ".epics[$EPIC_INDEX].userStories" | \
872
872
  node -e 'const fs=require("fs"); const stories=JSON.parse(fs.readFileSync(0,"utf8")); process.stdout.write(JSON.stringify(stories.filter(s => s.passes !== true)));')
873
873
 
874
- local RESULT_FILE="${ROOT_DIR}/results/result-${EPIC_ID}.txt"
875
874
  local EPIC_LOG="${ROOT_DIR}/logs/epic-${EPIC_ID}-$(date +%s).log"
876
- mkdir -p "${ROOT_DIR}/results" "${ROOT_DIR}/logs"
877
- rm -f "$RESULT_FILE"
875
+ mkdir -p "${ROOT_DIR}/logs"
878
876
 
879
877
  # Create isolated worktree for this epic
880
878
  local WORKTREE_PATH
@@ -950,7 +948,7 @@ $PENDING_STORIES_JSON
950
948
  ## Critical Rules
951
949
  - Do NOT stop after the first story — process ALL stories before exiting
952
950
  - Idle or waiting messages from teammates are NORMAL — they do not mean the session should end
953
- - Once the final result is written, end the session immediately. Do not wait for more input.
951
+ - Once the final PRD updates are complete and you have printed the DONE summary, end the session immediately. Do not wait for more input.
954
952
  - Process stories sequentially: build → validate → next. Do not stop early.
955
953
  - After each story result (pass or fail), update $PRD_ABS_PATH to keep both passes and failureReason accurate for that story
956
954
 
@@ -1220,7 +1218,6 @@ while true; do
1220
1218
  for slot in "${!active_pids[@]}"; do
1221
1219
  local finished_epic_id
1222
1220
  finished_epic_id=$(rjq read "$PRD_FILE" ".epics[${active_indices[$slot]}].id")
1223
- local result_file="${ROOT_DIR}/results/result-${finished_epic_id}.txt"
1224
1221
  local process_finished=false
1225
1222
 
1226
1223
  emit_new_log_output "$finished_epic_id" "${active_logs[$slot]}" "${active_log_lines[$slot]:-0}"
@@ -1326,22 +1323,23 @@ while true; do
1326
1323
  process_finished=true
1327
1324
  fi
1328
1325
 
1329
- if [ "$process_finished" = true ] || [ -f "$result_file" ]; then
1330
- # If the result file exists, the epic is complete even if the backend
1331
- # session is still idling. Terminate the lingering job and advance.
1326
+ local total_s passed_s
1327
+ total_s=$(rjq length "$PRD_FILE" ".epics[${active_indices[$slot]}].userStories")
1328
+ passed_s=$(rjq count-where "$PRD_FILE" ".epics[${active_indices[$slot]}].userStories" "passes=true")
1329
+ local all_done=false
1330
+ [ "$passed_s" -eq "$total_s" ] && [ "$total_s" -gt 0 ] && all_done=true
1331
+
1332
+ if [ "$process_finished" = true ] || [ "$all_done" = true ]; then
1333
+ # Treat fully-passed stories in the PRD as the authoritative completion
1334
+ # signal, even if the backend session is still idling.
1332
1335
  if [ "$process_finished" = false ]; then
1333
1336
  terminate_process_tree "${active_pids[$slot]}"
1334
1337
  fi
1335
1338
  wait "${active_pids[$slot]}" 2>/dev/null || true
1336
1339
 
1337
- # Check if this was a crash (process exited, no result file, not all stories done)
1338
- local total_s passed_s
1339
- total_s=$(rjq length "$PRD_FILE" ".epics[${active_indices[$slot]}].userStories")
1340
- passed_s=$(rjq count-where "$PRD_FILE" ".epics[${active_indices[$slot]}].userStories" "passes=true")
1341
- local all_done=false
1342
- [ "$passed_s" -eq "$total_s" ] && [ "$total_s" -gt 0 ] && all_done=true
1343
-
1344
- if [ ! -f "$result_file" ] && [ "$all_done" = false ]; then
1340
+ # If the process exited before the epic reached all stories passed,
1341
+ # consider it a crash and retry when possible.
1342
+ if [ "$all_done" = false ]; then
1345
1343
  local retry_count
1346
1344
  retry_count="$(get_crash_retry_count "$finished_epic_id")"
1347
1345
  if [ "$retry_count" -lt "$MAX_CRASH_RETRIES" ]; then