46 lines
1.5 KiB
Bash
46 lines
1.5 KiB
Bash
#!/bin/bash
|
|
# Orphan bead recovery: find in_progress beads whose assignee session has died
|
|
# and unclaim them. BeadReady fires automatically; waiting bots claim via event.
|
|
# Intended to run from cron every 5 minutes.
|
|
set -euo pipefail
|
|
|
|
LOG_PREFIX="[orphan-check $(date '+%Y-%m-%d %H:%M:%S')]"
|
|
log() { echo "$LOG_PREFIX $*"; }
|
|
|
|
# Get live session IDs
|
|
LIVE_SESSIONS=$(9p read anvillm/list 2>/dev/null | awk -F'\t' '{print $1}' || true)
|
|
|
|
# Get all mounts
|
|
MTAB=$(9p read anvillm/beads/mtab 2>/dev/null || true)
|
|
if [ -z "$MTAB" ]; then
|
|
log "no mounts, nothing to do"
|
|
exit 0
|
|
fi
|
|
|
|
while IFS=$'\t' read -r MOUNT CWD; do
|
|
[ -z "$MOUNT" ] && continue
|
|
|
|
IN_PROGRESS=$(9p read "anvillm/beads/$MOUNT/list" 2>/dev/null \
|
|
| jq -r '.[] | select(.status == "in_progress") | [.id, (.assignee // "")] | @tsv' \
|
|
2>/dev/null || true)
|
|
|
|
[ -z "$IN_PROGRESS" ] && continue
|
|
|
|
while IFS=$'\t' read -r BEAD_ID ASSIGNEE; do
|
|
[ -z "$BEAD_ID" ] && continue
|
|
|
|
# Skip if claimed by user (human in the loop — not an orphan)
|
|
[ "$ASSIGNEE" = "user" ] && continue
|
|
|
|
# Skip if assignee session is still alive
|
|
if [ -n "$ASSIGNEE" ] && echo "$LIVE_SESSIONS" | grep -qx "$ASSIGNEE"; then
|
|
continue
|
|
fi
|
|
|
|
log "orphan: $BEAD_ID (was: ${ASSIGNEE:-unassigned}) mount=$MOUNT — unclaiming"
|
|
echo "unclaim $BEAD_ID" | 9p write "anvillm/beads/$MOUNT/ctl" 2>/dev/null || \
|
|
log "WARNING: unclaim failed for $BEAD_ID"
|
|
|
|
done <<< "$IN_PROGRESS"
|
|
done <<< "$MTAB"
|