bmalph 2.7.3 ā 2.7.5
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 +68 -30
- package/dist/commands/doctor-checks.js +5 -4
- package/dist/commands/doctor-checks.js.map +1 -1
- package/dist/commands/run.js +4 -0
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/status.js +12 -3
- package/dist/commands/status.js.map +1 -1
- package/dist/installer.js +101 -48
- package/dist/installer.js.map +1 -1
- package/dist/platform/cursor-runtime-checks.js +81 -0
- package/dist/platform/cursor-runtime-checks.js.map +1 -0
- package/dist/platform/cursor.js +4 -3
- package/dist/platform/cursor.js.map +1 -1
- package/dist/platform/detect.js +28 -5
- package/dist/platform/detect.js.map +1 -1
- package/dist/platform/instructions-snippet.js +18 -0
- package/dist/platform/instructions-snippet.js.map +1 -1
- package/dist/platform/resolve.js +23 -5
- package/dist/platform/resolve.js.map +1 -1
- package/dist/run/ralph-process.js +84 -15
- package/dist/run/ralph-process.js.map +1 -1
- package/dist/transition/artifact-scan.js +15 -3
- package/dist/transition/artifact-scan.js.map +1 -1
- package/dist/transition/fix-plan.js +4 -4
- package/dist/transition/fix-plan.js.map +1 -1
- package/dist/transition/orchestration.js +45 -13
- package/dist/transition/orchestration.js.map +1 -1
- package/dist/transition/preflight.js +9 -1
- package/dist/transition/preflight.js.map +1 -1
- package/dist/transition/story-id.js +46 -0
- package/dist/transition/story-id.js.map +1 -0
- package/dist/transition/story-parsing.js +3 -4
- package/dist/transition/story-parsing.js.map +1 -1
- package/package.json +1 -1
- package/ralph/RALPH-REFERENCE.md +27 -3
- package/ralph/drivers/claude-code.sh +44 -2
- package/ralph/drivers/codex.sh +10 -1
- package/ralph/drivers/copilot.sh +5 -0
- package/ralph/drivers/cursor.sh +50 -29
- package/ralph/lib/response_analyzer.sh +440 -111
- package/ralph/ralph_loop.sh +73 -61
package/ralph/ralph_loop.sh
CHANGED
|
@@ -744,7 +744,7 @@ get_session_file_age_seconds() {
|
|
|
744
744
|
echo "$age_seconds"
|
|
745
745
|
}
|
|
746
746
|
|
|
747
|
-
# Initialize or resume
|
|
747
|
+
# Initialize or resume persisted driver session (with expiration check)
|
|
748
748
|
#
|
|
749
749
|
# Session Expiration Strategy:
|
|
750
750
|
# - Default expiration: 24 hours (configurable via CLAUDE_SESSION_EXPIRY_HOURS)
|
|
@@ -786,16 +786,17 @@ init_claude_session() {
|
|
|
786
786
|
fi
|
|
787
787
|
|
|
788
788
|
# Session is valid, try to read it
|
|
789
|
-
local session_id
|
|
789
|
+
local session_id
|
|
790
|
+
session_id=$(get_last_session_id)
|
|
790
791
|
if [[ -n "$session_id" ]]; then
|
|
791
792
|
local age_hours=$((age_seconds / 3600))
|
|
792
|
-
log_status "INFO" "Resuming
|
|
793
|
+
log_status "INFO" "Resuming session: ${session_id:0:20}... (${age_hours}h old)"
|
|
793
794
|
echo "$session_id"
|
|
794
795
|
return 0
|
|
795
796
|
fi
|
|
796
797
|
fi
|
|
797
798
|
|
|
798
|
-
log_status "INFO" "Starting new
|
|
799
|
+
log_status "INFO" "Starting new session"
|
|
799
800
|
echo ""
|
|
800
801
|
}
|
|
801
802
|
|
|
@@ -803,12 +804,13 @@ init_claude_session() {
|
|
|
803
804
|
save_claude_session() {
|
|
804
805
|
local output_file=$1
|
|
805
806
|
|
|
806
|
-
# Try to extract session ID from
|
|
807
|
+
# Try to extract session ID from structured output
|
|
807
808
|
if [[ -f "$output_file" ]]; then
|
|
808
|
-
local session_id
|
|
809
|
+
local session_id
|
|
810
|
+
session_id=$(extract_session_id_from_output "$output_file" 2>/dev/null || echo "")
|
|
809
811
|
if [[ -n "$session_id" && "$session_id" != "null" ]]; then
|
|
810
812
|
echo "$session_id" > "$CLAUDE_SESSION_FILE"
|
|
811
|
-
log_status "INFO" "Saved
|
|
813
|
+
log_status "INFO" "Saved session: ${session_id:0:20}..."
|
|
812
814
|
fi
|
|
813
815
|
fi
|
|
814
816
|
}
|
|
@@ -1015,6 +1017,7 @@ update_session_last_used() {
|
|
|
1015
1017
|
|
|
1016
1018
|
# Global array for Claude command arguments (avoids shell injection)
|
|
1017
1019
|
declare -a CLAUDE_CMD_ARGS=()
|
|
1020
|
+
declare -a LIVE_CMD_ARGS=()
|
|
1018
1021
|
|
|
1019
1022
|
# Build CLI command with platform driver (shell-injection safe)
|
|
1020
1023
|
# Delegates to the active platform driver's driver_build_command()
|
|
@@ -1023,6 +1026,45 @@ build_claude_command() {
|
|
|
1023
1026
|
driver_build_command "$@"
|
|
1024
1027
|
}
|
|
1025
1028
|
|
|
1029
|
+
supports_driver_sessions() {
|
|
1030
|
+
if declare -F driver_supports_sessions >/dev/null; then
|
|
1031
|
+
driver_supports_sessions
|
|
1032
|
+
return $?
|
|
1033
|
+
fi
|
|
1034
|
+
|
|
1035
|
+
return 0
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
supports_live_output() {
|
|
1039
|
+
if declare -F driver_supports_live_output >/dev/null; then
|
|
1040
|
+
driver_supports_live_output
|
|
1041
|
+
return $?
|
|
1042
|
+
fi
|
|
1043
|
+
|
|
1044
|
+
return 0
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
prepare_live_command_args() {
|
|
1048
|
+
LIVE_CMD_ARGS=("${CLAUDE_CMD_ARGS[@]}")
|
|
1049
|
+
|
|
1050
|
+
if declare -F driver_prepare_live_command >/dev/null; then
|
|
1051
|
+
driver_prepare_live_command
|
|
1052
|
+
return $?
|
|
1053
|
+
fi
|
|
1054
|
+
|
|
1055
|
+
return 0
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
get_live_stream_filter() {
|
|
1059
|
+
if declare -F driver_stream_filter >/dev/null; then
|
|
1060
|
+
driver_stream_filter
|
|
1061
|
+
return 0
|
|
1062
|
+
fi
|
|
1063
|
+
|
|
1064
|
+
echo "empty"
|
|
1065
|
+
return 1
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1026
1068
|
# Main execution function
|
|
1027
1069
|
execute_claude_code() {
|
|
1028
1070
|
local timestamp=$(date '+%Y-%m-%d_%H-%M-%S')
|
|
@@ -1054,7 +1096,7 @@ execute_claude_code() {
|
|
|
1054
1096
|
|
|
1055
1097
|
# Initialize or resume session
|
|
1056
1098
|
local session_id=""
|
|
1057
|
-
if [[ "$CLAUDE_USE_CONTINUE" == "true" ]]; then
|
|
1099
|
+
if [[ "$CLAUDE_USE_CONTINUE" == "true" ]] && supports_driver_sessions; then
|
|
1058
1100
|
session_id=$(init_claude_session)
|
|
1059
1101
|
fi
|
|
1060
1102
|
|
|
@@ -1094,11 +1136,16 @@ execute_claude_code() {
|
|
|
1094
1136
|
# - --continue (session continuity)
|
|
1095
1137
|
# - -p (prompt content)
|
|
1096
1138
|
|
|
1139
|
+
if ! supports_live_output; then
|
|
1140
|
+
log_status "WARN" "$DRIVER_DISPLAY_NAME does not support structured live streaming. Falling back to background mode."
|
|
1141
|
+
LIVE_OUTPUT=false
|
|
1142
|
+
fi
|
|
1143
|
+
|
|
1097
1144
|
# Check dependencies for live mode
|
|
1098
|
-
if ! command -v jq &> /dev/null; then
|
|
1145
|
+
if [[ "$LIVE_OUTPUT" == "true" ]] && ! command -v jq &> /dev/null; then
|
|
1099
1146
|
log_status "ERROR" "Live mode requires 'jq' but it's not installed. Falling back to background mode."
|
|
1100
1147
|
LIVE_OUTPUT=false
|
|
1101
|
-
elif ! command -v stdbuf &> /dev/null; then
|
|
1148
|
+
elif [[ "$LIVE_OUTPUT" == "true" ]] && ! command -v stdbuf &> /dev/null; then
|
|
1102
1149
|
log_status "ERROR" "Live mode requires 'stdbuf' (from coreutils) but it's not installed. Falling back to background mode."
|
|
1103
1150
|
LIVE_OUTPUT=false
|
|
1104
1151
|
fi
|
|
@@ -1116,42 +1163,15 @@ execute_claude_code() {
|
|
|
1116
1163
|
log_status "INFO" "šŗ Live output mode enabled - showing $DRIVER_DISPLAY_NAME streaming..."
|
|
1117
1164
|
echo -e "${PURPLE}āāāāāāāāāāāāāāāā ${DRIVER_DISPLAY_NAME} Output āāāāāāāāāāāāāāāā${NC}"
|
|
1118
1165
|
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
if [[ "$skip_next" == "true" ]]; then
|
|
1125
|
-
# Replace "json" with "stream-json" for output format
|
|
1126
|
-
LIVE_CMD_ARGS+=("stream-json")
|
|
1127
|
-
skip_next=false
|
|
1128
|
-
elif [[ "$arg" == "--output-format" ]]; then
|
|
1129
|
-
LIVE_CMD_ARGS+=("$arg")
|
|
1130
|
-
skip_next=true
|
|
1131
|
-
else
|
|
1132
|
-
LIVE_CMD_ARGS+=("$arg")
|
|
1133
|
-
fi
|
|
1134
|
-
done
|
|
1166
|
+
if ! prepare_live_command_args; then
|
|
1167
|
+
log_status "ERROR" "Failed to prepare live streaming command. Falling back to background mode."
|
|
1168
|
+
LIVE_OUTPUT=false
|
|
1169
|
+
fi
|
|
1170
|
+
fi
|
|
1135
1171
|
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
# jq filter: show text + tool names + newlines for readability
|
|
1141
|
-
local jq_filter='
|
|
1142
|
-
if .type == "stream_event" then
|
|
1143
|
-
if .event.type == "content_block_delta" and .event.delta.type == "text_delta" then
|
|
1144
|
-
.event.delta.text
|
|
1145
|
-
elif .event.type == "content_block_start" and .event.content_block.type == "tool_use" then
|
|
1146
|
-
"\n\nā” [" + .event.content_block.name + "]\n"
|
|
1147
|
-
elif .event.type == "content_block_stop" then
|
|
1148
|
-
"\n"
|
|
1149
|
-
else
|
|
1150
|
-
empty
|
|
1151
|
-
end
|
|
1152
|
-
else
|
|
1153
|
-
empty
|
|
1154
|
-
end'
|
|
1172
|
+
if [[ "$LIVE_OUTPUT" == "true" ]]; then
|
|
1173
|
+
local jq_filter
|
|
1174
|
+
jq_filter=$(get_live_stream_filter)
|
|
1155
1175
|
|
|
1156
1176
|
# Execute with streaming, preserving all flags from build_claude_command()
|
|
1157
1177
|
# Use stdbuf to disable buffering for real-time output
|
|
@@ -1183,34 +1203,26 @@ execute_claude_code() {
|
|
|
1183
1203
|
echo ""
|
|
1184
1204
|
echo -e "${PURPLE}āāāāāāāāāāāāāāāā End of Output āāāāāāāāāāāāāāāāāāā${NC}"
|
|
1185
1205
|
|
|
1186
|
-
#
|
|
1187
|
-
#
|
|
1188
|
-
#
|
|
1206
|
+
# Preserve full stream output for downstream analysis and session extraction.
|
|
1207
|
+
# Claude-style stream_json can be collapsed to the final result record,
|
|
1208
|
+
# while Codex JSONL should remain as event output for the shared parser.
|
|
1189
1209
|
if [[ "$CLAUDE_USE_CONTINUE" == "true" && -f "$output_file" ]]; then
|
|
1190
|
-
# Preserve full stream output for analysis (don't overwrite output_file)
|
|
1191
1210
|
local stream_output_file="${output_file%.log}_stream.log"
|
|
1192
1211
|
cp "$output_file" "$stream_output_file"
|
|
1193
1212
|
|
|
1194
|
-
#
|
|
1195
|
-
# Use flexible regex to match various JSON formatting styles
|
|
1196
|
-
# Matches: "type":"result", "type": "result", "type" : "result"
|
|
1213
|
+
# Collapse Claude-style stream_json to the final result object when present.
|
|
1197
1214
|
local result_line=$(grep -E '"type"[[:space:]]*:[[:space:]]*"result"' "$output_file" 2>/dev/null | tail -1)
|
|
1198
1215
|
|
|
1199
1216
|
if [[ -n "$result_line" ]]; then
|
|
1200
|
-
# Validate that extracted line is valid JSON before using it
|
|
1201
1217
|
if echo "$result_line" | jq -e . >/dev/null 2>&1; then
|
|
1202
|
-
# Write validated result as the output_file for downstream processing
|
|
1203
|
-
# (save_claude_session and analyze_response expect JSON format)
|
|
1204
1218
|
echo "$result_line" > "$output_file"
|
|
1205
|
-
log_status "INFO" "
|
|
1219
|
+
log_status "INFO" "Collapsed streamed response to the final result record"
|
|
1206
1220
|
else
|
|
1207
|
-
log_status "WARN" "Extracted result line is not valid JSON, keeping stream output"
|
|
1208
|
-
# Restore original stream output
|
|
1209
1221
|
cp "$stream_output_file" "$output_file"
|
|
1222
|
+
log_status "WARN" "Final result record was invalid JSON, keeping full stream output"
|
|
1210
1223
|
fi
|
|
1211
1224
|
else
|
|
1212
|
-
log_status "
|
|
1213
|
-
# Keep stream output as-is for debugging
|
|
1225
|
+
log_status "INFO" "Keeping full stream output for shared response analysis"
|
|
1214
1226
|
fi
|
|
1215
1227
|
fi
|
|
1216
1228
|
else
|
|
@@ -1305,7 +1317,7 @@ EOF
|
|
|
1305
1317
|
log_status "SUCCESS" "ā
$DRIVER_DISPLAY_NAME execution completed successfully"
|
|
1306
1318
|
|
|
1307
1319
|
# Save session ID from JSON output (Phase 1.1)
|
|
1308
|
-
if [[ "$CLAUDE_USE_CONTINUE" == "true" ]]; then
|
|
1320
|
+
if [[ "$CLAUDE_USE_CONTINUE" == "true" ]] && supports_driver_sessions; then
|
|
1309
1321
|
save_claude_session "$output_file"
|
|
1310
1322
|
fi
|
|
1311
1323
|
|