Skip to content

Commit 1984077

Browse files
committed
Add upfront dependency check for RLCR loop (codex, jq, git)
Check all required external tools (codex, jq, git) at the start of setup-rlcr-loop.sh before any loop initialization. Previously, jq was not checked at all and would cause cryptic failures mid-loop when the stop hook tried to produce JSON output. Now users get a single clear error listing all missing tools with install links. Replaces the standalone codex check that ran later in the setup flow. https://claude.ai/code/session_01RHtyGrUsBvUC6S924XhcM7
1 parent 42d1a3d commit 1984077

File tree

5 files changed

+170
-16
lines changed

5 files changed

+170
-16
lines changed

.claude-plugin/marketplace.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"name": "humanize",
99
"source": "./",
1010
"description": "Humanize - An iterative development plugin that uses Codex to review Claude's work. Creates a feedback loop where Claude implements plans and Codex independently reviews progress, ensuring quality through continuous refinement.",
11-
"version": "1.11.0"
11+
"version": "1.12.0"
1212
}
1313
]
1414
}

.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "humanize",
33
"description": "Humanize - An iterative development plugin that uses Codex to review Claude's work. Creates a feedback loop where Claude implements plans and Codex independently reviews progress, ensuring quality through continuous refinement.",
4-
"version": "1.11.0",
4+
"version": "1.12.0",
55
"author": {
66
"name": "humania-org"
77
},

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Humanize
22

3-
**Current Version: 1.11.0**
3+
**Current Version: 1.12.0**
44

