synops/scripts/run-next-task.sh
vegard a9590e4ed9 Oppdatert run-next-task.sh for filbaserte tasks
Plukker fra tasks/*.md, flytter til active/, done/ ved fullføring.
Støtter --loop (kjør kontinuerlig), --dry (forhåndsvis), --status.
Krasj-deteksjon: stale oppgaver i active/ >60 min frigjøres.
30 min timeout per oppgave.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 18:02:09 +00:00

160 lines
4.1 KiB
Bash
Executable file

#!/usr/bin/env bash
# Plukk neste oppgave fra tasks/ og kjør med Claude Code.
# Bruk:
# ./scripts/run-next-task.sh # kjør én oppgave
# ./scripts/run-next-task.sh --loop # kjør oppgaver i loop
# ./scripts/run-next-task.sh --dry # vis neste uten å kjøre
# ./scripts/run-next-task.sh --status # vis status
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
TASKS="$ROOT/tasks"
ACTIVE="$TASKS/active"
DONE="$TASKS/done"
LOGS="$ROOT/logs"
LOCKFILE="/tmp/synops-task-runner.lock"
mkdir -p "$ACTIVE" "$DONE" "$LOGS"
# Lås — hindrer dobbeltstart
if [ -f "$LOCKFILE" ]; then
PID=$(cat "$LOCKFILE" 2>/dev/null || echo "")
if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then
echo "Allerede en task-runner aktiv (PID $PID)"
exit 0
fi
rm -f "$LOCKFILE"
fi
echo $$ > "$LOCKFILE"
trap 'rm -f "$LOCKFILE"' EXIT
# --- Krasj-deteksjon: frigjør stale oppgaver ---
unstale() {
for f in "$ACTIVE"/*.md; do
[ -f "$f" ] || continue
age_min=$(( ($(date +%s) - $(stat -c %Y "$f")) / 60 ))
if [ "$age_min" -gt 60 ]; then
echo "Frigjør stale oppgave: $(basename "$f") ($age_min min)"
mv "$f" "$TASKS/"
fi
done
}
# --- Status ---
if [[ "${1:-}" == "--status" ]]; then
todo=$(ls "$TASKS"/*.md 2>/dev/null | grep -v README | wc -l)
active=$(ls "$ACTIVE"/*.md 2>/dev/null | wc -l)
done_count=$(ls "$DONE"/*.md 2>/dev/null | wc -l)
echo "=== Synops oppgavestatus ==="
echo "Gjenstår: $todo"
echo "Aktiv: $active"
echo "Fullført: $done_count"
if [ "$active" -gt 0 ]; then
echo ""
echo "--- Aktive ---"
ls "$ACTIVE"/*.md 2>/dev/null | xargs -I{} basename {}
fi
echo ""
echo "--- Neste 5 ---"
ls "$TASKS"/*.md 2>/dev/null | grep -v README | sort | head -5 | xargs -I{} basename {}
exit 0
fi
# --- Kjør én oppgave ---
run_one() {
unstale
TASK=$(ls "$TASKS"/*.md 2>/dev/null | grep -v README | sort | head -1)
if [ -z "$TASK" ]; then
echo "Ingen oppgaver å gjøre"
return 1
fi
TASKNAME=$(basename "$TASK")
echo "=== Plukker: $TASKNAME ==="
if [[ "${1:-}" == "--dry" ]]; then
cat "$TASK"
return 0
fi
# Flytt til active
mv "$TASK" "$ACTIVE/$TASKNAME"
TASK_CONTENT=$(cat "$ACTIVE/$TASKNAME")
cd "$ROOT"
git pull origin main 2>/dev/null || true
# Kjør Claude Code
LOGFILE="$LOGS/task-$(date +%Y%m%d-%H%M)-$TASKNAME.log"
timeout 1800 claude -p "
Du har fått denne oppgaven:
$TASK_CONTENT
Arbeidsmappe: $ROOT
Arbeidsflyt:
1. Les CLAUDE.md for prosjektkontekst
2. Les refererte docs/proposals
3. Implementer
4. Verifiser (cargo check, npm run build)
5. Commit og push
6. Rapporter hva du gjorde
Regler:
- Les relevante filer før du endrer dem
- Gjør minimale, fokuserte endringer
- Push jevnlig underveis
" --dangerously-skip-permissions 2>&1 | tee "$LOGFILE"
EXIT_CODE=${PIPESTATUS[0]}
if [ "$EXIT_CODE" -eq 0 ]; then
mv "$ACTIVE/$TASKNAME" "$DONE/$(date +%Y-%m-%d)-$TASKNAME"
echo "=== Fullført: $TASKNAME ==="
# Commit task-flytt
cd "$ROOT"
git add -A tasks/ && git commit -m "Task fullført: $TASKNAME" --no-verify 2>/dev/null || true
git push origin main 2>/dev/null || true
return 0
else
mv "$ACTIVE/$TASKNAME" "$TASKS/$TASKNAME"
echo "=== Feilet (exit $EXIT_CODE): $TASKNAME ==="
return 1
fi
}
# --- Dry run ---
if [[ "${1:-}" == "--dry" ]]; then
unstale
TASK=$(ls "$TASKS"/*.md 2>/dev/null | grep -v README | sort | head -1)
if [ -z "$TASK" ]; then
echo "Ingen oppgaver"
else
echo "Neste: $(basename "$TASK")"
echo "---"
cat "$TASK"
fi
exit 0
fi
# --- Loop-modus ---
if [[ "${1:-}" == "--loop" ]]; then
echo "=== Task runner loop startet ($(date)) ==="
while true; do
if ! run_one; then
echo "Ingen flere oppgaver eller feil. Venter 5 min..."
sleep 300
else
echo "Venter 30 sek før neste oppgave..."
sleep 30
fi
done
fi
# --- Enkel kjøring ---
run_one