agentic-loop 3.4.3 → 3.4.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/package.json +1 -1
- package/ralph/verify/tests.sh +100 -37
- package/templates/PROMPT.md +7 -2
package/package.json
CHANGED
package/ralph/verify/tests.sh
CHANGED
|
@@ -4,26 +4,81 @@
|
|
|
4
4
|
|
|
5
5
|
# Check that new/modified source files have corresponding test files
|
|
6
6
|
# This catches the case where Claude writes code but forgets tests
|
|
7
|
+
# Config: .checks.requireTests = true|false (default: false)
|
|
7
8
|
verify_test_files_exist() {
|
|
8
9
|
local story_type="${RALPH_STORY_TYPE:-general}"
|
|
9
10
|
|
|
11
|
+
# Check if this check is enabled in config
|
|
12
|
+
local require_tests
|
|
13
|
+
require_tests=$(get_config '.checks.requireTests' "false")
|
|
14
|
+
if [[ "$require_tests" != "true" ]]; then
|
|
15
|
+
return 0
|
|
16
|
+
fi
|
|
17
|
+
|
|
10
18
|
# Skip for frontend stories (handled differently with .test.tsx pattern)
|
|
11
19
|
[[ "$story_type" == "frontend" ]] && return 0
|
|
12
20
|
|
|
13
21
|
echo -n " Test files exist for new code... "
|
|
14
22
|
|
|
23
|
+
local missing_tests=()
|
|
24
|
+
local checked=0
|
|
25
|
+
|
|
26
|
+
# Check Python files if this is a Python project
|
|
27
|
+
if [[ -f "pyproject.toml" ]] || [[ -f "requirements.txt" ]] || [[ -f "setup.py" ]]; then
|
|
28
|
+
_check_python_test_files missing_tests checked
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Check Go files if this is a Go project
|
|
32
|
+
if [[ -f "go.mod" ]]; then
|
|
33
|
+
_check_go_test_files missing_tests checked
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# If nothing to check, skip
|
|
37
|
+
if [[ $checked -eq 0 ]]; then
|
|
38
|
+
print_success "skipped (no new source files)"
|
|
39
|
+
return 0
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
if [[ ${#missing_tests[@]} -eq 0 ]]; then
|
|
43
|
+
print_success "passed ($checked files checked)"
|
|
44
|
+
return 0
|
|
45
|
+
else
|
|
46
|
+
print_error "missing tests"
|
|
47
|
+
echo ""
|
|
48
|
+
echo " The following files need test files:"
|
|
49
|
+
for file in "${missing_tests[@]}"; do
|
|
50
|
+
echo " $file"
|
|
51
|
+
done
|
|
52
|
+
echo ""
|
|
53
|
+
echo " Create test files for new code before completing the story."
|
|
54
|
+
echo " To disable this check: set .checks.requireTests = false in config.json"
|
|
55
|
+
|
|
56
|
+
# Save for failure context
|
|
57
|
+
{
|
|
58
|
+
echo "Missing test files for new code:"
|
|
59
|
+
for file in "${missing_tests[@]}"; do
|
|
60
|
+
echo " $file"
|
|
61
|
+
done
|
|
62
|
+
} > "$RALPH_DIR/last_test_existence_failure.log"
|
|
63
|
+
|
|
64
|
+
return 1
|
|
65
|
+
fi
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
# Helper: Check Python files have corresponding test files
|
|
69
|
+
# Usage: _check_python_test_files <missing_array_name> <checked_var_name>
|
|
70
|
+
_check_python_test_files() {
|
|
71
|
+
local -n _missing=$1
|
|
72
|
+
local -n _checked=$2
|
|
73
|
+
|
|
15
74
|
# Get list of modified Python files (excluding tests themselves)
|
|
16
75
|
local modified_files
|
|
17
76
|
modified_files=$(git diff --name-only HEAD~1 2>/dev/null | grep '\.py$' | grep -v 'test_' | grep -v '_test\.py' | grep -v '/tests/' || true)
|
|
18
77
|
|
|
19
|
-
|
|
20
|
-
if [[ -z "$modified_files" ]]; then
|
|
21
|
-
print_success "skipped (no new Python files)"
|
|
22
|
-
return 0
|
|
23
|
-
fi
|
|
78
|
+
[[ -z "$modified_files" ]] && return 0
|
|
24
79
|
|
|
25
|
-
local
|
|
26
|
-
|
|
80
|
+
local backend_dir
|
|
81
|
+
backend_dir=$(get_config '.directories.backend' "")
|
|
27
82
|
|
|
28
83
|
while IFS= read -r src_file; do
|
|
29
84
|
[[ -z "$src_file" ]] && continue
|
|
@@ -35,11 +90,11 @@ verify_test_files_exist() {
|
|
|
35
90
|
[[ "$src_file" == *"/alembic/"* ]] && continue
|
|
36
91
|
[[ "$src_file" == *"config"* ]] && continue
|
|
37
92
|
[[ "$src_file" == *"settings"* ]] && continue
|
|
93
|
+
[[ "$src_file" == *"conftest"* ]] && continue
|
|
38
94
|
|
|
39
|
-
((
|
|
95
|
+
((_checked++))
|
|
40
96
|
|
|
41
|
-
|
|
42
|
-
local base_name dir_name test_file
|
|
97
|
+
local base_name dir_name
|
|
43
98
|
base_name=$(basename "$src_file" .py)
|
|
44
99
|
dir_name=$(dirname "$src_file")
|
|
45
100
|
|
|
@@ -52,9 +107,6 @@ verify_test_files_exist() {
|
|
|
52
107
|
"tests/${base_name}_test.py"
|
|
53
108
|
)
|
|
54
109
|
|
|
55
|
-
# Check for backend dir patterns
|
|
56
|
-
local backend_dir
|
|
57
|
-
backend_dir=$(get_config '.directories.backend' "")
|
|
58
110
|
if [[ -n "$backend_dir" ]]; then
|
|
59
111
|
possible_tests+=(
|
|
60
112
|
"$backend_dir/tests/test_${base_name}.py"
|
|
@@ -71,35 +123,46 @@ verify_test_files_exist() {
|
|
|
71
123
|
done
|
|
72
124
|
|
|
73
125
|
if [[ "$found" == "false" ]]; then
|
|
74
|
-
|
|
126
|
+
_missing+=("$src_file → test_${base_name}.py")
|
|
75
127
|
fi
|
|
76
128
|
done <<< "$modified_files"
|
|
129
|
+
}
|
|
77
130
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
echo ""
|
|
84
|
-
echo " The following files need test files:"
|
|
85
|
-
for file in "${missing_tests[@]}"; do
|
|
86
|
-
local base_name
|
|
87
|
-
base_name=$(basename "$file" .py)
|
|
88
|
-
echo " $file → test_${base_name}.py"
|
|
89
|
-
done
|
|
90
|
-
echo ""
|
|
91
|
-
echo " Create test files for new code before completing the story."
|
|
131
|
+
# Helper: Check Go files have corresponding test files
|
|
132
|
+
# Usage: _check_go_test_files <missing_array_name> <checked_var_name>
|
|
133
|
+
_check_go_test_files() {
|
|
134
|
+
local -n _missing=$1
|
|
135
|
+
local -n _checked=$2
|
|
92
136
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
for file in "${missing_tests[@]}"; do
|
|
97
|
-
echo " $file"
|
|
98
|
-
done
|
|
99
|
-
} > "$RALPH_DIR/last_test_existence_failure.log"
|
|
137
|
+
# Get list of modified Go files (excluding tests themselves)
|
|
138
|
+
local modified_files
|
|
139
|
+
modified_files=$(git diff --name-only HEAD~1 2>/dev/null | grep '\.go$' | grep -v '_test\.go$' || true)
|
|
100
140
|
|
|
101
|
-
|
|
102
|
-
|
|
141
|
+
[[ -z "$modified_files" ]] && return 0
|
|
142
|
+
|
|
143
|
+
while IFS= read -r src_file; do
|
|
144
|
+
[[ -z "$src_file" ]] && continue
|
|
145
|
+
[[ ! -f "$src_file" ]] && continue
|
|
146
|
+
|
|
147
|
+
# Skip generated files, main.go, etc.
|
|
148
|
+
[[ "$src_file" == *"_generated.go" ]] && continue
|
|
149
|
+
[[ "$src_file" == *"/vendor/"* ]] && continue
|
|
150
|
+
[[ "$(basename "$src_file")" == "main.go" ]] && continue
|
|
151
|
+
[[ "$(basename "$src_file")" == "doc.go" ]] && continue
|
|
152
|
+
|
|
153
|
+
((_checked++))
|
|
154
|
+
|
|
155
|
+
local base_name dir_name
|
|
156
|
+
base_name=$(basename "$src_file" .go)
|
|
157
|
+
dir_name=$(dirname "$src_file")
|
|
158
|
+
|
|
159
|
+
# Go convention: foo.go -> foo_test.go in same directory
|
|
160
|
+
local test_file="$dir_name/${base_name}_test.go"
|
|
161
|
+
|
|
162
|
+
if [[ ! -f "$test_file" ]]; then
|
|
163
|
+
_missing+=("$src_file → ${base_name}_test.go")
|
|
164
|
+
fi
|
|
165
|
+
done <<< "$modified_files"
|
|
103
166
|
}
|
|
104
167
|
|
|
105
168
|
# Run unit tests
|
package/templates/PROMPT.md
CHANGED
|
@@ -24,19 +24,24 @@ For each story, you must:
|
|
|
24
24
|
|
|
25
25
|
**Every new code file MUST have a corresponding test file.**
|
|
26
26
|
|
|
27
|
-
For **
|
|
27
|
+
For **Python** backend stories:
|
|
28
28
|
- New file `foo.py` → create `tests/test_foo.py`
|
|
29
29
|
- Test each public function/method
|
|
30
30
|
- Test error cases (invalid input, missing data, API failures)
|
|
31
31
|
- Test edge cases (empty lists, None values, boundary conditions)
|
|
32
32
|
- Use pytest fixtures for database/API mocking
|
|
33
33
|
|
|
34
|
+
For **Go** projects:
|
|
35
|
+
- New file `foo.go` → create `foo_test.go` in same directory
|
|
36
|
+
- Use table-driven tests for multiple cases
|
|
37
|
+
- Test error paths and edge cases
|
|
38
|
+
|
|
34
39
|
For **frontend** stories (TypeScript/React):
|
|
35
40
|
- New component `Foo.tsx` → create `Foo.test.tsx`
|
|
36
41
|
- Test rendering, user interactions, error states
|
|
37
42
|
- Test loading states and empty states
|
|
38
43
|
|
|
39
|
-
**Do NOT skip tests.** If
|
|
44
|
+
**Do NOT skip tests.** If test enforcement is enabled, verification will fail without tests.
|
|
40
45
|
|
|
41
46
|
### 3. Verify It Actually Works
|
|
42
47
|
|