Restructure QA output for maximum actionability

Complete rewrite of output format:

1. PRIORITY FILES section:
   - Shows files with CRITICAL/HIGH issues sorted by count
   - Breaks down severity per file: "file.sh (CRITICAL: 2, HIGH: 5)"
   - Calculates coverage: "Fix top 3 files = 50% of issues"
   - Immediately answers: "Which files should I fix first?"

2. HIGH ISSUES grouped BY FILE:
   - Shows first 3 issues per file with line numbers
   - Displays total count: "file.sh (12 issues)"
   - Groups related issues together for batch fixing
   - Much easier to work through file-by-file

3. QUICK WINS section:
   - Shows patterns appearing 10+ times
   - Provides fix description for each pattern
   - Example: "15 × SOURCE - Add existence checks before sourcing"
   - Identifies opportunities to fix many issues at once

4. MEDIUM/LOW collapsed:
   - Single summary line (not pages of low-priority detail)
   - Provides grep command to view when needed

Benefits for AI/human readers:
- Answers "where do I start?" immediately
- Groups issues by file (actionable context)
- Shows impact (% coverage of top files)
- Identifies patterns (fix 15 issues with one approach)
- Reduces noise (no pages of MEDIUM/LOW details)
- Clear hierarchy: PRIORITY → CRITICAL → HIGH → QUICK WINS

