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 +1 -1
- package/prompts/team-lead-policy.md +2 -1
- package/ralph.sh +27 -12
package/package.json
CHANGED
|
@@ -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
|
|
137
|
-
|
|
138
|
-
|
|
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
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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" \
|