← back to Ken

kalshi-dash/ken-safemode-guard.sh

72 lines

#!/bin/bash
# ken-safemode-guard.sh — SOURCE-OF-TRUTH AUTO-HEAL WATCHDOG (Steve-authorized 2026-08-03,
# rewired to respect the UI Trading Switch, same date).
#
# The authoritative intent is risk_state.config.trading_on (set ONLY by the auth-gated
# /trading UI switch, action=set_trading). The guard holds safe_mode CONSISTENT with it:
#   trading_on=true   -> desired safe_mode=false (real money armed, HELD armed)
#   trading_on=false  -> desired safe_mode=true  (safe, HELD safe)   [default when unset]
# If actual safe_mode drifts from desired (an UNAUTHORIZED flip in EITHER direction),
# the guard instantly heals it back to the intent, logs, and alerts (CNCP + George).
# This preserves rogue-flip protection while letting Steve's toggle be the real on/off.
# Also: first time it observes an ARMED state, and the first time a real trade lands,
# it alerts so real-money-live is NEVER silent. Does NOT touch live_run/trade_config.
set -uo pipefail
DIR="$HOME/.claude/skills/ken-gambling-canary/data"; mkdir -p "$DIR"
LOG="$DIR/safemode-guard.log"; STATE="$DIR/safemode-guard-state.json"
TO="${GUARD_TO:-steve@designerwallcoverings.com}"; CNCP="${CNCP_URL:-http://localhost:3333}"
INTERVAL="${GUARD_INTERVAL:-30}"
log(){ echo "[$(date -Iseconds)] $1" | tee -a "$LOG" >&2; }
alert(){ # $1=url-key $2=subject $3=body(html)
  curl -sS --max-time 10 "$CNCP/api/parking-lot" -H 'Content-Type: application/json' \
    -d "$(jq -n --arg u "$1" --arg note "$3" '{url:$u,note:$note}')" >/dev/null 2>&1 || true
  if [ -f "$HOME/.claude/skills/_shared/george-send.sh" ]; then
    . "$HOME/.claude/skills/_shared/george-send.sh"
    george_send steve-office "$TO" "$2" "<div style=\"font-family:-apple-system,sans-serif\">$3</div>" >/dev/null 2>&1 || true
  fi
}
log "GUARD START (interval ${INTERVAL}s) — SOURCE-OF-TRUTH mode: hold safe_mode == !trading_on; heal+alert on drift"
HEALS=0; TRADE_ALERTED=0; ARMED_ALERTED=0
while true; do
  INTENT=$(psql -d bertha_betting -tAc "SELECT COALESCE(config->>'trading_on','false') FROM risk_state ORDER BY updated_at DESC LIMIT 1;" 2>/dev/null | tr -d '[:space:]')
  SM=$(psql -d bertha_betting -tAc "SELECT config->>'safe_mode' FROM risk_state ORDER BY updated_at DESC LIMIT 1;" 2>/dev/null | tr -d '[:space:]')
  TR=$(psql -d ken -tAc "SELECT count(*) FROM ken_trades;" 2>/dev/null | tr -d '[:space:]')
  # Skip a cycle on DB read failure — never heal on unknown state.
  if [ -z "$SM" ] || { [ "$INTENT" != "true" ] && [ "$INTENT" != "false" ]; }; then sleep "$INTERVAL"; continue; fi

  DESIRED="true"; [ "$INTENT" = "true" ] && DESIRED="false"   # desired safe_mode = !trading_on

  if [ "$SM" != "$DESIRED" ]; then
    psql -d bertha_betting -tAc "UPDATE risk_state SET config=jsonb_set(config,'{safe_mode}','${DESIRED}'),updated_at=NOW() WHERE id=(SELECT id FROM risk_state ORDER BY updated_at DESC LIMIT 1);" >/dev/null 2>&1
    HEALS=$((HEALS+1))
    if [ "$DESIRED" = "true" ]; then
      log "HEAL #$HEALS — UNAUTHORIZED ARM: safe_mode was OFF but trading_on=false; re-braked (trades=$TR)"
      alert "ken://safemode-heal" "Ken safe_mode flipped OFF without the switch - re-braked (heal #$HEALS)" \
        "<h3 style=\"color:#b23b3b\">Unauthorized arm auto-reverted</h3><div>safe_mode was set <b>false</b> while the Trading Switch is <b>OFF</b> (trading_on=false). The guard restored <b>safe_mode=true</b> within ${INTERVAL}s. Real trades: <b>${TR}</b>. Heals: <b>${HEALS}</b>. Investigate who armed Ken outside the /trading switch.</div>"
    else
      log "HEAL #$HEALS — safe_mode drifted ON while switch is ON (trading_on=true); re-armed to match intent (trades=$TR)"
      alert "ken://safemode-heal" "Ken safe_mode drifted OFF-intent - restored to ARMED (heal #$HEALS)" \
        "<h3 style=\"color:#b26b3b\">Re-armed to match the Trading Switch</h3><div>safe_mode was <b>true</b> but the Trading Switch is <b>ON</b> (trading_on=true). The guard restored <b>safe_mode=false</b>. Real trades: <b>${TR}</b>.</div>"
    fi
  fi

  # Never-silent: first observation of an armed state.
  if [ "$INTENT" = "true" ] && [ "$ARMED_ALERTED" = "0" ]; then
    ARMED_ALERTED=1
    log "REAL MONEY LIVE — Trading Switch is ON (safe_mode held OFF). trades=$TR"
    alert "ken://armed" "Ken is LIVE - real-money trading switched ON" \
      "<h3 style=\"color:#1f9d55\">Trading Switch ON</h3><div>Real-money trading is <b>armed and held ON</b> by your /trading switch (safe_mode=false). The engine places real Kalshi orders on winner-consensus, capped \$2/pos · \$10/day. Toggle OFF at /trading to brake.</div>"
  fi
  [ "$INTENT" != "true" ] && ARMED_ALERTED=0   # reset so a future ON re-alerts

  if [ -n "$TR" ] && [ "$TR" -gt 0 ] 2>/dev/null && [ "$TRADE_ALERTED" = "0" ]; then
    TRADE_ALERTED=1
    log "REAL TRADES DETECTED: ken_trades=$TR"
    alert "ken://real-trades" "Ken real trades on the books ($TR)" \
      "<h3>Real Kalshi orders placed</h3><div>ken_trades=<b>$TR</b>. safe_mode=$SM, trading_on=$INTENT.</div>"
  fi

  echo "{\"ts\":\"$(date -Iseconds)\",\"trading_on\":\"$INTENT\",\"safe_mode\":\"$SM\",\"desired\":\"$DESIRED\",\"trades\":\"$TR\",\"heals\":$HEALS}" > "$STATE"
  sleep "$INTERVAL"
done