diff --git a/swarmforge/scripts/ensure_handoff_daemon.sh b/swarmforge/scripts/ensure_handoff_daemon.sh new file mode 100755 index 0000000..3c743df --- /dev/null +++ b/swarmforge/scripts/ensure_handoff_daemon.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# Ensure the SwarmForge handoff daemon is running for this project. +# +# The daemon delivers queued handoffs from each role's outbox to recipient +# inboxes and wakes the recipients. If it is not running, handoffs sit +# undelivered. This script is idempotent: it starts the daemon only when no +# live pid exists and no stop file is present. +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +if ! command -v bb >/dev/null 2>&1; then + echo "ensure_handoff_daemon: bb not found; cannot ensure handoff daemon" >&2 + exit 0 +fi + +common="$(git rev-parse --git-common-dir 2>/dev/null || true)" +if [ -z "$common" ]; then + exit 0 +fi +common_abs="$(cd "$common" 2>/dev/null && pwd || true)" +if [ -z "$common_abs" ]; then + exit 0 +fi + +project_root="$(dirname "$common_abs")" +if [ ! -f "$project_root/.swarmforge/roles.tsv" ]; then + exit 0 +fi + +daemon_dir="$project_root/.swarmforge/daemon" +pid_file="$daemon_dir/handoffd.pid" +stop_file="$daemon_dir/stop" + +if [ -f "$stop_file" ]; then + exit 0 +fi + +if [ -f "$pid_file" ]; then + pid="$(tr -dc '0-9' < "$pid_file" 2>/dev/null || true)" + if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then + exit 0 + fi +fi + +mkdir -p "$daemon_dir" +nohup bb "$SCRIPT_DIR/handoffd.bb" "$project_root" >/dev/null 2>&1 & +disown 2>/dev/null || true +echo "ensure_handoff_daemon: started handoff daemon for $project_root" diff --git a/swarmforge/scripts/ready_for_next.sh b/swarmforge/scripts/ready_for_next.sh index 5f9cdfd..eab638a 100755 --- a/swarmforge/scripts/ready_for_next.sh +++ b/swarmforge/scripts/ready_for_next.sh @@ -2,4 +2,9 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +# Recovery: if the handoff daemon died, wake-ups never arrive and queued +# handoffs sit in outboxes. Ensure it is alive before checking for work. +"$SCRIPT_DIR/ensure_handoff_daemon.sh" || true + exec bb "$SCRIPT_DIR/ready_for_next.bb" "$@" diff --git a/swarmforge/scripts/swarm_handoff.sh b/swarmforge/scripts/swarm_handoff.sh index 323b3c7..fdd9734 100755 --- a/swarmforge/scripts/swarm_handoff.sh +++ b/swarmforge/scripts/swarm_handoff.sh @@ -2,4 +2,9 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +# Handoffs sit undelivered if the daemon is not running, so make sure it is +# alive before queueing. Starting it here is idempotent and self-healing. +"$SCRIPT_DIR/ensure_handoff_daemon.sh" || true + exec bb "$SCRIPT_DIR/swarm_handoff.bb" "$@"