diff --git a/bin/dispatch-deploy b/bin/dispatch-deploy index 313027f0..476bd454 100755 --- a/bin/dispatch-deploy +++ b/bin/dispatch-deploy @@ -151,6 +151,88 @@ write_failure_log() { echo "failure details written to $FAILURE_LOG" >&2 } +spawn_diagnosis_agent() { + local step="$1" + local tag="$2" + local previous_tag="${3:-unknown}" + + # Generate agent ID and session name + local agent_id="agt_$(openssl rand -hex 6)" + local session_name="dispatch_${agent_id}" + local media_dir="/tmp/dispatch-media/${agent_id}" + mkdir -p "$media_dir" + + local port + port=$(resolve_port) + + # Read DISPATCH_BIN_DIR from server .env + local bin_dir="" + local env_file="$SERVER_DIR/.env" + if [[ -f "$env_file" ]]; then + bin_dir=$(grep -E '^DISPATCH_BIN_DIR=' "$env_file" | tail -1 | cut -d= -f2) + fi + if [[ -z "$bin_dir" ]]; then + bin_dir="$SERVER_DIR/bin" + fi + + # Pre-register agent in PostgreSQL so reconcileAgents() picks it up + local db_url="" + if [[ -f "$env_file" ]]; then + db_url=$(grep -E '^DATABASE_URL=' "$env_file" | tail -1 | cut -d= -f2) + fi + if [[ -n "$db_url" ]] && command -v psql &>/dev/null; then + psql "$db_url" -c " + INSERT INTO agents (id, name, type, status, cwd, created_at, updated_at) + VALUES ('$agent_id', 'deploy-diagnosis', 'claude', 'running', '$SERVER_DIR', + NOW(), NOW()) + ON CONFLICT DO NOTHING; + " >/dev/null 2>&1 || true + fi + + # Build failure context from the failure log + local failure_context="" + if [[ -f "$FAILURE_LOG" ]]; then + failure_context=$(cat "$FAILURE_LOG") + fi + + local prompt="The Dispatch deploy pipeline failed and needs diagnosis. + +Failed step: $step +Target tag: $tag +Previous tag: $previous_tag + +Failure details: +${failure_context:-No failure log available.} + +Please diagnose why the deploy/rollback failed: +1. Check server logs: tail -100 $LOG_FILE +2. Check if the server process is running +3. Check launchd service status +4. Inspect the build output and configuration +5. Report findings via dispatch-event + +If you can fix the issue, do so and redeploy with: bin/dispatch-deploy $tag" + + local user_local_bin="$HOME/.local/bin" + local path_prefix="${bin_dir}:${user_local_bin}" + + echo "==> spawning diagnosis agent ($session_name)..." + tmux new-session -d -s "$session_name" -c "$SERVER_DIR" \ + "DISPATCH_AGENT_ID='${agent_id}' \ + DISPATCH_MEDIA_DIR='${media_dir}' \ + DISPATCH_PORT='${port}' \ + PATH='${path_prefix}':\"\$PATH\" \ + claude --append-system-prompt 'You are a Dispatch deploy diagnosis agent. Call dispatch-event at start (working), when blocked (blocked), and before final response (done/idle).' \ + -p '${prompt//\'/\'\\\'\'}'" \ + 2>/dev/null || { + echo "warning: could not spawn diagnosis agent (tmux unavailable?)" >&2 + return + } + + echo " agent ID: $agent_id" + echo " tmux attach: tmux attach -t $session_name" +} + main() { local tag="${1:-}" if [[ -z "$tag" ]]; then @@ -188,6 +270,7 @@ main() { echo "==> building $tag" if ! build_tag "$tag"; then write_failure_log "build" "$tag" "$previous_tag" "" "Build failed for $tag." + spawn_diagnosis_agent "build" "$tag" "$previous_tag" echo "error: build failed" >&2 exit 1 fi @@ -211,6 +294,7 @@ main() { if [[ "$previous_tag" == "$tag" || "$previous_tag" == "unknown" ]]; then write_failure_log "health check" "$tag" "" "" "" + spawn_diagnosis_agent "health check (no rollback available)" "$tag" "unknown" echo "error: cannot roll back (no previous tag available)" >&2 exit 1 fi @@ -226,6 +310,7 @@ main() { write_failure_log "health check" "$tag" "$previous_tag" "failed" \ "Rollback to $previous_tag also failed. Server may be down." + spawn_diagnosis_agent "health check (deploy + rollback failed)" "$tag" "$previous_tag" echo "error: deploy failed and rollback failed — server may be down" >&2 echo " check logs: tail -f $LOG_FILE" >&2 exit 1 diff --git a/bin/dispatch-release b/bin/dispatch-release index a11e55d6..defb272f 100755 --- a/bin/dispatch-release +++ b/bin/dispatch-release @@ -146,8 +146,9 @@ main() { echo "==> release workflow produced tag: $tag" - # dispatch-deploy handles rollback and failure logging internally. - # We don't spawn a diagnosis agent here since Dispatch may be down. + # dispatch-deploy handles rollback, failure logging, and diagnosis agent + # spawning internally. It launches diagnosis agents via tmux+claude CLI + # directly, so it works even when the server is down. if ! "$ROOT_DIR/bin/dispatch-deploy" "$tag"; then echo "error: deploy failed — see $HOME/.dispatch/logs/last-release-failure.log" >&2 exit 1