55
> Derived from the [GAAC (GitHub-as-a-Context)](https://github.com/SihaoLiu/gaac) project.
66

scripts/setup-rlcr-loop.sh

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,37 @@ PROJECT_ROOT="${CLAUDE_PROJECT_DIR:-$(pwd)}"
254254

255255
# loop-common.sh already sourced above (provides find_active_loop, find_active_pr_loop, etc.)
256256

257+
# ========================================
258+
# Required Dependency Check
259+
# ========================================
260+
# Check all required external tools upfront so users get a single,
261+
# actionable error message instead of a cryptic mid-loop failure.
262+
263+
MISSING_DEPS=()
264+
265+
if ! command -v codex &>/dev/null; then
266+
MISSING_DEPS+=("codex - Install: https://github.com/openai/codex")
267+
fi
268+
269+
if ! command -v jq &>/dev/null; then
270+
MISSING_DEPS+=("jq - Install: https://jqlang.github.io/jq/download/")
271+
fi
272+
273+
if ! command -v git &>/dev/null; then
274+
MISSING_DEPS+=("git - Install: https://git-scm.com/downloads")
275+
fi
276+
277+
if [[ ${#MISSING_DEPS[@]} -gt 0 ]]; then
278+
echo "Error: Missing required dependencies for RLCR loop" >&2
279+
echo "" >&2
280+
for dep in "${MISSING_DEPS[@]}"; do
281+
echo " - $dep" >&2
282+
done
283+
echo "" >&2
284+
echo "Please install the missing tools and try again." >&2
285+
exit 1
286+
fi
287+
257288
# ========================================
258289
# Mutual Exclusion Check
259290
# ========================================
@@ -578,14 +609,6 @@ else
578609
LINE_COUNT=0
579610
fi # End of skip-impl plan file content validation skip
580611

581-
# Check codex is available
582-
if ! command -v codex &>/dev/null; then
583-
echo "Error: start-rlcr-loop requires codex to run" >&2
584-
echo "" >&2
585-
echo "Please install Codex CLI: https://openai.com/codex" >&2
586-
exit 1
587-
fi
588-
589612
# ========================================
590613
# Record Branch
591614
# ========================================

tests/robustness/test-setup-scripts-robustness.sh

Lines changed: 136 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -673,21 +673,21 @@ create_minimal_plan "$TEST_DIR/repo28"
673673
echo "plan.md" >> "$TEST_DIR/repo28/.gitignore"
674674
git -C "$TEST_DIR/repo28" add .gitignore && git -C "$TEST_DIR/repo28" commit -q -m "Add gitignore"
675675

676-
# Create empty bin dir with no codex - should fail at codex check
676+
# Create empty bin dir with no codex - should fail at dependency check
677677
mkdir -p "$TEST_DIR/repo28/bin"
678678
# Prepend empty bin dir to hide system codex (if any)
679679

680680
OUTPUT=$(PATH="$TEST_DIR/repo28/bin:$PATH" run_rlcr_setup "$TEST_DIR/repo28" plan.md 2>&1) || EXIT_CODE=$?
681681
EXIT_CODE=${EXIT_CODE:-0}
682-
# Should fail at codex check (not argument parsing) - proves args were valid
682+
# Should fail at dependency check (not argument parsing) - proves args were valid
683683
if [[ $EXIT_CODE -ne 0 ]] && echo "$OUTPUT" | grep -qi "codex"; then
684-
pass "Valid RLCR setup proceeds to codex check"
684+
pass "Valid RLCR setup proceeds to dependency check"
685685
else
686686
# If codex is actually installed, it might proceed further
687687
if command -v codex &>/dev/null; then
688688
pass "Valid RLCR setup (codex available, may proceed further)"
689689
else
690-
fail "Valid RLCR setup" "fail at codex check" "exit=$EXIT_CODE"
690+
fail "Valid RLCR setup" "fail at dependency check" "exit=$EXIT_CODE"
691691
fi
692692
fi
693693

@@ -704,7 +704,7 @@ mkdir -p "$TEST_DIR/repo29/bin"
704704

705705
OUTPUT=$(PATH="$TEST_DIR/repo29/bin:$PATH" run_rlcr_setup "$TEST_DIR/repo29" plan.md --max 10 --codex-timeout 3600 2>&1) || EXIT_CODE=$?
706706
EXIT_CODE=${EXIT_CODE:-0}
707-
# Should NOT fail at argument parsing - should fail later (codex check)
707+
# Should NOT fail at argument parsing - should fail later (dependency check)
708708
if echo "$OUTPUT" | grep -qi "positive integer"; then
709709
fail "Valid numeric args" "accepted" "rejected as invalid"
710710
else
@@ -1074,6 +1074,137 @@ else
10741074
fi
10751075
fi
10761076

1077+
# ========================================
1078+
# Dependency Check Tests
1079+
# ========================================
1080+
1081+
echo ""
1082+
echo "--- Dependency Check Tests ---"
1083+
echo ""
1084+
1085+
# Test 46: Missing codex shows dependency error
1086+
echo "Test 46: Missing codex shows dependency error"
1087+
mkdir -p "$TEST_DIR/repo46"
1088+
init_basic_git_repo "$TEST_DIR/repo46"
1089+
create_minimal_plan "$TEST_DIR/repo46"
1090+
echo "plan.md" >> "$TEST_DIR/repo46/.gitignore"
1091+
git -C "$TEST_DIR/repo46" add .gitignore && git -C "$TEST_DIR/repo46" commit -q -m "Add gitignore"
1092+
1093+
# Create bin dir with jq but no codex
1094+
mkdir -p "$TEST_DIR/repo46/bin"
1095+
cat > "$TEST_DIR/repo46/bin/jq" << 'EOF'
1096+
#!/bin/bash
1097+
exit 0
1098+
EOF
1099+
chmod +x "$TEST_DIR/repo46/bin/jq"
1100+
# Hide system codex by making the only codex on PATH our empty bin dir
1101+
OUTPUT=$(PATH="$TEST_DIR/repo46/bin:/usr/bin:/bin" run_rlcr_setup "$TEST_DIR/repo46" plan.md 2>&1) || EXIT_CODE=$?
1102+
EXIT_CODE=${EXIT_CODE:-0}
1103+
if [[ $EXIT_CODE -ne 0 ]] && echo "$OUTPUT" | grep -qi "Missing required dependencies" && echo "$OUTPUT" | grep -q "codex"; then
1104+
pass "Missing codex detected in dependency check"
1105+
else
1106+
if command -v codex &>/dev/null; then
1107+
skip "Cannot test missing codex (codex is installed on this system)"
1108+
else
1109+
fail "Missing codex detection" "dependency error mentioning codex" "exit=$EXIT_CODE output=$OUTPUT"
1110+
fi
1111+
fi
1112+
1113+
# Test 47: Missing jq shows dependency error
1114+
echo ""
1115+
echo "Test 47: Missing jq shows dependency error"
1116+
mkdir -p "$TEST_DIR/repo47"
1117+
init_basic_git_repo "$TEST_DIR/repo47"
1118+
create_minimal_plan "$TEST_DIR/repo47"
1119+
echo "plan.md" >> "$TEST_DIR/repo47/.gitignore"
1120+
git -C "$TEST_DIR/repo47" add .gitignore && git -C "$TEST_DIR/repo47" commit -q -m "Add gitignore"
1121+
1122+
# Create bin dir with codex but no jq
1123+
mkdir -p "$TEST_DIR/repo47/bin"
1124+
cat > "$TEST_DIR/repo47/bin/codex" << 'EOF'
1125+
#!/bin/bash
1126+
exit 0
1127+
EOF
1128+
chmod +x "$TEST_DIR/repo47/bin/codex"
1129+
# Use a restricted PATH that has git but no jq
1130+
OUTPUT=$(PATH="$TEST_DIR/repo47/bin:/usr/bin:/bin" run_rlcr_setup "$TEST_DIR/repo47" plan.md 2>&1) || EXIT_CODE=$?
1131+
EXIT_CODE=${EXIT_CODE:-0}
1132+
if [[ $EXIT_CODE -ne 0 ]] && echo "$OUTPUT" | grep -qi "Missing required dependencies" && echo "$OUTPUT" | grep -q "jq"; then
1133+
pass "Missing jq detected in dependency check"
1134+
else
1135+
if command -v jq &>/dev/null && [[ "$(command -v jq)" == /usr/bin/jq || "$(command -v jq)" == /bin/jq ]]; then
1136+
skip "Cannot test missing jq (jq is available in /usr/bin or /bin)"
1137+
else
1138+
fail "Missing jq detection" "dependency error mentioning jq" "exit=$EXIT_CODE output=$OUTPUT"
1139+
fi
1140+
fi
1141+
1142+
# Test 48: Multiple missing dependencies listed together
1143+
echo ""
1144+
echo "Test 48: Multiple missing dependencies listed together"
1145+
mkdir -p "$TEST_DIR/repo48"
1146+
init_basic_git_repo "$TEST_DIR/repo48"
1147+
create_minimal_plan "$TEST_DIR/repo48"
1148+
echo "plan.md" >> "$TEST_DIR/repo48/.gitignore"
1149+
git -C "$TEST_DIR/repo48" add .gitignore && git -C "$TEST_DIR/repo48" commit -q -m "Add gitignore"
1150+
1151+
# Create a bin dir that has system tools but not codex or jq.
1152+
# We symlink all of /usr/bin except codex and jq, plus add git.
1153+
mkdir -p "$TEST_DIR/repo48/bin"
1154+
# Only include essential tools (bash, env, git, etc.) but NOT codex or jq
1155+
for tool in bash env cat sed awk grep mkdir date head od tr wc dirname sort ls rm cp mv chmod ln readlink printf; do
1156+
TOOL_PATH=$(command -v "$tool" 2>/dev/null || true)
1157+
if [[ -n "$TOOL_PATH" && -x "$TOOL_PATH" && ! -e "$TEST_DIR/repo48/bin/$tool" ]]; then
1158+
ln -s "$TOOL_PATH" "$TEST_DIR/repo48/bin/$tool"
1159+
fi
1160+
done
1161+
REAL_GIT_PATH=$(command -v git)
1162+
ln -s "$REAL_GIT_PATH" "$TEST_DIR/repo48/bin/git"
1163+
# Also link timeout/gtimeout if available
1164+
for tool in timeout gtimeout; do
1165+
TOOL_PATH=$(command -v "$tool" 2>/dev/null || true)
1166+
if [[ -n "$TOOL_PATH" && -x "$TOOL_PATH" ]]; then
1167+
ln -s "$TOOL_PATH" "$TEST_DIR/repo48/bin/$tool"
1168+
fi
1169+
done
1170+
1171+
OUTPUT=$(PATH="$TEST_DIR/repo48/bin" run_rlcr_setup "$TEST_DIR/repo48" plan.md 2>&1) || EXIT_CODE=$?
1172+
EXIT_CODE=${EXIT_CODE:-0}
1173+
if [[ $EXIT_CODE -ne 0 ]] && echo "$OUTPUT" | grep -q "codex" && echo "$OUTPUT" | grep -q "jq"; then
1174+
pass "Multiple missing dependencies listed in single error"
1175+
else
1176+
# If both tools happen to be in our restricted bin, skip
1177+
if PATH="$TEST_DIR/repo48/bin" command -v codex &>/dev/null && PATH="$TEST_DIR/repo48/bin" command -v jq &>/dev/null; then
1178+
skip "Cannot test multiple missing deps (both available in restricted PATH)"
1179+
else
1180+
fail "Multiple missing deps" "error listing codex and jq" "exit=$EXIT_CODE"
1181+
fi
1182+
fi
1183+
1184+
# Test 49: All dependencies present passes check
1185+
echo ""
1186+
echo "Test 49: All dependencies present passes dependency check"
1187+
mkdir -p "$TEST_DIR/repo49"
1188+
init_basic_git_repo "$TEST_DIR/repo49"
1189+
create_minimal_plan "$TEST_DIR/repo49"
1190+
echo "plan.md" >> "$TEST_DIR/repo49/.gitignore"
1191+
git -C "$TEST_DIR/repo49" add .gitignore && git -C "$TEST_DIR/repo49" commit -q -m "Add gitignore"
1192+
1193+
# Create mock codex and jq
1194+
mkdir -p "$TEST_DIR/repo49/bin"
1195+
echo '#!/bin/bash
1196+
exit 0' > "$TEST_DIR/repo49/bin/codex"
1197+
chmod +x "$TEST_DIR/repo49/bin/codex"
1198+
1199+
OUTPUT=$(PATH="$TEST_DIR/repo49/bin:$PATH" run_rlcr_setup "$TEST_DIR/repo49" plan.md 2>&1) || EXIT_CODE=$?
1200+
EXIT_CODE=${EXIT_CODE:-0}
1201+
# Should NOT fail at dependency check - should proceed further
1202+
if echo "$OUTPUT" | grep -qi "Missing required dependencies"; then
1203+
fail "All deps present" "no dependency error" "dependency error shown"
1204+
else
1205+
pass "All dependencies present - proceeds past dependency check"
1206+
fi
1207+
10771208
# ========================================
10781209
# Summary
10791210
# ========================================

0 commit comments

Comments
 (0)