Просмотр исходного кода

feat(mac-ops): Adopt TERMINAL-DESIGN panel UI (v2.8.0)

- New skills/mac-ops/scripts/_lib/panel.sh wraps term.sh and collects
  findings transparently via log_pass/fail/warn/info overrides
- health-audit.sh and quickrun.sh emit state-grouped tree panels with
  brand glyph, summary line, and health footer indicator
- Refactored term.sh to drop declare -A (bash 4-only) in favour of a
  flat case lookup — panels now work on stock macOS bash 3.2
- Added [mac-ops]="🩺|[M]" brand glyph
- JSON_MODE never renders a panel (NDJSON contract preserved)
- 115 mac-ops tests still pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0xDarkMatter 4 недель назад
Родитель
Сommit
eaad08ca8b

+ 1 - 1
.claude-plugin/plugin.json

@@ -1,6 +1,6 @@
 {
   "name": "claude-mods",
-  "version": "2.7.8",
+  "version": "2.8.0",
   "description": "Custom commands, skills, and agents for Claude Code - session continuity, 23 expert agents, 78 skills, 2 commands, 6 rules, 4 hooks, 13 output styles, modern CLI tools",
   "author": "0xDarkMatter",
   "repository": "https://github.com/0xDarkMatter/claude-mods",

+ 3 - 0
README.md

@@ -22,6 +22,9 @@ From Python async patterns to Rust ownership models, from AWS Fargate deployment
 
 ## Recent Updates
 
+**v2.8.0** (May 2026)
+- 🎨 **`mac-ops` panel UI** - Adopted the TERMINAL-DESIGN panel system (same visual language as `windows-ops`). `health-audit.sh` and `quickrun.sh` now render a state-grouped tree panel with rounded corners, brand glyph (🩺 / `[M]`), 21-checks summary line, failing/warning/pass/info sections, and a footer health indicator that maps WARN→warning (orange) and FAIL→critical (red). New `skills/mac-ops/scripts/_lib/panel.sh` wraps `skills/_lib/term.sh` and transparently collects findings via `log_pass/fail/warn/info` overrides — sub-scripts emit a plain summary, orchestrators emit the panel. Also refactored `term.sh` to drop bash 4-only associative arrays (`declare -A`) in favour of a flat case lookup, so the panel system now works on stock macOS bash 3.2 without requiring `brew install bash`. ASCII fallback when not a UTF locale; honors `NO_PANEL=1`, `FORCE_PANEL=1`, `JSON_MODE=1` (JSON output never renders a panel — the NDJSON contract is sacred). 115 mac-ops tests still pass.
+
 **v2.7.8** (May 2026)
 - 🩺 **`mac-ops` --days parse fix** - Dogfooded `quickrun.sh` end-to-end and caught a real bug: health-audit's `--days N` parser used `for arg in "$@"` with `shift`, which doesn't update the loop variable, so `DAYS` ended up containing the literal string `--days` instead of the numeric value. Section labels then printed `IO errors via log (--days days)` instead of `(1 days)`. Refactored to a `while [[ $# -gt 0 ]]` loop that correctly handles the two-token form. The two-pass approach (parse-then-restore-via `set --`) keeps downstream `parse_common_flags` working unchanged.
 

+ 34 - 42
skills/_lib/term.sh

@@ -49,42 +49,8 @@ TERM_ICON_WARN=""
 TERM_ICON_HINT=""
 
 # ─── Registries (Unicode|ASCII) ───────────────────────────────────────────
-declare -A TERM_BRAND=(
-  [fleet]="⚡|[F]"
-  [forge]="🔨|[B]"
-  [psql]="🐘|[P]"
-  [watch]="📡|[M]"
-  [deploy]="🚀|[D]"
-  [git]="🌿|[G]"
-  [windows-ops]="🩺|[H]"
-)
-
-declare -A TERM_HEALTH_GLYPH=(
-  [healthy]="•|(+)"
-  [pending]="•|(.)"
-  [warning]="•|(!)"
-  [critical]="•|(!!)"
-  [busted]="⬤|(X)"
-  [unknown]="•|(?)"
-)
-
-declare -A TERM_DIAGRAM_ICON=(
-  [user]="👤|(U)"
-  [web]="🌐|(W)"
-  [mobile]="📱|(M)"
-  [auth]="🔐|(A)"
-  [database]="🗄|(D)"
-  [cache]="⚡|(C)"
-  [queue]="📨|(Q)"
-  [storage]="📦|(P)"
-  [service]="⚙|*"
-  [api]="🔌|(I)"
-  [search]="🔍|(S)"
-  [timer]="⏱|(T)"
-  [build]="🔨|(B)"
-  [hook]="🪝|(H)"
-  [log]="📄|(F)"
-)
+# Implemented as case statements in __term_lookup below (bash 3.2 compatible —
+# stock macOS bash lacks associative arrays).
 
 # Header indicator glyph (branch/⎇)
 TERM_GLYPH_BRANCH=""
@@ -205,12 +171,38 @@ term_color() {
 # term_emoji <registry_name> <key>  — returns Unicode glyph or ASCII fallback.
 # Internal helper; pass "BRAND", "HEALTH_GLYPH", "DIAGRAM_ICON".
 __term_lookup() {
-  local map=$1 key=$2 entry uni ascii
-  case "$map" in
-    BRAND)         entry="${TERM_BRAND[$key]:-}" ;;
-    HEALTH_GLYPH)  entry="${TERM_HEALTH_GLYPH[$key]:-}" ;;
-    DIAGRAM_ICON)  entry="${TERM_DIAGRAM_ICON[$key]:-}" ;;
-    *)             entry="" ;;
+  local map=$1 key=$2 entry="" uni ascii
+  case "${map}::${key}" in
+    BRAND::fleet)               entry="⚡|[F]" ;;
+    BRAND::forge)               entry="🔨|[B]" ;;
+    BRAND::psql)                entry="🐘|[P]" ;;
+    BRAND::watch)               entry="📡|[M]" ;;
+    BRAND::deploy)              entry="🚀|[D]" ;;
+    BRAND::git)                 entry="🌿|[G]" ;;
+    BRAND::windows-ops)         entry="🩺|[H]" ;;
+    BRAND::mac-ops)             entry="🩺|[M]" ;;
+    HEALTH_GLYPH::healthy)      entry="•|(+)" ;;
+    HEALTH_GLYPH::pending)      entry="•|(.)" ;;
+    HEALTH_GLYPH::warning)      entry="•|(!)" ;;
+    HEALTH_GLYPH::critical)     entry="•|(!!)" ;;
+    HEALTH_GLYPH::alarm)        entry="•|(!!)" ;;
+    HEALTH_GLYPH::busted)       entry="⬤|(X)" ;;
+    HEALTH_GLYPH::unknown)      entry="•|(?)" ;;
+    DIAGRAM_ICON::user)         entry="👤|(U)" ;;
+    DIAGRAM_ICON::web)          entry="🌐|(W)" ;;
+    DIAGRAM_ICON::mobile)       entry="📱|(M)" ;;
+    DIAGRAM_ICON::auth)         entry="🔐|(A)" ;;
+    DIAGRAM_ICON::database)     entry="🗄|(D)" ;;
+    DIAGRAM_ICON::cache)        entry="⚡|(C)" ;;
+    DIAGRAM_ICON::queue)        entry="📨|(Q)" ;;
+    DIAGRAM_ICON::storage)      entry="📦|(P)" ;;
+    DIAGRAM_ICON::service)      entry="⚙|*" ;;
+    DIAGRAM_ICON::api)          entry="🔌|(I)" ;;
+    DIAGRAM_ICON::search)       entry="🔍|(S)" ;;
+    DIAGRAM_ICON::timer)        entry="⏱|(T)" ;;
+    DIAGRAM_ICON::build)        entry="🔨|(B)" ;;
+    DIAGRAM_ICON::hook)         entry="🪝|(H)" ;;
+    DIAGRAM_ICON::log)          entry="📄|(F)" ;;
   esac
   [[ -z "$entry" ]] && { printf '%s' "?"; return; }
   uni="${entry%|*}"

