← back to Professional Directory

scripts/doctor-nightly-v5-check.sh

112 lines

#!/bin/bash
# Doctor v5 nightly run check — runs at 09:00 PT daily, audits last night's mockup gen.
# Wired to com.steve.doctor-nightly-v5-check.
set -uo pipefail

PD="${PD:-/Users/macstudio3/Projects/professional-directory}"
cd "$PD" || exit 1

TODAY=$(date +%Y-%m-%d)
LOG_TXT="$PD/logs/doctor-nightly-v5-check.log"
mkdir -p "$PD/logs"

ts_local() { date +"%H:%M:%S"; }
log() { echo "[v5-check $(ts_local)] $*" | tee -a "$LOG_TXT"; }

# ----- Last nightly run logs -----
NIGHTLY_OUT="$PD/logs/mockups-nightly.out.log"
NIGHTLY_ERR="$PD/logs/mockups-nightly.err.log"

OUT_AGE_MIN=-1
ERR_LINES=0
ERR_TAIL=""
if [ -f "$NIGHTLY_OUT" ]; then
  OUT_AGE_MIN=$(( ( $(date +%s) - $(stat -f %m "$NIGHTLY_OUT") ) / 60 ))
fi
if [ -f "$NIGHTLY_ERR" ]; then
  ERR_LINES=$(wc -l < "$NIGHTLY_ERR" | tr -d ' ')
  ERR_TAIL=$(tail -20 "$NIGHTLY_ERR" 2>/dev/null)
fi

# ----- Mockup files written between 01:00 and 09:00 today -----
MOCK_DIR="$PD/data/mockups"
WROTE_TODAY=$(find "$MOCK_DIR" -maxdepth 1 -name '*.html' -newermt "${TODAY} 01:00" ! -newermt "${TODAY} 09:00" 2>/dev/null | wc -l | tr -d ' ')
TAINTED_TODAY=$(find "$MOCK_DIR" -maxdepth 1 -name '*tainted*' -newermt "${TODAY} 01:00" ! -newermt "${TODAY} 09:00" 2>/dev/null | wc -l | tr -d ' ')

# ----- Run the audit on today's files only -----
AUDIT_REPORT=""
if [ "$WROTE_TODAY" -gt 0 ]; then
  AUDIT_REPORT=$(node -e "
const fs = require('fs');
const path = require('path');
const dir = '$MOCK_DIR';
const today = '$TODAY';
const start = Date.parse(today + 'T01:00:00') / 1000;
const end = Date.parse(today + 'T09:00:00') / 1000;
const all = fs.readdirSync(dir).filter(f => f.endsWith('.html'))
  .map(f => ({ f, m: fs.statSync(path.join(dir,f)).mtimeMs / 1000 }))
  .filter(x => x.m >= start && x.m <= end);
const tainted = all.filter(x => x.f.includes('tainted'));
const clean = all.filter(x => !x.f.includes('tainted'));
console.log(JSON.stringify({ total: all.length, clean: clean.length, tainted: tainted.length, taintRate: all.length ? (tainted.length / all.length * 100).toFixed(1) + '%' : 'n/a' }));
" 2>&1)
fi

# ----- snapshot-mockups.js run? Look for its output marker -----
SNAPSHOT_RAN="unknown"
if [ -f "$NIGHTLY_OUT" ]; then
  if grep -q "snapshot-mockups" "$NIGHTLY_OUT" 2>/dev/null || tail -50 "$NIGHTLY_OUT" 2>/dev/null | grep -qi "snapshot"; then
    SNAPSHOT_RAN="yes"
  else
    SNAPSHOT_RAN="not-found-in-log"
  fi
fi

# ----- MS1 health right now -----
MS1_STATUS=$(curl -s -o /dev/null -w '%{http_code}' --max-time 5 http://192.168.1.133:11434/api/tags || echo "000")
QWEN_LOADED=$(curl -s --max-time 5 http://192.168.1.133:11434/api/tags 2>/dev/null | python3 -c 'import json,sys; d=json.load(sys.stdin); print("yes" if "qwen3:32b" in [m["name"] for m in d.get("models",[])] else "no")' 2>/dev/null || echo "unknown")

# ----- Body -----
BODY="Doctor v5 nightly check — $TODAY

Run logs:
- mockups-nightly.out.log mtime: $OUT_AGE_MIN min ago
- mockups-nightly.err.log: $ERR_LINES total lines

Files generated 01:00-09:00 today: $WROTE_TODAY
- Tainted: $TAINTED_TODAY
- Audit: ${AUDIT_REPORT:-no files to audit}

snapshot-mockups.js ran: $SNAPSHOT_RAN
MS1 ollama right now: $MS1_STATUS (qwen3:32b loaded: $QWEN_LOADED)

Last 20 lines of err log:
$ERR_TAIL

Auto-generated by com.steve.doctor-nightly-v5-check"

log "files=$WROTE_TODAY tainted=$TAINTED_TODAY out_age=${OUT_AGE_MIN}min err_lines=$ERR_LINES MS1=$MS1_STATUS qwen=$QWEN_LOADED"

# ----- Email Steve via George -----
python3 -c '
import json, urllib.request, sys, os
body = sys.stdin.read()
payload = json.dumps({
  "to": "steveabramsdesigns@gmail.com",
  "subject": "Doctor v5 nightly check — " + os.environ.get("TODAY", ""),
  "body": body
}).encode()
req = urllib.request.Request(
  "http://localhost:9850/api/send?account=info",
  data=payload,
  headers={"Content-Type": "application/json"}
)
try:
  r = urllib.request.urlopen(req, timeout=10)
  print("george:", r.status)
except Exception as e:
  print("george-err:", e, file=sys.stderr)
' TODAY="$TODAY" <<<"$BODY" >> "$LOG_TXT" 2>&1

exit 0