bmalph 2.8.0 → 2.10.0

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.
Files changed (113) hide show
  1. package/README.md +51 -28
  2. package/dist/cli.js +4 -2
  3. package/dist/commands/doctor-checks.js +1 -1
  4. package/dist/commands/doctor-health-checks.js +2 -1
  5. package/dist/commands/init.js +3 -1
  6. package/dist/commands/reset.js +1 -1
  7. package/dist/commands/run.js +49 -1
  8. package/dist/commands/status.js +0 -9
  9. package/dist/commands/upgrade.js +1 -1
  10. package/dist/installer/metadata.js +1 -1
  11. package/dist/installer/project-files.js +2 -3
  12. package/dist/installer/ralph-assets.js +8 -0
  13. package/dist/installer/template-files.js +54 -0
  14. package/dist/reset.js +2 -3
  15. package/dist/run/ralph-process.js +13 -3
  16. package/dist/run/run-dashboard.js +6 -4
  17. package/dist/transition/artifact-scan.js +3 -6
  18. package/dist/transition/context.js +1 -1
  19. package/dist/utils/constants.js +22 -0
  20. package/dist/utils/github.js +4 -3
  21. package/dist/utils/ralph-runtime-state.js +3 -13
  22. package/dist/utils/validate.js +4 -10
  23. package/dist/watch/dashboard.js +1 -0
  24. package/dist/watch/renderer.js +23 -0
  25. package/dist/watch/state-reader.js +20 -1
  26. package/package.json +8 -2
  27. package/ralph/drivers/DRIVER_INTERFACE.md +422 -0
  28. package/ralph/drivers/codex.sh +2 -2
  29. package/ralph/lib/response_analyzer.sh +87 -87
  30. package/ralph/ralph_loop.sh +220 -1
  31. package/ralph/templates/PROMPT.md +12 -0
  32. package/ralph/templates/REVIEW_PROMPT.md +60 -0
  33. package/ralph/templates/ralphrc.template +18 -0
  34. package/dist/cli.js.map +0 -1
  35. package/dist/commands/check-updates.js.map +0 -1
  36. package/dist/commands/doctor-checks.js.map +0 -1
  37. package/dist/commands/doctor-health-checks.js.map +0 -1
  38. package/dist/commands/doctor-runtime-checks.js.map +0 -1
  39. package/dist/commands/doctor.js.map +0 -1
  40. package/dist/commands/implement.js.map +0 -1
  41. package/dist/commands/init.js.map +0 -1
  42. package/dist/commands/reset.js.map +0 -1
  43. package/dist/commands/run.js.map +0 -1
  44. package/dist/commands/status.js.map +0 -1
  45. package/dist/commands/upgrade.js.map +0 -1
  46. package/dist/commands/watch.js.map +0 -1
  47. package/dist/installer/bmad-assets.js.map +0 -1
  48. package/dist/installer/commands.js.map +0 -1
  49. package/dist/installer/install.js.map +0 -1
  50. package/dist/installer/metadata.js.map +0 -1
  51. package/dist/installer/project-files.js.map +0 -1
  52. package/dist/installer/ralph-assets.js.map +0 -1
  53. package/dist/installer/template-files.js.map +0 -1
  54. package/dist/installer/types.js.map +0 -1
  55. package/dist/installer.js.map +0 -1
  56. package/dist/platform/aider.js.map +0 -1
  57. package/dist/platform/claude-code.js.map +0 -1
  58. package/dist/platform/codex.js.map +0 -1
  59. package/dist/platform/copilot.js.map +0 -1
  60. package/dist/platform/cursor-runtime-checks.js.map +0 -1
  61. package/dist/platform/cursor.js.map +0 -1
  62. package/dist/platform/detect.js.map +0 -1
  63. package/dist/platform/doctor-checks.js.map +0 -1
  64. package/dist/platform/guidance.js.map +0 -1
  65. package/dist/platform/instructions-snippet.js.map +0 -1
  66. package/dist/platform/opencode.js.map +0 -1
  67. package/dist/platform/registry.js.map +0 -1
  68. package/dist/platform/resolve.js.map +0 -1
  69. package/dist/platform/types.js.map +0 -1
  70. package/dist/platform/windsurf.js.map +0 -1
  71. package/dist/reset.js.map +0 -1
  72. package/dist/run/ralph-process.js.map +0 -1
  73. package/dist/run/run-dashboard.js.map +0 -1
  74. package/dist/run/types.js.map +0 -1
  75. package/dist/transition/artifact-collection.js.map +0 -1
  76. package/dist/transition/artifact-loading.js.map +0 -1
  77. package/dist/transition/artifact-scan.js.map +0 -1
  78. package/dist/transition/artifacts.js.map +0 -1
  79. package/dist/transition/context-output.js.map +0 -1
  80. package/dist/transition/context.js.map +0 -1
  81. package/dist/transition/fix-plan-sync.js.map +0 -1
  82. package/dist/transition/fix-plan.js.map +0 -1
  83. package/dist/transition/index.js.map +0 -1
  84. package/dist/transition/orchestration.js.map +0 -1
  85. package/dist/transition/preflight.js.map +0 -1
  86. package/dist/transition/section-patterns.js.map +0 -1
  87. package/dist/transition/specs-changelog.js.map +0 -1
  88. package/dist/transition/specs-index.js.map +0 -1
  89. package/dist/transition/specs-sync.js.map +0 -1
  90. package/dist/transition/sprint-status.js.map +0 -1
  91. package/dist/transition/story-id.js.map +0 -1
  92. package/dist/transition/story-parsing.js.map +0 -1
  93. package/dist/transition/tech-stack.js.map +0 -1
  94. package/dist/transition/types.js.map +0 -1
  95. package/dist/utils/artifact-definitions.js.map +0 -1
  96. package/dist/utils/config.js.map +0 -1
  97. package/dist/utils/constants.js.map +0 -1
  98. package/dist/utils/dryrun.js.map +0 -1
  99. package/dist/utils/errors.js.map +0 -1
  100. package/dist/utils/file-system.js.map +0 -1
  101. package/dist/utils/format-status.js.map +0 -1
  102. package/dist/utils/github.js.map +0 -1
  103. package/dist/utils/json.js.map +0 -1
  104. package/dist/utils/logger.js.map +0 -1
  105. package/dist/utils/ralph-runtime-state.js.map +0 -1
  106. package/dist/utils/state.js.map +0 -1
  107. package/dist/utils/validate.js.map +0 -1
  108. package/dist/watch/dashboard.js.map +0 -1
  109. package/dist/watch/file-watcher.js.map +0 -1
  110. package/dist/watch/frame-writer.js.map +0 -1
  111. package/dist/watch/renderer.js.map +0 -1
  112. package/dist/watch/state-reader.js.map +0 -1
  113. package/dist/watch/types.js.map +0 -1
