Skip to content

Commit 93d7f44

Browse files
authored
Add upfront dependency check for RLCR loop (codex, jq, git) (#32)
1 parent 42d1a3d commit 93d7f44

File tree

5 files changed

+173
-16
lines changed

5 files changed

+173
-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: 139 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,140 @@ 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+
echo '#!/bin/bash
1199+
exit 0' > "$TEST_DIR/repo49/bin/jq"
1200+
chmod +x "$TEST_DIR/repo49/bin/jq"
1201+
1202+
OUTPUT=$(PATH="$TEST_DIR/repo49/bin:$PATH" run_rlcr_setup "$TEST_DIR/repo49" plan.md 2>&1) || EXIT_CODE=$?
1203+
EXIT_CODE=${EXIT_CODE:-0}
1204+
# Should NOT fail at dependency check - should proceed further
1205+
if echo "$OUTPUT" | grep -qi "Missing required dependencies"; then
1206+
fail "All deps present" "no dependency error" "dependency error shown"
1207+
else
1208+
pass "All dependencies present - proceeds past dependency check"
1209+
fi
1210+
10771211
# ========================================
10781212
# Summary
10791213
# ========================================

0 commit comments

Comments
 (0)