#!/usr/bin/env bash set -euo pipefail # Watchdog B v2 dispatcher/runner. # Unified entrypoint for timer/service/manual runs. # # Flow: # 1) Call check_openclaw_state.sh to get one of: running | stalled | idle # 2) Emit a human-readable action template for the detected state # 3) Invoke the notification layer (dry-run/manual by default, configurable) # 4) Persist rendered output for local verification / future integrations # # Notification behavior is intentionally conservative: # - running: defaults to a manual/queue-ready owner report path # - stalled/idle: nudge main agent first, then optionally escalate to owner report # - outbound owner messaging reuses the existing owner-reporting-system queue SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" SKILL_DIR="$(cd -- "$SCRIPT_DIR/.." && pwd)" WATCHDOG_B_CONFIG_FILE_DEFAULT="$HOME/.config/openclaw/watchdog-b.env" WATCHDOG_B_CONFIG_FILE="${WATCHDOG_B_CONFIG_FILE:-$WATCHDOG_B_CONFIG_FILE_DEFAULT}" if [[ -f "$WATCHDOG_B_CONFIG_FILE" ]]; then set -a # shellcheck disable=SC1090 . "$WATCHDOG_B_CONFIG_FILE" set +a fi WORKSPACE_DEFAULT="$HOME/.openclaw/workspace" WORKSPACE_DIR="${WATCHDOG_B_WORKSPACE:-$WORKSPACE_DEFAULT}" CHECKER="${WATCHDOG_B_CHECKER:-$SCRIPT_DIR/check_openclaw_state.sh}" ARTIFACT_DIR="${WATCHDOG_B_ARTIFACT_DIR:-$WORKSPACE_DIR/state/watchdog-b}" TIMESTAMP="$(date '+%Y-%m-%dT%H:%M:%S%z')" HOSTNAME_VALUE="$(hostname 2>/dev/null || echo unknown-host)" NOTIFIER="${WATCHDOG_B_NOTIFIER:-$SCRIPT_DIR/notify_watchdog_b.py}" NOTIFY_DRY_RUN="${WATCHDOG_B_NOTIFY_DRY_RUN:-1}" mkdir -p "$ARTIFACT_DIR" if [[ ! -x "$CHECKER" ]]; then echo "watchdog-b error: checker not executable: $CHECKER" >&2 exit 1 fi STATE="$($CHECKER)" emit_running() { cat <&2 exit 2 ;; esac printf '%s\n' "$OUTPUT" NOTIFY_OUTPUT="" if [[ -x "$NOTIFIER" ]]; then NOTIFY_CMD=("$NOTIFIER" --state "$STATE" --timestamp "$TIMESTAMP") if [[ "$NOTIFY_DRY_RUN" == "1" ]]; then NOTIFY_CMD+=(--dry-run) fi if NOTIFY_OUTPUT="$(WATCHDOG_B_ARTIFACT_DIR="$ARTIFACT_DIR" "${NOTIFY_CMD[@]}" 2>&1)"; then printf '%s\n' "$NOTIFY_OUTPUT" else printf '%s\n' "$NOTIFY_OUTPUT" echo "watchdog-b warning: notifier returned non-zero for state=$STATE" >&2 fi else echo "watchdog-b warning: notifier not executable: $NOTIFIER" >&2 fi printf '%s\n' "$OUTPUT" > "$ARTIFACT_DIR/last-output.txt" printf '%s\n' "$NOTIFY_OUTPUT" > "$ARTIFACT_DIR/last-notify-output.txt" printf '%s\t%s\n' "$TIMESTAMP" "$STATE" >> "$ARTIFACT_DIR/history.tsv" printf '%s\n' "$STATE" > "$ARTIFACT_DIR/last-state.txt"