#!/usr/bin/env bash # source: /home/_crossfeed/tooling/agent-stack @ HEAD # dispatch-turn.sh — headless work-turn launcher. # Semaphore-gated (org concurrency cap), FRESH session by default (small # context = quota-friendly; the turn self-bootstraps from the prompt file), # success/fail doorbell to the vertical PMO screen. PMO usage: # screen -dmS work-turn- \ # ~/.coordinate/scripts/dispatch-turn.sh set -uo pipefail SLUG=${1:?slug}; PROMPT=${2:?prompt-file} TOOLING=${TOOLING:-/home/_crossfeed/tooling} SEMI="$TOOLING/agent-stack/semaphore.sh" LOG="$HOME/.coordinate/logs/$SLUG.log" TAG="$USER-$SLUG" WAIT=${WAIT_SECS:-300} [ -f "$PROMPT" ] || { echo "no prompt file: $PROMPT" >&2; exit 1; } semirc=0 bash "$SEMI" try "$TAG" "$WAIT" >/dev/null 2>&1 || semirc=$? if [ "$semirc" = 99 ]; then echo "$(date -Is) semaphore gate unavailable - proceeding UNGATED (install metrics dirs)" >> "$LOG" elif [ "$semirc" != 0 ]; then echo "$(date -Is) semaphore rc=$semirc after ${WAIT}s budget - not launched" >> "$LOG" screen -S "${USER}-PMO" -X stuff "$(printf 'Work turn DEFERRED (concurrency cap) - rerun later: %s.\r' "$SLUG")" || true exit 3 fi GATED=1; [ "$semirc" = 0 ] || GATED=0 cd "$HOME" rc=0 # 2026-08-29 ~06:30: Charles upgraded to MAX plan, all buckets zero. # Quality-first: default back to glm-5.2; TURN_MODEL=glm-4.7-flash for # grind/admin turns when wanted. TURN_MODEL=${TURN_MODEL:-litellm/glm-5.2} env HOME="$HOME" TERM=xterm-256color \ crush run --quiet --model "$TURN_MODEL" "$(cat "$PROMPT")" >> "$LOG" 2>&1 || rc=$? bash "$SEMI" release "$TAG" >/dev/null 2>&1 || true if [ "$rc" = 0 ]; then screen -S "${USER}-PMO" -X stuff "$(printf 'Work turn done OK - read inbox-pmo + logs/%s.\r' "$SLUG")" || true else screen -S "${USER}-PMO" -X stuff "$(printf 'Work turn FAILED (rc=%s) - read logs/%s.\r' "$rc" "$SLUG")" || true fi exit "$rc"