feat(WARDEN-WP-0020): T4 scheduling tick + T5 SCOPE — worker complete

T4 — scripts/worker-tick.sh: scheduled tick for the conservative worker. flock concurrency
guard; short-lived kubectl port-forward to llm-connect (or LLM_CONNECT_URL, or rule-brain
fallback). Ships disabled; header documents the cron entry. Schedules the conservative tier
only (never auto-send).

T5 — SCOPE records `warden worker` as an implemented capability: conservative triage
default, full-auto opt-in, llm-connect brain, the four guardrails, schedulable tick.

WARDEN-WP-0020 finished: the autonomous coordination worker — T1 scaffold, T2 llm-connect
brain, T3 guarded executor, conservative tier (Option A), T4 scheduling, T5 docs. 245 tests,
lint clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-30 00:41:04 +02:00
parent d0261ebb52
commit 22c5bd1bbb
3 changed files with 61 additions and 7 deletions

42
scripts/worker-tick.sh Executable file
View File

@@ -0,0 +1,42 @@
#!/usr/bin/env bash
# Scheduled tick for the ops-warden conservative worker (WARDEN-WP-0020 T4).
#
# Triages NEW State Hub coordination requests into $WARDEN_STATE_DIR/worker-digest.md
# (drafted replies you approve) and posts ONE progress note. Conservative tier: it NEVER
# sends to other agents and never marks messages read. Safe to schedule.
#
# DISABLED by default. Enable with a cron entry (every 15 min), e.g.:
# */15 * * * * /home/worsch/ops-warden/scripts/worker-tick.sh >> ~/.local/state/warden/worker-tick.log 2>&1
# Brain: WORKER_BRAIN=llm (default; needs llm-connect) or rule (offline, deterministic).
# To use llm without an in-cluster run, set LLM_CONNECT_URL; otherwise the tick opens a
# short-lived kubectl port-forward to activity-core/llm-connect and tears it down.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
STATE="${WARDEN_STATE_DIR:-$HOME/.local/state/warden}"
mkdir -p "$STATE"
# Concurrency guard — never let two ticks overlap.
exec 9>"$STATE/worker-tick.lock"
flock -n 9 || { echo "$(date -Is) tick: another run holds the lock; skip"; exit 0; }
BRAIN="${WORKER_BRAIN:-llm}"
LLM_URL="${LLM_CONNECT_URL:-}"
PF_PID=""
cleanup() { [[ -n "$PF_PID" ]] && kill "$PF_PID" 2>/dev/null || true; }
trap cleanup EXIT
if [[ "$BRAIN" == "llm" && -z "$LLM_URL" ]]; then
if command -v kubectl >/dev/null 2>&1; then
kubectl -n activity-core port-forward deploy/llm-connect 18080:8080 >/dev/null 2>&1 &
PF_PID=$!
sleep 4
LLM_URL="http://127.0.0.1:18080"
else
echo "$(date -Is) tick: kubectl unavailable; falling back to rule brain"
BRAIN="rule"
fi
fi
echo "$(date -Is) tick: brain=$BRAIN"
LLM_CONNECT_URL="$LLM_URL" uv run --directory "$ROOT" warden worker run --execute --brain "$BRAIN"