+ 214 - 0
skills/mac-ops/scripts/_lib/panel.sh

@@ -0,0 +1,214 @@
+# mac-ops :: _lib/panel.sh
+# Panel-rendering helper that wraps the shared skills/_lib/term.sh API.
+# Source AFTER common.sh. Provides:
+#
+#   panel_init           — detect TTY, source term.sh
+#   panel_findings_open  — start collecting findings (called once at top)
+#   panel_render <name> <indicator>
+#                        — emit the state-grouped panel using collected
+#                          findings + log_pass/log_fail/log_warn counts
+#
+# Collection happens transparently: the existing log_pass / log_fail /
+# log_warn / log_info from common.sh ALSO push (state, section, label,
+# detail) tuples into MAC_PANEL_FINDINGS when panel mode is on.
+
+# Locate the project-level term.sh (4 levels up from script dir, then _lib)
+__MACOPS_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+__MACOPS_TERM_LIB="$(cd "$__MACOPS_SCRIPT_DIR/../../../_lib" 2>/dev/null && pwd)/term.sh"
+
+# Panel mode default: auto. Force on with FORCE_PANEL=1, off with NO_PANEL=1.
+PANEL_MODE="${PANEL_MODE:-auto}"
+MAC_PANEL_ENABLED=0
+MAC_PANEL_FINDINGS=()    # each entry: "state|section|label|detail"
+
+panel_init() {
+    # If JSON output requested, never enable panels — JSON is the contract
+    if [[ "${JSON_MODE:-0}" -eq 1 ]]; then return 0; fi
+
+    # NO_PANEL forces off; FORCE_PANEL forces on; otherwise TTY-detect
+    if [[ "${NO_PANEL:-0}" -eq 1 ]]; then return 0; fi
+
+    # Source term.sh if available.
+    if [[ -f "$__MACOPS_TERM_LIB" ]]; then
+        # shellcheck source=/dev/null
+        . "$__MACOPS_TERM_LIB"
+        term_init
+    else
+        return 0
+    fi
+
+    # Use panel mode if stdout is a TTY or forced
+    if [[ "${FORCE_PANEL:-0}" -eq 1 ]] || [[ "$TERM_TTY" -eq 1 ]]; then
+        MAC_PANEL_ENABLED=1
+    fi
+}
+
+panel_enabled() { [[ "$MAC_PANEL_ENABLED" -eq 1 ]]; }
+
+# Override common.sh log_* functions to also collect findings.
+# (These are sourced AFTER common.sh and will override its versions.)
+__MAC_ORIGINAL_PASS=$(declare -f log_pass || true)
+__MAC_ORIGINAL_FAIL=$(declare -f log_fail || true)
+__MAC_ORIGINAL_WARN=$(declare -f log_warn || true)
+__MAC_ORIGINAL_INFO=$(declare -f log_info || true)
+
+# Wrap each log function so it both updates counters AND collects findings.
+# When panel mode is on, ALSO suppress the inline echo — we'll render at end.
+
+log_pass() {
+    PASS_COUNT=$((PASS_COUNT + 1))
+    MAC_PANEL_FINDINGS+=("pass|${CURRENT_SECTION}|$1|${2:-}")
+    if [[ "$MAC_PANEL_ENABLED" -eq 1 ]]; then return 0; fi
+    if [[ "${JSON_MODE:-0}" -eq 1 ]]; then
+        printf '{"type":"check","section":"%s","label":"%s","status":"pass","detail":"%s"}\n' \
+            "$(_json_escape "$CURRENT_SECTION")" "$(_json_escape "$1")" "$(_json_escape "${2:-}")"
+    else
+        echo "[PASS] $1${2:+ :: $2}"
+    fi
+}
+
+log_fail() {
+    FAIL_COUNT=$((FAIL_COUNT + 1))
+    [[ -z "$FIRST_FAIL" ]] && FIRST_FAIL="[$CURRENT_SECTION] $1"
+    MAC_PANEL_FINDINGS+=("fail|${CURRENT_SECTION}|$1|${2:-}")
+    if [[ "$MAC_PANEL_ENABLED" -eq 1 ]]; then return 0; fi
+    if [[ "${JSON_MODE:-0}" -eq 1 ]]; then
+        printf '{"type":"check","section":"%s","label":"%s","status":"fail","detail":"%s"}\n' \
+            "$(_json_escape "$CURRENT_SECTION")" "$(_json_escape "$1")" "$(_json_escape "${2:-}")"
+    else
+        echo "[FAIL] $1${2:+ :: $2}"
+    fi
+}
+
+log_warn() {
+    WARN_COUNT=$((WARN_COUNT + 1))
+    MAC_PANEL_FINDINGS+=("warn|${CURRENT_SECTION}|$1|${2:-}")
+    if [[ "$MAC_PANEL_ENABLED" -eq 1 ]]; then return 0; fi
+    if [[ "${JSON_MODE:-0}" -eq 1 ]]; then
+        printf '{"type":"check","section":"%s","label":"%s","status":"warn","detail":"%s"}\n' \
+            "$(_json_escape "$CURRENT_SECTION")" "$(_json_escape "$1")" "$(_json_escape "${2:-}")"
+    else
+        echo "[WARN] $1${2:+ :: $2}"
+    fi
+}
+
+log_info() {
+    INFO_COUNT=$((INFO_COUNT + 1))
+    MAC_PANEL_FINDINGS+=("info|${CURRENT_SECTION}|$1|${2:-}")
+    if [[ "$MAC_PANEL_ENABLED" -eq 1 ]]; then return 0; fi
+    if [[ "${JSON_MODE:-0}" -eq 1 ]]; then
+        printf '{"type":"check","section":"%s","label":"%s","status":"info","detail":"%s"}\n' \
+            "$(_json_escape "$CURRENT_SECTION")" "$(_json_escape "$1")" "$(_json_escape "${2:-}")"
+    else
+        echo "[INFO] $1${2:+ :: $2}"
+    fi
+}
+
+# In panel mode, suppress `note` and `section` so the body stays clean —
+# rendering happens at the end via panel_render.
+__MAC_ORIGINAL_NOTE=$(declare -f note || true)
+__MAC_ORIGINAL_SECTION=$(declare -f section || true)
+
+note() {
+    [[ "$MAC_PANEL_ENABLED" -eq 1 ]] && return 0
+    [[ "${JSON_MODE:-0}" -eq 1 ]] && return 0
+    [[ "${QUIET:-0}" -eq 1 ]] && return 0
+    echo "$@"
+}
+
+section() {
+    CURRENT_SECTION="$1"
+    if [[ "$MAC_PANEL_ENABLED" -eq 1 ]]; then return 0; fi
+    if [[ "${JSON_MODE:-0}" -eq 1 ]]; then
+        printf '{"type":"section","name":"%s"}\n' "$(_json_escape "$1")"
+    else
+        [[ "${QUIET:-0}" -eq 1 ]] || { echo; echo "=== $1 ==="; }
+    fi
+}
+
+# Render the collected findings as a state-grouped tree panel.
+# Args:
+#   $1 = script tag (e.g. "health-audit")
+#   $2 = right indicator (e.g. hostname)
+panel_render() {
+    if [[ "$MAC_PANEL_ENABLED" -ne 1 ]]; then
+        # Not panel mode — just emit the standard summary block
+        emit_summary
+        return
+    fi
+
+    local tag="${1:-mac-ops}"
+    local indicator="${2:-}"
+
+    echo ""
+    term_panel_open mac-ops "mac-ops · $tag" "$indicator"
+    term_panel_vert
+    term_summary_line "$((PASS_COUNT+FAIL_COUNT+WARN_COUNT+INFO_COUNT)) checks · $FAIL_COUNT fail · $WARN_COUNT warn"
+    term_panel_vert
+
+    # Render in order: fail, warn, pass (count only), info (count only)
+    local order=(fail warn)
+    local labels=(failing warning)
+    local i
+    for i in 0 1; do
+        local st="${order[$i]}"
+        local label="${labels[$i]}"
+        local count=0
+        local entries=()
+        local entry
+        for entry in ${MAC_PANEL_FINDINGS[@]+"${MAC_PANEL_FINDINGS[@]}"}; do
+            [[ "${entry%%|*}" == "$st" ]] && { entries+=("$entry"); count=$((count+1)); }
+        done
+        [[ "$count" -eq 0 ]] && continue
+        term_section "$st" "$label" "$count"
+        local n=${#entries[@]}
+        local idx=0
+        for entry in "${entries[@]}"; do
+            local rest="${entry#*|}"
+            local section_name="${rest%%|*}"; rest="${rest#*|}"
+            local lbl="${rest%%|*}"; rest="${rest#*|}"
+            local detail="$rest"
+            local connector
+            if [[ $((idx + 1)) -eq $n ]]; then connector="$TERM_TREE_LAST"; else connector="$TERM_TREE_BRANCH"; fi
+            local sec_short="${section_name%% *}"
+            sec_short="${sec_short%.}"
+            local one_line
+            if [[ -n "$detail" ]]; then
+                one_line="$(printf '%-40s %s' "$lbl" "$detail")"
+            else
+                one_line="$lbl"
+            fi
+            # 100-char hard truncate
+            (( ${#one_line} > 100 )) && one_line="${one_line:0:97}..."
+            printf '%s   %s [%s] %s\n' \
+                "$(term_color dim "$TERM_TREE_VERT")" \
+                "$connector" \
+                "$(term_color dim "$sec_short")" \
+                "$one_line"
+        done
+        term_panel_vert
+        idx=$((idx+1))
+    done
+
+    # Pass + info counts on a single line
+    term_section "ok" "pass" "$PASS_COUNT"
+    if [[ "$INFO_COUNT" -gt 0 ]]; then
+        term_section "info" "info" "$INFO_COUNT"
+    fi
+    term_panel_vert
+
+    # Determine overall health indicator
+    local health_state="healthy"
+    [[ "$WARN_COUNT" -gt 0 ]] && health_state="warning"
+    [[ "$FAIL_COUNT" -gt 0 ]] && health_state="critical"
+    local right_health
+    right_health="$(term_health "$health_state" "$FAIL_COUNT fail · $WARN_COUNT warn")"
+    term_panel_close "" "$right_health"
+    echo ""
+
+    # Also emit a plain SUMMARY line for parseability
+    echo "  PASS: $PASS_COUNT    FAIL: $FAIL_COUNT    WARN: $WARN_COUNT    INFO: $INFO_COUNT"
+    if [[ -n "$FIRST_FAIL" ]]; then
+        echo "  First failure: $FIRST_FAIL"
+    fi
+}

+ 5 - 2
skills/mac-ops/scripts/health-audit.sh

@@ -45,6 +45,8 @@ set -- ${SAVED_ARGS[@]+"${SAVED_ARGS[@]}"}
 source "$(dirname "$0")/_lib/common.sh"
 parse_common_flags "$@"
 maybe_filter_self "$@"
+source "$(dirname "$0")/_lib/panel.sh"
+panel_init
 
 # ----------------------------------------------------------------------------
 section "1. HARDWARE HEALTH"
@@ -243,9 +245,10 @@ note "  Uptime:     $(uptime | awk -F'up ' '{split($2,a,","); print a[1]}')"
 note "  Hostname:   $(scutil --get LocalHostName 2>/dev/null || hostname)"
 
 # ----------------------------------------------------------------------------
-emit_summary
+hostname_short=$(scutil --get LocalHostName 2>/dev/null | head -c 30 || hostname -s | head -c 30)
+panel_render "health-audit" "$hostname_short"
 
-if [[ "$JSON_MODE" -eq 0 ]] && [[ -n "$FIRST_FAIL" ]]; then
+if [[ "$JSON_MODE" -eq 0 ]] && [[ "$MAC_PANEL_ENABLED" -eq 0 ]] && [[ -n "$FIRST_FAIL" ]]; then
     case "$FIRST_FAIL" in
         *"PANIC"*|*"panic"*)
             echo "  Next: scripts/panic-triage.sh  # decode the most recent panic + pre-panic timeline" ;;

+ 66 - 2
skills/mac-ops/scripts/quickrun.sh

@@ -40,6 +40,8 @@ done
 source "$(dirname "$0")/_lib/common.sh"
 parse_common_flags "$@"
 maybe_filter_self "$@"
+source "$(dirname "$0")/_lib/panel.sh"
+panel_init
 
 SCRIPTS_DIR="$(dirname "$0")"
 
@@ -60,9 +62,10 @@ run_subscript() {
     note "  $label"
     note "════════════════════════════════════════════════════════════════"
 
-    # Capture sub-script output (suppress its own SUMMARY since we'll do our own)
+    # Capture sub-script output (suppress its own SUMMARY since we'll do our own).
+    # Force NO_PANEL so children emit parseable plain text — we render our own panel.
     local out
-    out=$(bash "$SCRIPTS_DIR/$script" --quiet "$@" 2>&1 || true)
+    out=$(NO_PANEL=1 bash "$SCRIPTS_DIR/$script" --quiet "$@" 2>&1 || true)
 
     # Echo the sub-script's findings (everything before its SUMMARY)
     echo "$out" | sed -n '/^=== /,/^=== SUMMARY ===/p' | sed '/^=== SUMMARY ===/q' | sed '$d'
@@ -109,6 +112,67 @@ if [[ "$JSON_MODE" -eq 1 ]]; then
     printf '{"type":"quickrun_summary","pass":%d,"fail":%d,"warn":%d,"info":%d,"fail_count":%d,"warn_count":%d}\n' \
         "$TOTAL_PASS" "$TOTAL_FAIL" "$TOTAL_WARN" "$TOTAL_INFO" \
         "${#ALL_FAILS[@]}" "${#ALL_WARNS[@]}"
+elif panel_enabled; then
+    hostname_short=$(scutil --get LocalHostName 2>/dev/null | head -c 30 || hostname -s | head -c 30)
+    echo ""
+    term_panel_open mac-ops "mac-ops · quickrun" "$hostname_short"
+    term_panel_vert
+    term_summary_line "$((TOTAL_PASS+TOTAL_FAIL+TOTAL_WARN+TOTAL_INFO)) checks across 5 audits · $TOTAL_FAIL fail · $TOTAL_WARN warn"
+    term_panel_vert
+
+    if [[ "${#ALL_FAILS[@]}" -gt 0 ]]; then
+        term_section "FAILED" "failing" "${#ALL_FAILS[@]}"
+        n=${#ALL_FAILS[@]}
+        i=0
+        for f in "${ALL_FAILS[@]}"; do
+            i=$((i+1))
+            if [[ "$i" -eq "$n" ]]; then connector="$TERM_TREE_LAST"; else connector="$TERM_TREE_BRANCH"; fi
+            line="$f"
+            (( ${#line} > 100 )) && line="${line:0:97}..."
+            printf '%s   %s %s\n' \
+                "$(term_color dim "$TERM_TREE_VERT")" \
+                "$connector" \
+                "$line"
+            [[ "$i" -ge 10 ]] && { printf '%s   %s %s\n' "$(term_color dim "$TERM_TREE_VERT")" "$TERM_TREE_LAST" "$(term_color dim "... +$((n-10)) more")"; break; }
+        done
+        term_panel_vert
+    fi
+
+    if [[ "${#ALL_WARNS[@]}" -gt 0 ]]; then
+        term_section "WARN" "warning" "${#ALL_WARNS[@]}"
+        n=${#ALL_WARNS[@]}
+        i=0
+        for w in "${ALL_WARNS[@]}"; do
+            i=$((i+1))
+            if [[ "$i" -eq "$n" ]]; then connector="$TERM_TREE_LAST"; else connector="$TERM_TREE_BRANCH"; fi
+            line="$w"
+            (( ${#line} > 100 )) && line="${line:0:97}..."
+            printf '%s   %s %s\n' \
+                "$(term_color dim "$TERM_TREE_VERT")" \
+                "$connector" \
+                "$line"
+            [[ "$i" -ge 10 ]] && { printf '%s   %s %s\n' "$(term_color dim "$TERM_TREE_VERT")" "$TERM_TREE_LAST" "$(term_color dim "... +$((n-10)) more")"; break; }
+        done
+        term_panel_vert
+    fi
+
+    term_section "OK" "pass" "$TOTAL_PASS"
+    if [[ "$TOTAL_INFO" -gt 0 ]]; then
+        term_section "info" "info" "$TOTAL_INFO"
+    fi
+    term_panel_vert
+
+    health_state="healthy"
+    [[ "$TOTAL_WARN" -gt 0 ]] && health_state="warning"
+    [[ "$TOTAL_FAIL" -gt 0 ]] && health_state="critical"
+    right_health="$(term_health "$health_state" "$TOTAL_FAIL fail · $TOTAL_WARN warn")"
+    term_panel_close "" "$right_health"
+    echo ""
+
+    if [[ "${#ALL_FAILS[@]}" -eq 0 ]] && [[ "${#ALL_WARNS[@]}" -eq 0 ]]; then
+        echo "  ✓ System looks clean. No FAILs or WARNs across 5 audits."
+    fi
+    echo "  Next: drill any FAIL into its source script (--verbose for detail)"
 else
     echo
     echo "  Aggregate: PASS $TOTAL_PASS    FAIL $TOTAL_FAIL    WARN $TOTAL_WARN    INFO $TOTAL_INFO"