ralph-teams 1.0.20 → 1.0.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ralph-teams",
3
- "version": "1.0.20",
3
+ "version": "1.0.21",
4
4
  "description": "CLI tool for Ralph Teams",
5
5
  "bin": {
6
6
  "ralph-teams": "dist/index.js",
@@ -14,8 +14,9 @@ You coordinate epic execution. Do not write implementation code yourself.
14
14
  ## Epic Planning
15
15
 
16
16
  - If `epicPlanning.enabled = 0`, do not spawn an epic planner. Use the epic as provided.
17
+ - If a usable canonical plan file already exists at the path provided in the prompt, do not spawn the epic planner. Use that plan even if `planned` is still `false`.
17
18
  - If the epic is already marked `planned=true`, do not spawn the epic planner. Read the canonical plan file path provided in the prompt and follow it.
18
- - Otherwise, if `epicPlanning.enabled = 1`, spawn the epic planner for any medium- or high-complexity epic.
19
+ - Otherwise, if `epicPlanning.enabled = 1`, spawn the epic planner for any medium- or high-complexity epic that does not already have a usable canonical plan.
19
20
  - Only skip epic planning for clearly low-complexity epics where the acceptance criteria can be implemented literally with no meaningful design decisions.
20
21
  - When delegating epic planning, explicitly tell the epic planner the exact output path for the epic plan file and require it to write the plan there before replying.
21
22
  - Treat an epic planner response as incomplete if it only pastes or summarizes the plan in chat. The epic planner must perform the file write itself and only then report completion.
package/ralph.sh CHANGED
@@ -133,9 +133,13 @@ resolve_rjq_bin() {
133
133
  fi
134
134
  done
135
135
 
136
- if command -v rjq >/dev/null 2>&1; then
137
- command -v rjq
138
- return 0
136
+ if type -P rjq >/dev/null 2>&1; then
137
+ local path_rjq
138
+ path_rjq="$(type -P rjq)"
139
+ if [ -n "$path_rjq" ] && [ -e "$path_rjq" ] && [ -x "$path_rjq" ]; then
140
+ echo "$path_rjq"
141
+ return 0
142
+ fi
139
143
  fi
140
144
 
141
145
  return 1
@@ -144,14 +148,12 @@ resolve_rjq_bin() {
144
148
  RJQ_BIN="$(resolve_rjq_bin || true)"
145
149
 
146
150
  rjq() {
147
- if [ -z "${RJQ_BIN:-}" ]; then
148
- echo "Error: rjq binary is not configured." >&2
149
- exit 1
150
- fi
151
-
152
- if [ ! -e "$RJQ_BIN" ]; then
153
- echo "Error: resolved rjq binary does not exist: $RJQ_BIN" >&2
154
- exit 1
151
+ if [ -z "${RJQ_BIN:-}" ] || [ ! -e "$RJQ_BIN" ]; then
152
+ RJQ_BIN="$(resolve_rjq_bin || true)"
153
+ if [ -z "${RJQ_BIN:-}" ] || [ ! -e "$RJQ_BIN" ]; then
154
+ echo "Error: resolved rjq binary does not exist: ${RJQ_BIN:-<unset>}" >&2
155
+ exit 1
156
+ fi
155
157
  fi
156
158
 
157
159
  case "$RJQ_BIN" in
@@ -1223,6 +1225,8 @@ spawn_epic_bg() {
1223
1225
  EPIC_TITLE=$(rjq read "$PRD_FILE" ".epics[$EPIC_INDEX].title")
1224
1226
  local EPIC_JSON
1225
1227
  EPIC_JSON=$(rjq read "$PRD_FILE" ".epics[$EPIC_INDEX]")
1228
+ local EPIC_PLANNED
1229
+ EPIC_PLANNED=$(rjq read "$PRD_FILE" ".epics[$EPIC_INDEX].planned" "false")
1226
1230
  local PENDING_STORIES_JSON
1227
1231
  PENDING_STORIES_JSON=$(rjq read "$PRD_FILE" ".epics[$EPIC_INDEX].userStories" | \
1228
1232
  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)));')
@@ -1238,6 +1242,10 @@ spawn_epic_bg() {
1238
1242
  local WORKTREE_PRD_PATH="${WORKTREE_ABS_PATH}/${PRD_REL_PATH}"
1239
1243
  local WORKTREE_STATE_FILE="${WORKTREE_ABS_PATH}/${RALPH_RUNTIME_DIRNAME}/state/${EPIC_ID}.json"
1240
1244
  local WORKTREE_PLAN_FILE="${WORKTREE_ABS_PATH}/${RALPH_RUNTIME_DIRNAME}/plans/plan-${EPIC_ID}.md"
1245
+ local WORKTREE_PLAN_EXISTS="false"
1246
+ if [ -f "$WORKTREE_PLAN_FILE" ]; then
1247
+ WORKTREE_PLAN_EXISTS="true"
1248
+ fi
1241
1249
 
1242
1250
  init_epic_state_file "$EPIC_ID" "$EPIC_INDEX"
1243
1251
 
@@ -1268,6 +1276,12 @@ $EPIC_JSON
1268
1276
  If this epic has planned=true in the PRD, the canonical implementation plan is:
1269
1277
  $WORKTREE_PLAN_FILE
1270
1278
 
1279
+ ## Planning Status
1280
+ - epic.planned = ${EPIC_PLANNED}
1281
+ - canonical_plan.exists = ${WORKTREE_PLAN_EXISTS}
1282
+ - If a usable canonical plan already exists, do NOT spawn the epic planner. Use it even if epic.planned is false.
1283
+ - Only spawn the epic planner when epicPlanning.enabled = 1 and there is no usable canonical plan for this epic.
1284
+
1271
1285
  ## Stories To Plan And Execute
1272
1286
  Only these stories should be planned or worked in this run. Stories omitted here are already passed and must be treated as done context only.
1273
1287
  $PENDING_STORIES_JSON
@@ -1322,6 +1336,7 @@ $TEAM_LEAD_POLICY
1322
1336
  - Use the exact epic state file path shown above for every story update. The PRD path is read-only context.
1323
1337
  - If your runtime supports named sub-agents, use the dedicated story-planner, epic-planner, builder, story-validator, and epic-validator roles and choose their models using the policy above.
1324
1338
  - If a story fails validation and still has retries left, spawn a new Builder for the retry instead of reusing the previous Builder run.
1339
+ - If your runtime is Codex exec mode, `request_user_input` is unavailable. Never call it. Do not stop to ask the user questions. Make a reasonable assumption, continue, and report the assumption in your final summary only if it matters.
1325
1340
 
1326
1341
  Begin."
1327
1342
 
@@ -1549,7 +1564,7 @@ run_backend_agent_session() {
1549
1564
  local prompt_file="${SCRIPT_DIR}/prompts/agents/${agent_name}.md"
1550
1565
  local role_body
1551
1566
  role_body="$(extract_prompt_body "$prompt_file")"
1552
- printf '%s\n\n## Assignment\n%s\n' "$role_body" "$prompt" | codex \
1567
+ printf 'Runtime note: This Codex session runs in exec mode. `request_user_input` is unavailable. Never call it. Do not stop to ask the user questions. Make a reasonable assumption and continue.\n\n%s\n\n## Assignment\n%s\n' "$role_body" "$prompt" | codex \
1553
1568
  -a never \
1554
1569
  exec \
1555
1570
  -C "$workdir" \