@@ -46,7 +46,7 @@ driver_permission_denial_help() {
46
46
  }
47
47
 
48
48
  # Build Codex CLI command
49
- # Codex uses: codex exec [--resume <id>] --json "prompt"
49
+ # Codex uses: codex exec [resume <id>] --json "prompt"
50
50
  driver_build_command() {
51
51
  local prompt_file=$1
52
52
  local loop_context=$2
@@ -67,7 +67,7 @@ driver_build_command() {
67
67
 
68
68
  # Session resume — gated on CLAUDE_USE_CONTINUE to respect --no-continue flag
69
69
  if [[ "$CLAUDE_USE_CONTINUE" == "true" && -n "$session_id" ]]; then
70
- CLAUDE_CMD_ARGS+=("--resume" "$session_id")
70
+ CLAUDE_CMD_ARGS+=("resume" "$session_id")
71
71
  fi
72
72
 
73
73
  # Build prompt with context
@@ -762,14 +762,14 @@ parse_json_response() {
762
762
  local summary_has_no_work_pattern="false"
763
763
  if [[ "$response_shape" == "codex_jsonl" || "$response_shape" == "opencode_jsonl" || "$response_shape" == "cursor_stream_jsonl" ]] && [[ "$explicit_exit_signal_found" != "true" && -n "$summary" ]]; then
764
764
  for keyword in "${COMPLETION_KEYWORDS[@]}"; do
765
- if echo "$summary" | grep -qi "$keyword"; then
765
+ if echo "$summary" | grep -qiw "$keyword"; then
766
766
  summary_has_completion_keyword="true"
767
767
  break
768
768
  fi
769
769
  done
770
770
 
771
771
  for pattern in "${NO_WORK_PATTERNS[@]}"; do
772
- if echo "$summary" | grep -qi "$pattern"; then
772
+ if echo "$summary" | grep -qiw "$pattern"; then
773
773
  summary_has_no_work_pattern="true"
774
774
  break
775
775
  fi
@@ -1035,13 +1035,15 @@ analyze_response() {
1035
1035
 
1036
1036
  # Text parsing fallback (original logic)
1037
1037
 
1038
- # Track whether an explicit EXIT_SIGNAL was found in RALPH_STATUS block
1039
- # If explicit signal found, heuristics should NOT override Claude's intent
1040
- local explicit_exit_signal_found=false
1041
-
1042
- # 1. Check for explicit structured output (if Claude follows schema)
1038
+ # 1. Check for explicit structured output (RALPH_STATUS block)
1039
+ # When a status block is present, it is authoritative skip all heuristics.
1040
+ # A structurally valid but field-empty block results in exit_signal=false,
1041
+ # confidence=0 by design (AI produced a block but provided no signal).
1042
+ local ralph_status_block_found=false
1043
1043
  local ralph_status_json=""
1044
1044
  if ralph_status_json=$(extract_ralph_status_block_json "$output_content" 2>/dev/null); then
1045
+ ralph_status_block_found=true
1046
+
1045
1047
  local status
1046
1048
  status=$(printf '%s' "$ralph_status_json" | jq -r -j '.status' 2>/dev/null)
1047
1049
  local exit_sig_found
@@ -1062,14 +1064,14 @@ analyze_response() {
1062
1064
 
1063
1065
  # If EXIT_SIGNAL is explicitly provided, respect it
1064
1066
  if [[ "$exit_sig_found" == "true" ]]; then
1065
- explicit_exit_signal_found=true
1066
1067
  if [[ "$exit_sig" == "true" ]]; then
1067
1068
  has_completion_signal=true
1068
1069
  exit_signal=true
1069
1070
  confidence_score=100
1070
1071
  else
1071
- # Explicit EXIT_SIGNAL: false - Claude says to continue
1072
+ # Explicit EXIT_SIGNAL: false Claude says to continue
1072
1073
  exit_signal=false
1074
+ confidence_score=80
1073
1075
  fi
1074
1076
  elif [[ "$status" == "COMPLETE" ]]; then
1075
1077
  # No explicit EXIT_SIGNAL but STATUS is COMPLETE
@@ -1077,68 +1079,93 @@ analyze_response() {
1077
1079
  exit_signal=true
1078
1080
  confidence_score=100
1079
1081
  fi
1082
+ # is_test_only and is_stuck stay false (defaults) — status block is authoritative
1080
1083
  fi
1081
1084
 
1082
- # 2. Detect completion keywords in natural language output
1083
- for keyword in "${COMPLETION_KEYWORDS[@]}"; do
1084
- if grep -qi "$keyword" "$output_file"; then
1085
- has_completion_signal=true
1086
- ((confidence_score+=10))
1087
- break
1088
- fi
1089
- done
1085
+ if [[ "$ralph_status_block_found" != "true" ]]; then
1086
+ # No status block found — fall back to heuristic analysis
1090
1087
 
1091
- # 3. Detect test-only loops
1092
- local test_command_count=0
1093
- local implementation_count=0
1094
- local error_count=0
1088
+ # 2. Detect completion keywords in natural language output
1089
+ for keyword in "${COMPLETION_KEYWORDS[@]}"; do
1090
+ if grep -qiw "$keyword" "$output_file"; then
1091
+ has_completion_signal=true
1092
+ ((confidence_score+=10))
1093
+ break
1094
+ fi
1095
+ done
1095
1096
 
1096
- test_command_count=$(grep -c -i "running tests\|npm test\|bats\|pytest\|jest" "$output_file" 2>/dev/null | head -1 || echo "0")
1097
- implementation_count=$(grep -c -i "implementing\|creating\|writing\|adding\|function\|class" "$output_file" 2>/dev/null | head -1 || echo "0")
1097
+ # 3. Detect test-only loops
1098
+ local test_command_count=0
1099
+ local implementation_count=0
1100
+ local error_count=0
1098
1101
 
1099
- # Strip whitespace and ensure it's a number
1100
- test_command_count=$(echo "$test_command_count" | tr -d '[:space:]')
1101
- implementation_count=$(echo "$implementation_count" | tr -d '[:space:]')
1102
+ test_command_count=$(grep -c -i "running tests\|npm test\|bats\|pytest\|jest" "$output_file" 2>/dev/null | head -1 || echo "0")
1103
+ implementation_count=$(grep -c -i "implementing\|creating\|writing\|adding\|function\|class" "$output_file" 2>/dev/null | head -1 || echo "0")
1102
1104
 
1103
- # Convert to integers with default fallback
1104
- test_command_count=${test_command_count:-0}
1105
- implementation_count=${implementation_count:-0}
1106
- test_command_count=$((test_command_count + 0))
1107
- implementation_count=$((implementation_count + 0))
1105
+ # Strip whitespace and ensure it's a number
1106
+ test_command_count=$(echo "$test_command_count" | tr -d '[:space:]')
1107
+ implementation_count=$(echo "$implementation_count" | tr -d '[:space:]')
1108
1108
 
1109
- if [[ $test_command_count -gt 0 ]] && [[ $implementation_count -eq 0 ]]; then
1110
- is_test_only=true
1111
- work_summary="Test execution only, no implementation"
1112
- fi
1109
+ # Convert to integers with default fallback
1110
+ test_command_count=${test_command_count:-0}
1111
+ implementation_count=${implementation_count:-0}
1112
+ test_command_count=$((test_command_count + 0))
1113
+ implementation_count=$((implementation_count + 0))
1113
1114
 
1114
- # 4. Detect stuck/error loops
1115
- # Use two-stage filtering to avoid counting JSON field names as errors
1116
- # Stage 1: Filter out JSON field patterns like "is_error": false
1117
- # Stage 2: Count actual error messages in specific contexts
1118
- # Pattern aligned with ralph_loop.sh to ensure consistent behavior
1119
- error_count=$(grep -v '"[^"]*error[^"]*":' "$output_file" 2>/dev/null | \
1120
- grep -cE '(^Error:|^ERROR:|^error:|\]: error|Link: error|Error occurred|failed with error|[Ee]xception|Fatal|FATAL)' \
1121
- 2>/dev/null || echo "0")
1122
- error_count=$(echo "$error_count" | tr -d '[:space:]')
1123
- error_count=${error_count:-0}
1124
- error_count=$((error_count + 0))
1115
+ if [[ $test_command_count -gt 0 ]] && [[ $implementation_count -eq 0 ]]; then
1116
+ is_test_only=true
1117
+ work_summary="Test execution only, no implementation"
1118
+ fi
1125
1119
 
1126
- if [[ $error_count -gt 5 ]]; then
1127
- is_stuck=true
1128
- fi
1120
+ # 4. Detect stuck/error loops
1121
+ # Use two-stage filtering to avoid counting JSON field names as errors
1122
+ # Stage 1: Filter out JSON field patterns like "is_error": false
1123
+ # Stage 2: Count actual error messages in specific contexts
1124
+ # Pattern aligned with ralph_loop.sh to ensure consistent behavior
1125
+ error_count=$(grep -v '"[^"]*error[^"]*":' "$output_file" 2>/dev/null | \
1126
+ grep -cE '(^Error:|^ERROR:|^error:|\]: error|Link: error|Error occurred|failed with error|[Ee]xception|Fatal|FATAL)' \
1127
+ 2>/dev/null || echo "0")
1128
+ error_count=$(echo "$error_count" | tr -d '[:space:]')
1129
+ error_count=${error_count:-0}
1130
+ error_count=$((error_count + 0))
1131
+
1132
+ if [[ $error_count -gt 5 ]]; then
1133
+ is_stuck=true
1134
+ fi
1129
1135
 
1130
- # 5. Detect "nothing to do" patterns
1131
- for pattern in "${NO_WORK_PATTERNS[@]}"; do
1132
- if grep -qi "$pattern" "$output_file"; then
1133
- has_completion_signal=true
1134
- ((confidence_score+=15))
1135
- work_summary="No work remaining"
1136
- break
1136
+ # 5. Detect "nothing to do" patterns
1137
+ for pattern in "${NO_WORK_PATTERNS[@]}"; do
1138
+ if grep -qiw "$pattern" "$output_file"; then
1139
+ has_completion_signal=true
1140
+ ((confidence_score+=15))
1141
+ work_summary="No work remaining"
1142
+ break
1143
+ fi
1144
+ done
1145
+
1146
+ # 7. Analyze output length trends (detect declining engagement)
1147
+ if [[ -f "$RALPH_DIR/.last_output_length" ]]; then
1148
+ local last_length
1149
+ last_length=$(cat "$RALPH_DIR/.last_output_length")
1150
+ if [[ "$last_length" -gt 0 ]]; then
1151
+ local length_ratio=$((output_length * 100 / last_length))
1152
+ if [[ $length_ratio -lt 50 ]]; then
1153
+ # Output is less than 50% of previous - possible completion
1154
+ ((confidence_score+=10))
1155
+ fi
1156
+ fi
1137
1157
  fi
1138
- done
1139
1158
 
1140
- # 6. Check for file changes (git integration)
1141
- # Fix #141: Detect both uncommitted changes AND committed changes
1159
+ # 9. Determine exit signal based on confidence (heuristic)
1160
+ if [[ $confidence_score -ge 40 || "$has_completion_signal" == "true" ]]; then
1161
+ exit_signal=true
1162
+ fi
1163
+ fi
1164
+
1165
+ # Always persist output length for next iteration (both paths)
1166
+ echo "$output_length" > "$RALPH_DIR/.last_output_length"
1167
+
1168
+ # 6. Check for file changes (git integration) — always runs
1142
1169
  if command -v git &>/dev/null && git rev-parse --git-dir >/dev/null 2>&1; then
1143
1170
  local loop_start_sha=""
1144
1171
  local current_sha=""
@@ -1174,19 +1201,7 @@ analyze_response() {
1174
1201
  fi
1175
1202
  fi
1176
1203
 
1177
- # 7. Analyze output length trends (detect declining engagement)
1178
- if [[ -f "$RALPH_DIR/.last_output_length" ]]; then
1179
- local last_length=$(cat "$RALPH_DIR/.last_output_length")
1180
- local length_ratio=$((output_length * 100 / last_length))
1181
-
1182
- if [[ $length_ratio -lt 50 ]]; then
1183
- # Output is less than 50% of previous - possible completion
1184
- ((confidence_score+=10))
1185
- fi
1186
- fi
1187
- echo "$output_length" > "$RALPH_DIR/.last_output_length"
1188
-
1189
- # 8. Extract work summary from output
1204
+ # 8. Extract work summary from output always runs
1190
1205
  if [[ -z "$work_summary" ]]; then
1191
1206
  # Try to find summary in output
1192
1207
  work_summary=$(grep -i "summary\|completed\|implemented" "$output_file" | head -1 | cut -c 1-100)
@@ -1195,21 +1210,6 @@ analyze_response() {
1195
1210
  fi
1196
1211
  fi
1197
1212
 
1198
- # Explicit EXIT_SIGNAL=false means "continue working", so completion
1199
- # heuristics must not register a done signal.
1200
- if [[ "$explicit_exit_signal_found" == "true" && "$exit_signal" == "false" ]]; then
1201
- has_completion_signal=false
1202
- fi
1203
-
1204
- # 9. Determine exit signal based on confidence (heuristic)
1205
- # IMPORTANT: Only apply heuristics if no explicit EXIT_SIGNAL was found in RALPH_STATUS
1206
- # Claude's explicit intent takes precedence over natural language pattern matching
1207
- if [[ "$explicit_exit_signal_found" != "true" ]]; then
1208
- if [[ $confidence_score -ge 40 || "$has_completion_signal" == "true" ]]; then
1209
- exit_signal=true
1210
- fi
1211
- fi
1212
-
1213
1213
  local has_permission_denials=false
1214
1214
  local permission_denial_count=0
1215
1215
  local denied_commands_json='[]'
@@ -74,6 +74,9 @@ _env_QUALITY_GATES="${QUALITY_GATES:-}"
74
74
  _env_QUALITY_GATE_MODE="${QUALITY_GATE_MODE:-}"
75
75
  _env_QUALITY_GATE_TIMEOUT="${QUALITY_GATE_TIMEOUT:-}"
76
76
  _env_QUALITY_GATE_ON_COMPLETION_ONLY="${QUALITY_GATE_ON_COMPLETION_ONLY:-}"
77
+ _env_REVIEW_ENABLED="${REVIEW_ENABLED:-}"
78
+ _env_REVIEW_INTERVAL="${REVIEW_INTERVAL:-}"
79
+ _env_REVIEW_MODE="${REVIEW_MODE:-}"
77
80
 
78
81
  # Now set defaults (only if not already set by environment)
79
82
  MAX_CALLS_PER_HOUR="${MAX_CALLS_PER_HOUR:-100}"
@@ -107,6 +110,18 @@ QUALITY_GATE_TIMEOUT="${QUALITY_GATE_TIMEOUT:-120}"
107
110
  QUALITY_GATE_ON_COMPLETION_ONLY="${QUALITY_GATE_ON_COMPLETION_ONLY:-false}"
108
111
  QUALITY_GATE_RESULTS_FILE="$RALPH_DIR/.quality_gate_results"
109
112
 
113
+ # Periodic code review configuration
114
+ REVIEW_ENABLED="${REVIEW_ENABLED:-false}"
115
+ REVIEW_INTERVAL="${REVIEW_INTERVAL:-5}"
116
+ REVIEW_FINDINGS_FILE="$RALPH_DIR/.review_findings.json"
117
+ REVIEW_PROMPT_FILE="$RALPH_DIR/REVIEW_PROMPT.md"
118
+ REVIEW_LAST_SHA_FILE="$RALPH_DIR/.review_last_sha"
119
+
120
+ # REVIEW_MODE is derived in initialize_runtime_context() after .ralphrc is loaded.
121
+ # This ensures backwards compat: old .ralphrc files with only REVIEW_ENABLED=true
122
+ # still map to enhanced mode. Env vars always win via the snapshot/restore mechanism.
123
+ REVIEW_MODE="${REVIEW_MODE:-off}"
124
+
110
125
  # Valid tool patterns for --allowed-tools validation
111
126
  # Default: Claude Code tools. Platform driver overwrites via driver_valid_tools() in main().
112
127
  # Validation runs in main() after load_platform_driver so the correct patterns are in effect.
@@ -256,6 +271,9 @@ load_ralphrc() {
256
271
  [[ -n "$_env_QUALITY_GATE_MODE" ]] && QUALITY_GATE_MODE="$_env_QUALITY_GATE_MODE"
257
272
  [[ -n "$_env_QUALITY_GATE_TIMEOUT" ]] && QUALITY_GATE_TIMEOUT="$_env_QUALITY_GATE_TIMEOUT"
258
273
  [[ -n "$_env_QUALITY_GATE_ON_COMPLETION_ONLY" ]] && QUALITY_GATE_ON_COMPLETION_ONLY="$_env_QUALITY_GATE_ON_COMPLETION_ONLY"
274
+ [[ -n "$_env_REVIEW_ENABLED" ]] && REVIEW_ENABLED="$_env_REVIEW_ENABLED"
275
+ [[ -n "$_env_REVIEW_INTERVAL" ]] && REVIEW_INTERVAL="$_env_REVIEW_INTERVAL"
276
+ [[ -n "$_env_REVIEW_MODE" ]] && REVIEW_MODE="$_env_REVIEW_MODE"
259
277
 
260
278
  normalize_claude_permission_mode
261
279
  RALPHRC_FILE="$config_file"
@@ -306,6 +324,14 @@ initialize_runtime_context() {
306
324
  fi
307
325
  fi
308
326
 
327
+ # Derive REVIEW_MODE after .ralphrc load so backwards-compat works:
328
+ # old .ralphrc files with only REVIEW_ENABLED=true map to enhanced mode.
329
+ if [[ "$REVIEW_MODE" == "off" && "$REVIEW_ENABLED" == "true" ]]; then
330
+ REVIEW_MODE="enhanced"
331
+ fi
332
+ # Keep REVIEW_ENABLED in sync for any code that checks it
333
+ [[ "$REVIEW_MODE" != "off" ]] && REVIEW_ENABLED="true" || REVIEW_ENABLED="false"
334
+
309
335
  # Load platform driver after config so PLATFORM_DRIVER can be overridden.
310
336
  load_platform_driver
311
337
  RUNTIME_CONTEXT_LOADED=true
@@ -346,7 +372,7 @@ get_tmux_base_index() {
346
372
  # Setup tmux session with monitor
347
373
  setup_tmux_session() {
348
374
  local session_name="ralph-$(date +%s)"
349
- local ralph_home="${RALPH_HOME:-$HOME/.ralph}"
375
+ local ralph_home="${RALPH_HOME:-$SCRIPT_DIR}"
350
376
  local project_dir="$(pwd)"
351
377
 
352
378
  initialize_runtime_context
@@ -1271,6 +1297,177 @@ build_loop_context() {
1271
1297
  echo "${context:0:500}"
1272
1298
  }
1273
1299
 
1300
+ # Check if a code review should run this iteration
1301
+ # Returns 0 (true) when review is due, 1 (false) otherwise
1302
+ # Args: $1 = loop_count, $2 = fix_plan_completed_delta (optional, for ultimate mode)
1303
+ should_run_review() {
1304
+ [[ "$REVIEW_MODE" == "off" ]] && return 1
1305
+ local loop_count=$1
1306
+ local fix_plan_delta=${2:-0}
1307
+
1308
+ # Never review on first loop (no implementation yet)
1309
+ (( loop_count < 1 )) && return 1
1310
+
1311
+ # Skip if circuit breaker is not CLOSED
1312
+ if [[ -f "$RALPH_DIR/.circuit_breaker_state" ]]; then
1313
+ local cb_state
1314
+ cb_state=$(jq -r '.state // "CLOSED"' "$RALPH_DIR/.circuit_breaker_state" 2>/dev/null)
1315
+ [[ "$cb_state" != "CLOSED" ]] && return 1
1316
+ fi
1317
+
1318
+ # Mode-specific trigger
1319
+ case "$REVIEW_MODE" in
1320
+ enhanced)
1321
+ (( loop_count % REVIEW_INTERVAL != 0 )) && return 1
1322
+ ;;
1323
+ ultimate)
1324
+ (( fix_plan_delta < 1 )) && return 1
1325
+ ;;
1326
+ *)
1327
+ # Unknown mode — treat as off
1328
+ return 1
1329
+ ;;
1330
+ esac
1331
+
1332
+ # Skip if no changes since last review (committed or uncommitted)
1333
+ if command -v git &>/dev/null && git rev-parse --git-dir &>/dev/null 2>&1; then
1334
+ local current_sha last_sha
1335
+ current_sha=$(git rev-parse HEAD 2>/dev/null || echo "unknown")
1336
+ last_sha=""
1337
+ [[ -f "$REVIEW_LAST_SHA_FILE" ]] && last_sha=$(cat "$REVIEW_LAST_SHA_FILE" 2>/dev/null)
1338
+ local has_uncommitted
1339
+ has_uncommitted=$(git status --porcelain 2>/dev/null | head -1)
1340
+ if [[ "$current_sha" == "$last_sha" && -z "$has_uncommitted" ]]; then
1341
+ return 1
1342
+ fi
1343
+ fi
1344
+ return 0
1345
+ }
1346
+
1347
+ # Build review findings context for injection into the next implementation loop
1348
+ # Returns a compact string (max 500-700 chars) with unresolved findings
1349
+ # HIGH/CRITICAL findings get a PRIORITY prefix and a higher char cap (700)
1350
+ build_review_context() {
1351
+ if [[ ! -f "$REVIEW_FINDINGS_FILE" ]]; then
1352
+ echo ""
1353
+ return
1354
+ fi
1355
+
1356
+ local severity issues_found summary
1357
+ severity=$(jq -r '.severity // ""' "$REVIEW_FINDINGS_FILE" 2>/dev/null)
1358
+ issues_found=$(jq -r '.issues_found // 0' "$REVIEW_FINDINGS_FILE" 2>/dev/null)
1359
+ summary=$(jq -r '.summary // ""' "$REVIEW_FINDINGS_FILE" 2>/dev/null | head -c 300)
1360
+
1361
+ if [[ "$issues_found" == "0" || -z "$severity" || "$severity" == "null" ]]; then
1362
+ echo ""
1363
+ return
1364
+ fi
1365
+
1366
+ # HIGH/CRITICAL findings: instruct the AI to fix them before picking a new story
1367
+ local context=""
1368
+ local max_len=500
1369
+ if [[ "$severity" == "HIGH" || "$severity" == "CRITICAL" ]]; then
1370
+ context="PRIORITY: Fix these code review findings BEFORE picking a new story. "
1371
+ max_len=700
1372
+ fi
1373
+ context+="REVIEW FINDINGS ($severity, $issues_found issues): $summary"
1374
+
1375
+ # Include top details if space allows
1376
+ local top_details
1377
+ top_details=$(jq -r '(.details[:2] // []) | map("- [\(.severity)] \(.file): \(.issue)") | join("; ")' "$REVIEW_FINDINGS_FILE" 2>/dev/null | head -c 150)
1378
+ if [[ -n "$top_details" && "$top_details" != "null" ]]; then
1379
+ context+=" Details: $top_details"
1380
+ fi
1381
+
1382
+ echo "${context:0:$max_len}"
1383
+ }
1384
+
1385
+ # Execute a periodic code review loop (read-only, no file modifications)
1386
+ # Uses a fresh ephemeral session with restricted tool permissions
1387
+ run_review_loop() {
1388
+ local loop_count=$1
1389
+
1390
+ log_status "INFO" "Starting periodic code review (loop #$loop_count)"
1391
+
1392
+ # Get diff context (committed + uncommitted changes)
1393
+ local last_sha=""
1394
+ [[ -f "$REVIEW_LAST_SHA_FILE" ]] && last_sha=$(cat "$REVIEW_LAST_SHA_FILE" 2>/dev/null)
1395
+ local diff_context=""
1396
+ if command -v git &>/dev/null && git rev-parse --git-dir &>/dev/null 2>&1; then
1397
+ local committed_diff="" uncommitted_diff=""
1398
+ if [[ -n "$last_sha" ]]; then
1399
+ committed_diff=$(git diff "$last_sha"..HEAD --stat 2>/dev/null | head -20 || true)
1400
+ else
1401
+ committed_diff=$(git diff HEAD~5..HEAD --stat 2>/dev/null | head -20 || true)
1402
+ fi
1403
+ uncommitted_diff=$(git diff --stat 2>/dev/null | head -10 || true)
1404
+ diff_context="${committed_diff}"
1405
+ if [[ -n "$uncommitted_diff" ]]; then
1406
+ diff_context+=$'\nUncommitted:\n'"${uncommitted_diff}"
1407
+ fi
1408
+ [[ -z "$diff_context" ]] && diff_context="No recent changes"
1409
+ fi
1410
+
1411
+ # Check review prompt exists
1412
+ if [[ ! -f "$REVIEW_PROMPT_FILE" ]]; then
1413
+ log_status "WARN" "Review prompt file not found: $REVIEW_PROMPT_FILE — skipping review"
1414
+ return 0
1415
+ fi
1416
+
1417
+ # Build review-specific context
1418
+ local review_context="CODE REVIEW LOOP (read-only). Analyze changes since last review. Recent changes: $diff_context"
1419
+
1420
+ # Save and override CLAUDE_ALLOWED_TOOLS for read-only mode
1421
+ local saved_tools="$CLAUDE_ALLOWED_TOOLS"
1422
+ CLAUDE_ALLOWED_TOOLS="Read,Glob,Grep"
1423
+
1424
+ local timeout_seconds=$((CLAUDE_TIMEOUT_MINUTES * 60))
1425
+ local review_output_file="$LOG_DIR/review_loop_${loop_count}.log"
1426
+
1427
+ # Build command with review prompt and NO session resume (ephemeral)
1428
+ if driver_build_command "$REVIEW_PROMPT_FILE" "$review_context" ""; then
1429
+ # Execute review (capture output)
1430
+ portable_timeout "${timeout_seconds}s" "${CLAUDE_CMD_ARGS[@]}" \
1431
+ < /dev/null > "$review_output_file" 2>&1 || true
1432
+ fi
1433
+
1434
+ # Restore CLAUDE_ALLOWED_TOOLS
1435
+ CLAUDE_ALLOWED_TOOLS="$saved_tools"
1436
+
1437
+ # Parse review findings from output
1438
+ if [[ -f "$review_output_file" ]]; then
1439
+ # Review ran successfully — save SHA so we don't re-review the same state
1440
+ git rev-parse HEAD > "$REVIEW_LAST_SHA_FILE" 2>/dev/null || true
1441
+
1442
+ local findings_json=""
1443
+ # Extract JSON between ---REVIEW_FINDINGS--- and ---END_REVIEW_FINDINGS--- markers
1444
+ findings_json=$(sed -n '/---REVIEW_FINDINGS---/,/---END_REVIEW_FINDINGS---/{//!p;}' "$review_output_file" 2>/dev/null | tr -d '\n' | head -c 5000)
1445
+
1446
+ # If output is JSON format, try extracting from result field first
1447
+ if [[ -z "$findings_json" ]]; then
1448
+ local raw_text
1449
+ raw_text=$(jq -r '.result // .content // ""' "$review_output_file" 2>/dev/null || cat "$review_output_file" 2>/dev/null)
1450
+ findings_json=$(echo "$raw_text" | sed -n '/---REVIEW_FINDINGS---/,/---END_REVIEW_FINDINGS---/{//!p;}' 2>/dev/null | tr -d '\n' | head -c 5000)
1451
+ fi
1452
+
1453
+ if [[ -n "$findings_json" ]]; then
1454
+ # Validate it's valid JSON before writing
1455
+ if echo "$findings_json" | jq . > /dev/null 2>&1; then
1456
+ local tmp_findings="$REVIEW_FINDINGS_FILE.tmp"
1457
+ echo "$findings_json" > "$tmp_findings"
1458
+ mv "$tmp_findings" "$REVIEW_FINDINGS_FILE"
1459
+ local issue_count
1460
+ issue_count=$(echo "$findings_json" | jq -r '.issues_found // 0' 2>/dev/null)
1461
+ log_status "INFO" "Code review complete. $issue_count issue(s) found."
1462
+ else
1463
+ log_status "WARN" "Review findings JSON is malformed — skipping"
1464
+ fi
1465
+ else
1466
+ log_status "INFO" "Code review complete. No structured findings extracted."
1467
+ fi
1468
+ fi
1469
+ }
1470
+
1274
1471
  # Get session file age in seconds (cross-platform)
1275
1472
  # Returns: age in seconds on stdout, or -1 if stat fails
1276
1473
  get_session_file_age_seconds() {
@@ -1805,6 +2002,13 @@ execute_claude_code() {
1805
2002
  if build_claude_command "$PROMPT_FILE" "$loop_context" "$session_id"; then
1806
2003
  use_modern_cli=true
1807
2004
  log_status "INFO" "Using modern CLI mode (${CLAUDE_OUTPUT_FORMAT} output)"
2005
+
2006
+ # Build review findings context (separate from loop context)
2007
+ local review_context=""
2008
+ review_context=$(build_review_context)
2009
+ if [[ -n "$review_context" ]]; then
2010
+ CLAUDE_CMD_ARGS+=("--append-system-prompt" "$review_context")
2011
+ fi
1808
2012
  else
1809
2013
  log_status "WARN" "Failed to build modern CLI command, falling back to legacy mode"
1810
2014
  if [[ "$LIVE_OUTPUT" == "true" ]]; then
@@ -2336,6 +2540,21 @@ main() {
2336
2540
 
2337
2541
  update_status "$loop_count" "$(cat "$CALL_COUNT_FILE")" "completed" "success"
2338
2542
 
2543
+ # Consume review findings after successful execution — the AI has received
2544
+ # the context via --append-system-prompt. Deleting here (not in
2545
+ # build_review_context) ensures findings survive transient loop failures.
2546
+ rm -f "$REVIEW_FINDINGS_FILE"
2547
+
2548
+ # Code review check
2549
+ local fix_plan_delta=0
2550
+ if [[ -f "$RESPONSE_ANALYSIS_FILE" ]]; then
2551
+ fix_plan_delta=$(jq -r '.analysis.fix_plan_completed_delta // 0' "$RESPONSE_ANALYSIS_FILE" 2>/dev/null || echo "0")
2552
+ [[ ! "$fix_plan_delta" =~ ^-?[0-9]+$ ]] && fix_plan_delta=0
2553
+ fi
2554
+ if should_run_review "$loop_count" "$fix_plan_delta"; then
2555
+ run_review_loop "$loop_count"
2556
+ fi
2557
+
2339
2558
  # Brief pause between successful executions
2340
2559
  sleep 5
2341
2560
  elif [ $exec_result -eq 3 ]; then
@@ -50,6 +50,18 @@ You are Ralph, an autonomous AI development agent working on a [YOUR PROJECT NAM
50
50
  - prefer small, reversible changes when requirements are ambiguous
51
51
  - surface blockers in the Ralph status block instead of starting a conversation
52
52
 
53
+ ## Self-Review Checklist (Before Reporting Status)
54
+
55
+ Before writing your RALPH_STATUS block, review your own work:
56
+
57
+ 1. Re-read the diff of files you modified this loop — check for obvious bugs, typos, missing error handling
58
+ 2. Verify you did not introduce regressions in existing functionality
59
+ 3. Confirm your changes match the spec in .ralph/specs/ for the story you worked on
60
+ 4. Check that new functions have proper error handling and edge case coverage
61
+ 5. Ensure you did not leave TODO/FIXME/HACK comments without justification
62
+
63
+ If you find issues, fix them before reporting status. This self-check costs nothing extra.
64
+
53
65
  ## 🎯 Status Reporting (CRITICAL - Ralph needs this!)
54
66
 
55
67
  **IMPORTANT**: At the end of your response, ALWAYS include this status block:
@@ -0,0 +1,60 @@
1
+ # Code Review Instructions
2
+
3
+ You are a code reviewer for [YOUR PROJECT NAME].
4
+ Your role is to analyze recent code changes and provide structured quality feedback.
5
+
6
+ ## CRITICAL RULES
7
+
8
+ - Do NOT modify any files
9
+ - Do NOT create any files
10
+ - Do NOT run any commands that change state
11
+ - ONLY read, analyze, and report
12
+
13
+ ## Review Checklist
14
+
15
+ 1. **Correctness**: Logic errors, off-by-one errors, missing edge cases
16
+ 2. **Error handling**: Errors properly caught and handled, no swallowed exceptions
17
+ 3. **Security**: Hardcoded secrets, injection vectors, unsafe patterns
18
+ 4. **Performance**: N+1 queries, unnecessary iterations, memory leaks
19
+ 5. **Code quality**: Dead code, duplicated logic, overly complex functions
20
+ 6. **Test coverage**: New features tested, tests meaningful (not testing implementation)
21
+ 7. **API contracts**: Public interfaces match their documentation and types
22
+
23
+ ## What to Analyze
24
+
25
+ - Read the git log and diff summary provided below
26
+ - Check .ralph/specs/ for specification compliance
27
+ - Review modified files for broader context
28
+ - Focus on substantive issues, not style nitpicks
29
+
30
+ ## Output Format
31
+
32
+ At the end of your analysis, include this block with a JSON payload:
33
+
34
+ ```
35
+ ---REVIEW_FINDINGS---
36
+ {"severity":"HIGH","issues_found":0,"summary":"No issues found.","details":[]}
37
+ ---END_REVIEW_FINDINGS---
38
+ ```
39
+
40
+ ### JSON Schema
41
+
42
+ ```json
43
+ {
44
+ "severity": "LOW | MEDIUM | HIGH | CRITICAL",
45
+ "issues_found": 0,
46
+ "summary": "One paragraph summary of findings",
47
+ "details": [
48
+ {
49
+ "severity": "HIGH",
50
+ "file": "src/example.ts",
51
+ "line": 42,
52
+ "issue": "Description of the issue",
53
+ "suggestion": "How to fix it"
54
+ }
55
+ ]
56
+ }
57
+ ```
58
+
59
+ The `severity` field at the top level reflects the highest severity among all issues found.
60
+ If no issues are found, set `severity` to `"LOW"`, `issues_found` to `0`, and `details` to `[]`.
@@ -125,6 +125,24 @@ QUALITY_GATE_TIMEOUT="${QUALITY_GATE_TIMEOUT:-120}"
125
125
  # Only run gates when the agent signals completion (EXIT_SIGNAL=true)
126
126
  QUALITY_GATE_ON_COMPLETION_ONLY="${QUALITY_GATE_ON_COMPLETION_ONLY:-false}"
127
127
 
128
+ # =============================================================================
129
+ # PERIODIC CODE REVIEW
130
+ # =============================================================================
131
+
132
+ # Review mode: off, enhanced, or ultimate (set via 'bmalph run --review [mode]')
133
+ # - off: no code review (default)
134
+ # - enhanced: periodic review every REVIEW_INTERVAL loops (~10-14% more tokens)
135
+ # - ultimate: review after every completed story (~20-30% more tokens)
136
+ # The review agent analyzes git diffs and outputs findings for the next implementation loop.
137
+ # Currently supported on Claude Code only.
138
+ REVIEW_MODE="${REVIEW_MODE:-off}"
139
+
140
+ # (Legacy) Enables review — prefer REVIEW_MODE instead
141
+ REVIEW_ENABLED="${REVIEW_ENABLED:-false}"
142
+
143
+ # Number of implementation loops between review sessions (enhanced mode only)
144
+ REVIEW_INTERVAL="${REVIEW_INTERVAL:-5}"
145
+
128
146
  # =============================================================================
129
147
  # ADVANCED SETTINGS
130
148
  # =============================================================================
package/dist/cli.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"check-updates.js","sourceRoot":"","sources":["../../src/commands/check-updates.ts"],"names":[],"mappings":"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"}