agentic-loop 3.4.3 → 3.4.4

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-loop",
3
- "version": "3.4.3",
3
+ "version": "3.4.4",
4
4
  "description": "Autonomous AI coding loop - PRD-driven development with Claude Code",
5
5
  "author": "Allie Jones <allie@allthrive.ai>",
6
6
  "license": "MIT",
@@ -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
- # If no Python files modified, skip
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 missing_tests=()
26
- local checked=0
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
- ((checked++))
95
+ ((_checked++))
40
96
 
41
- # Determine expected test file location
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
- missing_tests+=("$src_file")
126
+ _missing+=("$src_file → test_${base_name}.py")
75
127
  fi
76
128
  done <<< "$modified_files"
129
+ }
77
130
 
78
- if [[ ${#missing_tests[@]} -eq 0 ]]; then
79
- print_success "passed ($checked files checked)"
80
- return 0
81
- else
82
- print_error "missing tests"
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
- # Save for failure context
94
- {
95
- echo "Missing test files for new code:"
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
- return 1
102
- fi
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
@@ -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 **backend** stories (Python/API):
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 you create code without tests, verification will fail.
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