Output is now optimized for taking action, not just reporting.
This commit is contained in:
cschantz
2026-01-08 23:17:19 -05:00
parent 97b91ba5f6
commit 5096b0f4cc
+86 -35
View File
@@ -3318,9 +3318,42 @@ fi
echo "" echo ""
# CRITICAL issues: Show ALL (no truncation) # PRIORITY FILES: Show which files have CRITICAL/HIGH issues
if [ "$crit" -gt 0 ] || [ "$high" -gt 0 ]; then
echo -e "${BOLD}PRIORITY FILES (CRITICAL/HIGH issues):${NC}"
{
[ "$crit" -gt 0 ] && grep "^CRITICAL|" "$REPORT" | cut -d'|' -f2
[ "$high" -gt 0 ] && grep "^HIGH|" "$REPORT" | cut -d'|' -f2
} | sed "s|$TOOLKIT_PATH/||" | sort | uniq -c | sort -rn | head -10 | while read count file; do
# Get breakdown by severity for this file
crit_in_file=$(grep "^CRITICAL|.*${file}" "$REPORT" 2>/dev/null | wc -l)
high_in_file=$(grep "^HIGH|.*${file}" "$REPORT" 2>/dev/null | wc -l)
if [ "$crit_in_file" -gt 0 ]; then
printf " ${RED}${NC} %s ${RED}(CRITICAL: %d, HIGH: %d)${NC}\n" "$file" "$crit_in_file" "$high_in_file"
else
printf " ${YELLOW}${NC} %s ${YELLOW}(HIGH: %d)${NC}\n" "$file" "$high_in_file"
fi
done
# Calculate coverage
total_priority=$((crit + high))
top3_count=$(
{
[ "$crit" -gt 0 ] && grep "^CRITICAL|" "$REPORT" | cut -d'|' -f2
[ "$high" -gt 0 ] && grep "^HIGH|" "$REPORT" | cut -d'|' -f2
} | sed "s|$TOOLKIT_PATH/||" | sort | uniq -c | sort -rn | head -3 | awk '{sum+=$1} END {print sum}'
)
if [ "$total_priority" -gt 0 ] && [ -n "$top3_count" ] && [ "$top3_count" -gt 0 ]; then
coverage=$((top3_count * 100 / total_priority))
echo -e " ${DIM}→ Fix top 3 files = ${coverage}% of CRITICAL/HIGH issues${NC}"
fi
echo ""
fi
# CRITICAL issues grouped by file
if [ "$crit" -gt 0 ]; then if [ "$crit" -gt 0 ]; then
echo -e "${RED}${BOLD}CRITICAL ISSUES ($crit) - MUST FIX:${NC}" echo -e "${RED}${BOLD}CRITICAL ISSUES ($crit) - MUST FIX IMMEDIATELY:${NC}"
grep "^CRITICAL|" "$REPORT" | while IFS='|' read -r sev file line issue; do grep "^CRITICAL|" "$REPORT" | while IFS='|' read -r sev file line issue; do
rel_file="${file#$TOOLKIT_PATH/}" rel_file="${file#$TOOLKIT_PATH/}"
printf " ${RED}${NC} %s:%s - %s\n" "$rel_file" "$line" "$issue" printf " ${RED}${NC} %s:%s - %s\n" "$rel_file" "$line" "$issue"
@@ -3328,50 +3361,68 @@ if [ "$crit" -gt 0 ]; then
echo "" echo ""
fi fi
# HIGH issues: Show top 20, group by file # HIGH issues: Group by file for easier action
if [ "$high" -gt 0 ]; then if [ "$high" -gt 0 ]; then
echo -e "${YELLOW}${BOLD}HIGH ISSUES ($high) - FIX SOON:${NC}" echo -e "${YELLOW}${BOLD}HIGH ISSUES BY FILE (showing top 15 issues):${NC}"
grep "^HIGH|" "$REPORT" | head -20 | while IFS='|' read -r sev file line issue; do
rel_file="${file#$TOOLKIT_PATH/}" # Get unique files with HIGH issues
printf " ${YELLOW}${NC} %s:%s - %s\n" "$rel_file" "$line" "$issue" high_files=$(grep "^HIGH|" "$REPORT" | cut -d'|' -f2 | sed "s|$TOOLKIT_PATH/||" | sort -u)
shown=0
echo "$high_files" | while read -r rel_file; do
[ "$shown" -ge 15 ] && break
# Count issues in this file
file_high_count=$(grep "^HIGH|.*${rel_file}" "$REPORT" 2>/dev/null | wc -l)
# Show first 3 issues from this file
echo -e " ${YELLOW}${rel_file}${NC} ${DIM}($file_high_count issues)${NC}"
grep "^HIGH|.*${rel_file}" "$REPORT" | head -3 | while IFS='|' read -r sev file line issue; do
printf " %s ${DIM}- %s${NC}\n" "$line" "$issue"
shown=$((shown + 1))
done done
if [ "$high" -gt 20 ]; then [ "$file_high_count" -gt 3 ] && echo -e " ${DIM}... +$((file_high_count - 3)) more in this file${NC}"
echo -e " ${DIM}... +$((high - 20)) more (run: grep '^HIGH' $REPORT)${NC}" done
if [ "$high" -gt 15 ]; then
echo -e " ${DIM}... +$((high - 15)) more issues (run: grep '^HIGH' $REPORT)${NC}"
fi fi
echo "" echo ""
fi fi
# MEDIUM/LOW: Just show file counts # QUICK WINS: Show patterns that appear frequently (easy to fix multiple at once)
if [ "$med" -gt 0 ] || [ "$low" -gt 0 ]; then
echo -e "${BOLD}MEDIUM ($med) & LOW ($low) ISSUES BY FILE:${NC}"
{
grep "^MEDIUM|" "$REPORT" 2>/dev/null | cut -d'|' -f2
grep "^LOW|" "$REPORT" 2>/dev/null | cut -d'|' -f2
} | sed "s|$TOOLKIT_PATH/||" | sort | uniq -c | sort -rn | head -15 | while read count file; do
printf " ${DIM}%3d issues${NC} - %s\n" "$count" "$file"
done
echo -e " ${DIM}(Run: grep '^MEDIUM\\|^LOW' $REPORT | less)${NC}"
echo ""
fi
# Top issue categories (compact view)
if [ "$total" -gt 0 ]; then if [ "$total" -gt 0 ]; then
echo -e "${BOLD}TOP 10 ISSUE CATEGORIES:${NC}" echo -e "${BOLD}QUICK WINS (patterns appearing 10+ times):${NC}"
declare -A cat_counts quick_wins_found=0
for tag in SQL-INJ CMD-INJ PANEL-CALL FILE-OP SECRET-LEAK RACE SOURCE RETURN NULL DEP TEMP SUBSHELL PIPE WORDSPLIT ARITH TEST REDIR TRAP ARRAY HEREDOC IF-MASK NUMCMP BG-JOB LOCALE PROC-SUB PRINTF REGEX BASHISM ESCAPE SLEEP-RACE IFS SUBSHELL-VAR TRAP-RACE PERF-LOOP PERF-CACHE PERF-READ RECURSION FD-LEAK ZOMBIE DISK-SPACE NET-TIMEOUT LOG-ROTATE CPU-LOOP HARDCODED-PATH MISSING-LIB USERDATA-ACCESS API-CHECK NO-CASE DB-PATTERN NO-USER-MGR NO-STANDALONE; do
# Check for common patterns
for tag in SOURCE TEMP HARDCODED-PATH WORDSPLIT NULL PIPE SUBSHELL; do
count=$(grep -c "\[$tag\]" "$REPORT" 2>/dev/null || echo 0) count=$(grep -c "\[$tag\]" "$REPORT" 2>/dev/null || echo 0)
# Sanitize: ensure it's a single integer
count=$(echo "$count" | head -1 | tr -d '\n\r' | grep -o '^[0-9]*$' || echo 0) count=$(echo "$count" | head -1 | tr -d '\n\r' | grep -o '^[0-9]*$' || echo 0)
[ "$count" -gt 0 ] 2>/dev/null && cat_counts[$tag]=$count
if [ "$count" -ge 10 ] 2>/dev/null; then
quick_wins_found=1
case "$tag" in
SOURCE) desc="Add existence checks before sourcing files" ;;
TEMP) desc="Use mktemp instead of hardcoded /tmp paths" ;;
HARDCODED-PATH) desc="Replace hardcoded paths with detection" ;;
WORDSPLIT) desc="Quote variable expansions" ;;
NULL) desc="Add empty checks before using variables" ;;
PIPE) desc="Avoid useless pipes (use grep -q directly)" ;;
SUBSHELL) desc="Export variables to subshells" ;;
*) desc="Fix $tag pattern" ;;
esac
printf " ${CYAN}%3d ×${NC} %-20s ${DIM}%s${NC}\n" "$count" "$tag" "$desc"
fi
done done
if [ ${#cat_counts[@]} -gt 0 ]; then [ "$quick_wins_found" -eq 0 ] && echo -e " ${DIM}No high-frequency patterns found${NC}"
for tag in "${!cat_counts[@]}"; do echo ""
echo "${cat_counts[$tag]} $tag" fi
done | sort -rn | head -10 | while read count tag; do
printf " %-18s %3d issues\n" "$tag" "$count" # MEDIUM/LOW summary (compact)
done if [ "$med" -gt 0 ] || [ "$low" -gt 0 ]; then
fi echo -e "${DIM}MEDIUM: $med issues | LOW: $low issues | Full details: grep '^MEDIUM\\|^LOW' $REPORT${NC}"
echo "" echo ""
fi fi