Skip to content

Commit 1b4a32c

Browse files
Flossyclaude
andcommitted
chore: Remove .claude directory and add to .gitignore
Remove Claude Code session data from repository. Add .claude to .gitignore to prevent future commits. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 8b62c27 commit 1b4a32c

32 files changed

Lines changed: 1684 additions & 96 deletions

.claude/scheduled_tasks.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"tasks": [
3+
{
4+
"id": "d26c2490",
5+
"cron": "*/10 * * * *",
6+
"prompt": "Run the automated code review workflow: execute .claude/scripts/code_review.sh, create GitHub issues via .claude/scripts/create_review_issues.py, auto-commit any fixes, and push to main. Stop when no new issues are found for 2 consecutive cycles.",
7+
"createdAt": 1780068397375,
8+
"lastFiredAt": 1780664647110,
9+
"recurring": true,
10+
"createdBySessionId": "8cbb97ab-1c4f-49bf-a8f7-b64b9b26e19a",
11+
"createdByPid": 1107370,
12+
"createdByProcStart": "3792428"
13+
}
14+
]
15+
}

.claude/scripts/brutal_review.sh

Lines changed: 312 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
1+
#!/bin/bash
2+
# BRUTAL Code Review - No Mercy for Bad Code
3+
# Finds: complexity, missing docs, anti-patterns, design issues, potential bugs
4+
5+
set -euo pipefail
6+
7+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
9+
REVIEW_OUTPUT_DIR="$PROJECT_ROOT/.claude/review-output"
10+
11+
mkdir -p "$REVIEW_OUTPUT_DIR"
12+
13+
echo "========================================="
14+
echo "BRUTAL Code Review - $(date)"
15+
echo "No mercy for bad code!"
16+
echo "========================================="
17+
18+
cd "$PROJECT_ROOT"
19+
20+
# Clean previous outputs
21+
rm -f "$REVIEW_OUTPUT_DIR"/brutal-*.txt
22+
23+
JAVA_COUNT=$(find src/main/java -name "*.java" -type f 2>/dev/null | wc -l)
24+
echo "Reviewing $JAVA_COUNT Java source files"
25+
echo ""
26+
27+
# 1. MISSING JAVADOC
28+
echo "[1/10] Hunting for missing JavaDoc..."
29+
{
30+
echo "=== Public API without JavaDoc ==="
31+
# Track whether we are inside a JavaDoc block (/** ... */) and whether the
32+
# most recently closed comment block was JavaDoc. When we encounter a public
33+
# or protected declaration, we check whether there was a JavaDoc comment that
34+
# ended between the declaration and the preceding code -- allowing for
35+
# annotations (including @Override), blank lines, or single-line /** ... */
36+
# comments in between.
37+
find src/main/java -name "*.java" -type f -exec awk '
38+
BEGIN { in_javadoc = 0; has_javadoc = 0; has_override = 0 }
39+
40+
# Start of a JavaDoc comment block
41+
/\/\*\*/ {
42+
in_javadoc = 1
43+
has_javadoc = 1
44+
}
45+
46+
# End of any block comment -- if we were in a JavaDoc block, mark it
47+
/\*\// {
48+
if (in_javadoc) {
49+
in_javadoc = 0
50+
# has_javadoc remains 1 until consumed or reset
51+
}
52+
}
53+
54+
# Skip lines inside JavaDoc/block comments (lines starting with *)
55+
/^[[:space:]]*\*/ { next }
56+
57+
# Track @Override annotation on its own line
58+
/^[[:space:]]*@Override[[:space:]]*$/ {
59+
has_override = 1
60+
next
61+
}
62+
63+
# Other annotations and blank lines between JavaDoc and declaration are
64+
# OK -- do not reset has_javadoc or has_override for those.
65+
/^[[:space:]]*@/ { next }
66+
/^[[:space:]]*$/ { next }
67+
68+
# Single-line comments should not reset state either
69+
/^[[:space:]]*\/\// { next }
70+
71+
# Check class/interface/enum declarations
72+
/^[[:space:]]*(public|protected)[[:space:]]+(static[[:space:]]+)?(class|interface|enum|@interface|abstract[[:space:]]+class)/ {
73+
if (!has_javadoc) print FILENAME":"NR":"$0
74+
has_javadoc = 0
75+
has_override = 0
76+
next
77+
}
78+
79+
# Check method/constructor declarations (lines containing a parenthesis)
80+
/^[[:space:]]*(public|protected)[[:space:]]+[^{;]*\(/ {
81+
if (!has_javadoc && !has_override) print FILENAME":"NR":"$0
82+
has_javadoc = 0
83+
has_override = 0
84+
next
85+
}
86+
87+
# Reset state on any other non-skipped line (code lines). This prevents
88+
# a JavaDoc on one member from being attributed to a later member.
89+
{
90+
if (!in_javadoc) {
91+
has_javadoc = 0
92+
has_override = 0
93+
}
94+
}
95+
' {} \;
96+
} > "$REVIEW_OUTPUT_DIR/brutal-missing-javadoc.txt" 2>/dev/null || true
97+
98+
JAVADOC_COUNT=$(tail -n +2 "$REVIEW_OUTPUT_DIR/brutal-missing-javadoc.txt" 2>/dev/null | grep -c . || true)
99+
if [ "$JAVADOC_COUNT" -gt 0 ]; then
100+
echo "✗ Found $JAVADOC_COUNT public APIs without JavaDoc"
101+
else
102+
echo "✓ All public APIs documented"
103+
fi
104+
105+
# 2. EXCEPTION SWALLOWING
106+
echo "[2/10] Looking for swallowed exceptions..."
107+
{
108+
echo "=== Empty Catch Blocks (Exception Swallowing) ==="
109+
find src/main/java -name "*.java" -exec grep -Pzo '(?s)catch\s*\([^)]+\)\s*\{\s*\}' {} \; 2>/dev/null | grep -v "^Binary" || true
110+
find src/main/java -name "*.java" -exec grep -A2 "catch.*Exception" {} \; | grep -B1 "^\s*//.*ignore\|^\s*//.*empty" || true
111+
} > "$REVIEW_OUTPUT_DIR/brutal-swallowed-exceptions.txt" 2>/dev/null || true
112+
113+
SWALLOW_COUNT=$(grep -c "catch" "$REVIEW_OUTPUT_DIR/brutal-swallowed-exceptions.txt" 2>/dev/null || true)
114+
if [ "$SWALLOW_COUNT" -gt 0 ]; then
115+
echo "✗ Found $SWALLOW_COUNT potential swallowed exceptions"
116+
else
117+
echo "✓ No obvious exception swallowing"
118+
fi
119+
120+
# 3. MAGIC NUMBERS
121+
echo "[3/10] Finding magic numbers..."
122+
{
123+
echo "=== Magic Numbers (Non-constant literals) ==="
124+
find src/main/java -name "*.java" -exec grep -Hn '\b[0-9]{2,}\b' {} \; | grep -v "private static final\|public static final\|@\|//\|/\*\|^[^:]*:[^:]*:[[:space:]]*\*" || true
125+
} > "$REVIEW_OUTPUT_DIR/brutal-magic-numbers.txt" 2>/dev/null || true
126+
127+
MAGIC_COUNT=$(tail -n +2 "$REVIEW_OUTPUT_DIR/brutal-magic-numbers.txt" 2>/dev/null | grep -c . || true)
128+
if [ "$MAGIC_COUNT" -gt 0 ]; then
129+
echo "✗ Found $MAGIC_COUNT potential magic numbers"
130+
else
131+
echo "✓ No magic numbers found"
132+
fi
133+
134+
# 4. GOD CLASSES (large files)
135+
echo "[4/10] Detecting God Classes..."
136+
{
137+
echo "=== God Classes (>500 lines) ==="
138+
find src/main/java -name "*.java" -type f -exec wc -l {} \; | awk '$1 > 500 {print}' | sort -rn
139+
} > "$REVIEW_OUTPUT_DIR/brutal-god-classes.txt" 2>/dev/null || true
140+
141+
GOD_COUNT=$(tail -n +2 "$REVIEW_OUTPUT_DIR/brutal-god-classes.txt" 2>/dev/null | grep -c . || true)
142+
if [ "$GOD_COUNT" -gt 0 ]; then
143+
echo "✗ Found $GOD_COUNT God Classes (>500 lines)"
144+
else
145+
echo "✓ No God Classes found"
146+
fi
147+
148+
# 5. DEEP NESTING
149+
echo "[5/10] Checking for deep nesting..."
150+
{
151+
echo "=== Deep Nesting (>3 levels) ==="
152+
find src/main/java -name "*.java" -exec awk '
153+
{
154+
indent = match($0, /[^ \t]/);
155+
if (indent > 0 && (indent-1)/4 > 3 && $0 ~ /if|for|while|switch/)
156+
print FILENAME":"NR":"(indent-1)/4" levels:"$0
157+
}
158+
' {} \;
159+
} > "$REVIEW_OUTPUT_DIR/brutal-deep-nesting.txt" 2>/dev/null || true
160+
161+
NEST_COUNT=$(tail -n +2 "$REVIEW_OUTPUT_DIR/brutal-deep-nesting.txt" 2>/dev/null | grep -c . || true)
162+
if [ "$NEST_COUNT" -gt 0 ]; then
163+
echo "✗ Found $NEST_COUNT deeply nested statements"
164+
else
165+
echo "✓ No excessive nesting"
166+
fi
167+
168+
# 6. NULL CHECKS WITHOUT VALIDATION
169+
echo "[6/10] Finding missing null validation..."
170+
{
171+
echo "=== Methods without null checks ==="
172+
# Look for public/protected methods with object parameters that genuinely lack null validation
173+
# Only flag methods that don't have Objects.requireNonNull in their first few lines
174+
find src/main/java -name "*.java" -exec awk '
175+
BEGIN { in_method=0; method_line=0 }
176+
/^[[:space:]]*(public|protected)[[:space:]]+(static|abstract|synchronized)?[[:space:]]*.*\([^)]*[A-Z][a-zA-Z0-9]*[^)]*\)/ && !/^\s*\/\// {
177+
# Check if @Nullable is on previous line
178+
if (prev ~ /@Nullable/) { in_method=0; next }
179+
# Only public/protected, not private
180+
in_method=1
181+
method_line=NR
182+
method_sig=$0
183+
check_count=0
184+
next
185+
}
186+
in_method && /^\s*{/ {
187+
in_method=2
188+
next
189+
}
190+
in_method==2 {
191+
# First few lines of method body
192+
if (check_count < 3) {
193+
if (/Objects\.requireNonNull|if.*null|throw.*NullPointer/) {
194+
in_method=0
195+
} else {
196+
check_count++
197+
}
198+
}
199+
if (/^\s*}/ && check_count >= 3) {
200+
# Likely missing null check
201+
print FILENAME":"method_line":"method_sig
202+
in_method=0
203+
}
204+
}
205+
{ prev=$0 }
206+
' {} \; 2>/dev/null | head -50
207+
} > "$REVIEW_OUTPUT_DIR/brutal-missing-null-checks.txt" 2>/dev/null || true
208+
209+
NULL_COUNT=$(tail -n +2 "$REVIEW_OUTPUT_DIR/brutal-missing-null-checks.txt" 2>/dev/null | wc -l)
210+
if [ "$NULL_COUNT" -gt 0 ]; then
211+
echo "✗ Found $NULL_COUNT public methods potentially missing null checks"
212+
else
213+
echo "✓ Null checking looks good"
214+
fi
215+
216+
# 7. MUTABLE STATIC FIELDS
217+
echo "[7/10] Hunting for mutable static state..."
218+
{
219+
echo "=== Mutable Static Fields (not final) ==="
220+
find src/main/java -name "*.java" -exec grep -Hn "private static [^f].*=\|public static [^f].*=" {} \; | grep -v "final\|Logger" || true
221+
} > "$REVIEW_OUTPUT_DIR/brutal-mutable-static.txt" 2>/dev/null || true
222+
223+
# Count actual findings (skip the header and empty lines)
224+
MUTABLE_COUNT=$(tail -n +2 "$REVIEW_OUTPUT_DIR/brutal-mutable-static.txt" 2>/dev/null | grep -c . || true)
225+
if [ "$MUTABLE_COUNT" -gt 0 ]; then
226+
echo "✗ Found $MUTABLE_COUNT mutable static fields"
227+
else
228+
echo "✓ No mutable static state"
229+
fi
230+
231+
# 8. RESOURCE LEAKS
232+
echo "[8/10] Checking for resource leaks..."
233+
{
234+
echo "=== Potential Resource Leaks (no try-with-resources) ==="
235+
# Use Python for accurate multiline try-with-resources detection
236+
if command -v python3 &> /dev/null; then
237+
python3 "$SCRIPT_DIR/check_resource_leaks.py" 2>/dev/null || true
238+
else
239+
# Fallback grep-based detection (less accurate for multiline patterns)
240+
find src/main/java -name "*.java" -exec grep -Hn "new.*Stream\|new.*Reader\|new.*Writer\|new.*Connection" {} \; | grep -v "try (" || true
241+
fi
242+
} > "$REVIEW_OUTPUT_DIR/brutal-resource-leaks.txt" 2>/dev/null || true
243+
244+
LEAK_COUNT=$(tail -n +2 "$REVIEW_OUTPUT_DIR/brutal-resource-leaks.txt" 2>/dev/null | grep -c . || true)
245+
if [ "$LEAK_COUNT" -gt 0 ]; then
246+
echo "✗ Found $LEAK_COUNT potential resource leaks"
247+
else
248+
echo "✓ Resources properly managed"
249+
fi
250+
251+
# 9. OVERLY BROAD EXCEPTION CATCHING
252+
echo "[9/10] Finding overly broad exception handling..."
253+
{
254+
echo "=== Catching Generic Exceptions ==="
255+
find src/main/java -name "*.java" -exec grep -Hn "catch.*Exception\s*e)\|catch.*Throwable" {} \; | grep -v "IOException\|SQLException\|InterruptedException" || true
256+
} > "$REVIEW_OUTPUT_DIR/brutal-broad-exceptions.txt" 2>/dev/null || true
257+
258+
BROAD_COUNT=$(tail -n +2 "$REVIEW_OUTPUT_DIR/brutal-broad-exceptions.txt" 2>/dev/null | grep -c . || true)
259+
if [ "$BROAD_COUNT" -gt 0 ]; then
260+
echo "✗ Found $BROAD_COUNT overly broad exception catches"
261+
else
262+
echo "✓ Exception handling is specific"
263+
fi
264+
265+
# 10. MISSING @Override
266+
echo "[10/10] Checking for missing @Override annotations..."
267+
{
268+
echo "=== Missing @Override Annotations ==="
269+
find src/main/java -name "*.java" -exec awk '
270+
/@Override/ { override=1; next }
271+
/^[[:space:]]*(public|protected)[[:space:]]+.*\(/ {
272+
if (!override && ($0 ~ /equals\(|hashCode\(|toString\(|compareTo\(/))
273+
print FILENAME":"NR":"$0
274+
override=0
275+
}
276+
{ if ($0 !~ /^[[:space:]]*$/ && $0 !~ /^[[:space:]]*\//) override=0 }
277+
' {} \;
278+
} > "$REVIEW_OUTPUT_DIR/brutal-missing-override.txt" 2>/dev/null || true
279+
280+
OVERRIDE_COUNT=$(tail -n +2 "$REVIEW_OUTPUT_DIR/brutal-missing-override.txt" 2>/dev/null | grep -c . || true)
281+
if [ "$OVERRIDE_COUNT" -gt 0 ]; then
282+
echo "✗ Found $OVERRIDE_COUNT missing @Override annotations"
283+
else
284+
echo "✓ @Override annotations look good"
285+
fi
286+
287+
echo ""
288+
echo "========================================="
289+
echo "BRUTAL Review Complete - $(date)"
290+
echo "========================================="
291+
292+
# Count total findings (skip header lines starting with === and empty lines)
293+
TOTAL_FINDINGS=0
294+
for file in "$REVIEW_OUTPUT_DIR"/brutal-*.txt; do
295+
if [ -f "$file" ] && [ -s "$file" ]; then
296+
COUNT=$(tail -n +2 "$file" | grep -c . || true)
297+
if [ "$COUNT" -gt 0 ]; then
298+
TOTAL_FINDINGS=$((TOTAL_FINDINGS + COUNT))
299+
fi
300+
fi
301+
done
302+
303+
echo "Total findings: $TOTAL_FINDINGS"
304+
echo ""
305+
306+
if [ $TOTAL_FINDINGS -eq 0 ]; then
307+
echo "🎉 Code passed brutal review!"
308+
else
309+
echo "💀 Fix these issues or face the consequences!"
310+
fi
311+
312+
exit 0

0 commit comments

Comments
 (0)