All skills
simota avatar

/orbit

@35ffd55
by shingo imotasimota/agent-skills85 stars
15

Running autonomous loops for nexus-autoloop. Generates script sets from goals, designs operation contracts, audits live loops, and recovers state — runners that complete reliably.

Use this Skill: https://skilld.dev/gh/simota/agent-skills/orbit

This session only. Nothing lands on disk.

referencescript-template-runner.md

≈9k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Orbit Runner Script Template

Purpose: load this only when Orbit must generate or patch run-loop.sh. It contains the executable runner template and nothing else.

Contents

Runner Template (run-loop.sh)

Primary output of Orbit. Drives autonomous loop execution from goal to DONE.

#!/bin/bash
# nexus-autoloop runner — generated by Orbit
# Goal: {{GOAL_SUMMARY}}
# Generated: {{TIMESTAMP}}
set -euo pipefail

#--- Configuration (customize per goal) ---
LOOP_DIR="${LOOP_DIR:-$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)}"
LOOP_DIR="$(cd -- "${LOOP_DIR}" && pwd)"
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || true)
MAX_ITERATIONS="${MAX_ITERATIONS:-20}"
RETRY_LIMIT="${RETRY_LIMIT:-3}"
RETRY_BACKOFF_BASE="${RETRY_BACKOFF_BASE:-2}"
# Executor command — see reference/executor-engines.md for engine-specific configuration
EXEC_CMD="${EXEC_CMD:-codex}"
EXEC_TIMEOUT="${ITER_TIMEOUT:-${EXEC_TIMEOUT:-600}}"
AUTOCOMMIT="${AUTOCOMMIT:-true}"
COMMIT_MSG_PREFIX="${COMMIT_MSG_PREFIX:-loop}"
NOTIFY_ENABLED="${NOTIFY_ENABLED:-false}"
MAX_LOG_SIZE="${MAX_LOG_SIZE:-5242880}"
ADAPTIVE_TIMEOUT="${ADAPTIVE_TIMEOUT:-false}"
SKIP_PREFLIGHT="${SKIP_PREFLIGHT:-false}"
BRANCH_ISOLATION="${BRANCH_ISOLATION:-true}"
SQUASH_ON_DONE="${SQUASH_ON_DONE:-true}"
SQUASH_MSG_ENGINE="${SQUASH_MSG_ENGINE:-auto}"

#--- Resilience configuration ---
CIRCUIT_BREAKER="${CIRCUIT_BREAKER:-true}"
CIRCUIT_THRESHOLD="${CIRCUIT_THRESHOLD:-3}"
CIRCUIT_COOLDOWN="${CIRCUIT_COOLDOWN:-300}"
TOOL_TIMEOUT="${TOOL_TIMEOUT:-120}"
ITER_TIMEOUT="${ITER_TIMEOUT:-${EXEC_TIMEOUT}}"
STRUCTURED_LOG="${STRUCTURED_LOG:-true}"
COST_TRACKING="${COST_TRACKING:-false}"
TOKEN_BUDGET="${TOKEN_BUDGET:-0}"

#--- External terminators (beyond MAX_ITERATIONS) ---
# Core Contract: termination MUST be enforced externally (iteration cap, timeout, budget).
LOOP_TIMEOUT="${LOOP_TIMEOUT:-0}"            # total wall-clock seconds; 0 = unlimited
USD_PER_RUN_CAP="${USD_PER_RUN_CAP:-0}"      # absolute USD cap per run; 0 = unlimited
USD_PER_ITER_CAP="${USD_PER_ITER_CAP:-0}"    # absolute USD cap per iteration; 0 = unlimited
# Executors that know their cost append a USD float line to ${LOOP_DIR}/.cost-usd each iteration.

#--- Semantic-stall & evidence gates ---
CONVERGENCE_THRESHOLD="${CONVERGENCE_THRESHOLD:-0.85}"
CONVERGENCE_WINDOW="${CONVERGENCE_WINDOW:-3}"
PLACEHOLDER_GREP="${PLACEHOLDER_GREP:-true}"
GOAL_IMMUTABLE="${GOAL_IMMUTABLE:-true}"

#--- Portable timeout (macOS + Linux) ---
portable_timeout() {
  local secs="$1"; shift
  if command -v timeout >/dev/null 2>&1; then
    timeout --signal=KILL "${secs}" "$@"
  elif command -v gtimeout >/dev/null 2>&1; then
    gtimeout --signal=KILL "${secs}" "$@"
  else
    perl -e '
      use POSIX ":sys_wait_h";
      my $timeout = shift @ARGV;
      my $pid = fork // die "fork: $!";
      if ($pid == 0) {
        setpgrp(0, 0) or die "setpgrp: $!";
        exec { $ARGV[0] } @ARGV or die "exec: $!";
      }
      local $SIG{ALRM} = sub {
        kill 9, -$pid; kill 9, $pid;
        waitpid($pid, 0); exit 124;
      };
      alarm $timeout;
      waitpid($pid, 0);
      my $status = $?;
      exit(($status & 127) ? 128 + ($status & 127) : $status >> 8);
    ' "${secs}" "$@"
  fi
}

#--- Pre-flight checks (skip with SKIP_PREFLIGHT=true) ---
preflight_check() {
  if [[ "${SKIP_PREFLIGHT}" == "true" ]]; then
    echo "[PREFLIGHT] Skipped (SKIP_PREFLIGHT=true)"
    return 0
  fi

  # Disk space check (abort if < 100MB free)
  local avail_kb
  avail_kb=$(df -k "${LOOP_DIR}" | awk 'NR==2{print $4}')
  if [[ "${avail_kb}" -lt 102400 ]]; then
    echo "[PREFLIGHT:FAIL] Disk space critically low: ${avail_kb}KB available (< 100MB)"
    return 1
  fi

  # Stale lock detection
  if [[ -f "${LOOP_DIR}/.run-loop.lock" ]]; then
    local lock_pid
    lock_pid=$(cat "${LOOP_DIR}/.run-loop.lock")
    if kill -0 "${lock_pid}" 2>/dev/null; then
      echo "[PREFLIGHT:FAIL] Active lock — PID ${lock_pid} is running"
      return 1
    else
      echo "[PREFLIGHT:WARN] Stale lock — PID ${lock_pid} dead, removing"
      rm -f "${LOOP_DIR}/.run-loop.lock"
    fi
  fi

  # Git repository health (AUTOCOMMIT only)
  if [[ "${AUTOCOMMIT}" == "true" ]]; then
    if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
      echo "[PREFLIGHT:FAIL] Not inside a git repository (AUTOCOMMIT=true requires git)"
      return 1
    fi
    if [[ -d "$(git rev-parse --git-path rebase-merge)" ]] || [[ -d "$(git rev-parse --git-path rebase-apply)" ]]; then
      echo "[PREFLIGHT:FAIL] Git rebase in progress — resolve before running loop"
      return 1
    fi
  fi

  echo "[PREFLIGHT] All checks passed"
  return 0
}

# Run pre-flight and abort on failure
if ! preflight_check; then
  echo "[ABORT] Pre-flight check failed — fix issues and retry"
  exit 1
fi

# Acquire the lock atomically; always release it, including unexpected errors.
if ! (set -o noclobber; echo $$ > "${LOOP_DIR}/.run-loop.lock") 2>/dev/null; then
  echo "[ABORT] Another runner acquired the loop lock"
  exit 1
fi
trap 'rm -f "${LOOP_DIR}/.run-loop.lock"' EXIT

#--- Log rotation ---
rotate_log() {
  if [[ -f "${LOOP_DIR}/runner.log" ]]; then
    local log_size
    log_size=$(wc -c < "${LOOP_DIR}/runner.log" 2>/dev/null || echo 0)
    if [[ "${log_size}" -gt "${MAX_LOG_SIZE}" ]]; then
      mv "${LOOP_DIR}/runner.log" "${LOOP_DIR}/runner.log.prev"
      echo "[LOG] Rotated runner.log (${log_size} bytes > MAX_LOG_SIZE=${MAX_LOG_SIZE})"
    fi
  fi
}
rotate_log

#--- Structured logging (JSON Lines) ---
json_escape() {
  local value="$1" char code escaped result="" i
  local LC_ALL=C
  for ((i=0; i<${#value}; i++)); do
    char="${value:i:1}"
    case "${char}" in
      '"') result+='\"' ;;
      '\') result+='\\' ;;
      *)
        printf -v code '%d' "'${char}"
        if ((code < 32)); then
          printf -v escaped '\\u%04x' "${code}"
          result+="${escaped}"
        else
          result+="${char}"
        fi ;;
    esac
  done
  printf '%s' "${result}"
}
emit_log() {
  if [[ "${STRUCTURED_LOG}" != "true" ]]; then return; fi
  local level="$1" event="$2"; shift 2
  local ts
  ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
  local json="{\"timestamp\":\"${ts}\",\"level\":\"$(json_escape "${level}")\",\"event\":\"$(json_escape "${event}")\",\"iteration\":${ITER:-0}"
  while [[ $# -ge 2 ]]; do
    json="${json},\"$(json_escape "$1")\":\"$(json_escape "$2")\""
    shift 2
  done
  printf '%s}\n' "${json}" >> "${LOOP_DIR}/runner.jsonl"
}

#--- Circuit breaker ---
CIRCUIT_FILE="${LOOP_DIR}/.circuit-state"
CB_STATE="CLOSED"
CB_FAIL_COUNT=0
CB_LAST_SIGNATURE=""
CB_LAST_UPDATED=0

load_circuit_state() {
  local key value
  [[ -f "${CIRCUIT_FILE}" ]] || return 0
  while IFS='=' read -r key value || [[ -n "${key}" ]]; do
    case "${key}" in
      CB_STATE) [[ "${value}" =~ ^(OPEN|HALF_OPEN|CLOSED)$ ]] || continue ;;
      CB_FAIL_COUNT|CB_LAST_UPDATED) [[ "${value}" =~ ^[0-9]+$ ]] || continue ;;
      CB_LAST_SIGNATURE) [[ "${value}" =~ ^[A-Za-z0-9_]*$ ]] || continue ;;
      *) continue ;;
    esac
    printf -v "${key}" '%s' "${value}"
  done < "${CIRCUIT_FILE}"
}

save_circuit_state() {
  cat > "${CIRCUIT_FILE}" <<CB_EOF
CB_STATE=${CB_STATE:-CLOSED}
CB_FAIL_COUNT=${CB_FAIL_COUNT}
CB_LAST_SIGNATURE=${CB_LAST_SIGNATURE}
CB_LAST_UPDATED=$(date +%s)
CB_EOF
}

check_circuit() {
  load_circuit_state
  if [[ "${CIRCUIT_BREAKER}" != "true" ]]; then return 0; fi
  local now
  now=$(date +%s)
  case "${CB_STATE:-CLOSED}" in
    OPEN)
      local elapsed=$(( now - ${CB_LAST_UPDATED:-0} ))
      if [[ "${elapsed}" -ge "${CIRCUIT_COOLDOWN}" ]]; then
        CB_STATE="HALF_OPEN"
        emit_log "INFO" "circuit_state_change" "from" "OPEN" "to" "HALF_OPEN" "reason" "cooldown_elapsed"
        save_circuit_state
        return 0
      fi
      emit_log "WARN" "circuit_open" "remaining_cooldown" "$((CIRCUIT_COOLDOWN - elapsed))"
      return 1
      ;;
    HALF_OPEN|CLOSED)
      return 0
      ;;
  esac
}

record_circuit_failure() {
  local signature="$1"
  if [[ "${CIRCUIT_BREAKER}" != "true" ]]; then return; fi
  if [[ "${signature}" == "${CB_LAST_SIGNATURE}" ]]; then
    CB_FAIL_COUNT=$((CB_FAIL_COUNT + 1))
  else
    CB_FAIL_COUNT=1
    CB_LAST_SIGNATURE="${signature}"
  fi
  if [[ "${CB_STATE:-CLOSED}" == "HALF_OPEN" ]]; then
    CB_STATE="OPEN"
    emit_log "WARN" "circuit_state_change" "from" "HALF_OPEN" "to" "OPEN" "signature" "${signature}"
  elif [[ "${CB_FAIL_COUNT}" -ge "${CIRCUIT_THRESHOLD}" ]]; then
    CB_STATE="OPEN"
    emit_log "WARN" "circuit_state_change" "from" "CLOSED" "to" "OPEN" "signature" "${signature}" "count" "${CB_FAIL_COUNT}"
  fi
  save_circuit_state
}

record_circuit_success() {
  if [[ "${CIRCUIT_BREAKER}" != "true" ]]; then return; fi
  if [[ "${CB_STATE:-CLOSED}" != "CLOSED" ]]; then
    emit_log "INFO" "circuit_state_change" "from" "${CB_STATE}" "to" "CLOSED" "reason" "success"
  fi
  CB_STATE="CLOSED"
  CB_FAIL_COUNT=0
  CB_LAST_SIGNATURE=""
  save_circuit_state
}

#--- Budget gate (reads optional executor-emitted ${LOOP_DIR}/.cost-usd) ---
# Never run unmonitored loops without budget caps. Enforcement is a no-op only when
# both caps are 0 AND no cost signal exists; otherwise caps are hard external terminators.
cost_total_usd() {
  [[ -f "${LOOP_DIR}/.cost-usd" ]] || { echo 0; return; }
  awk '{s+=$1} END{printf "%.4f", s+0}' "${LOOP_DIR}/.cost-usd"
}
cost_last_usd() {
  [[ -f "${LOOP_DIR}/.cost-usd" ]] || { echo 0; return; }
  tail -1 "${LOOP_DIR}/.cost-usd" 2>/dev/null | awk '{printf "%.4f", $1+0}'
}
budget_exceeded() {
  # returns 0 (true) when a configured cap is exceeded
  local total last
  total=$(cost_total_usd); last=$(cost_last_usd)
  if [[ "${USD_PER_RUN_CAP}" != "0" ]] && awk "BEGIN{exit !(${total} > ${USD_PER_RUN_CAP})}"; then
    echo "[BUDGET:RUN] run cost \$${total} exceeded USD_PER_RUN_CAP=\$${USD_PER_RUN_CAP}"; return 0
  fi
  if [[ "${USD_PER_ITER_CAP}" != "0" ]] && awk "BEGIN{exit !(${last} > ${USD_PER_ITER_CAP})}"; then
    echo "[BUDGET:ITER] iter cost \$${last} exceeded USD_PER_ITER_CAP=\$${USD_PER_ITER_CAP}"; return 0
  fi
  return 1
}

# Pin the start commit even without branch isolation: autocommit must not hide
# changed files from completion checks. Emit NUL-delimited literal paths.
loop_changed_files() {
  local base="${LOOP_BASE:-}"
  [[ -n "${REPO_ROOT}" ]] || return 0
  if [[ -n "${base}" ]] && git rev-parse --verify "${base}" >/dev/null 2>&1; then
    git -C "${REPO_ROOT}" diff --name-only -z "${base}...HEAD" -- 2>/dev/null || true
  fi
  git -C "${REPO_ROOT}" diff --name-only -z HEAD -- 2>/dev/null || true
  git -C "${REPO_ROOT}" ls-files --others --exclude-standard -z 2>/dev/null || true
}

#--- Placeholder gate: verify PASS alone is not DONE evidence (AP-12) ---
placeholder_clean() {
  [[ "${PLACEHOLDER_GREP}" == "true" ]] || return 0
  local changed path result
  changed=$(mktemp "${LOOP_DIR}/placeholder-paths.XXXXXX")
  loop_changed_files > "${changed}"
  while IFS= read -r -d '' path; do
    case "${path}" in
      *.js|*.ts|*.tsx|*.jsx|*.py|*.go|*.rb|*.rs|*.java|*.kt|*.swift|*.php|*.c|*.cc|*.cpp|*.h) ;;
      *) continue ;;
    esac
    path="${REPO_ROOT}/${path}"
    [[ -f "${path}" ]] || continue # deleted source needs no scan
    result=0
    grep -nE 'TODO|FIXME|NotImplementedError|raise NotImplemented|^[[:space:]]*pass[[:space:]]*$|return None[[:space:]]*#|throw new Error\("not implemented"\)' -- "${path}" || result=$?
    if [[ "${result}" -ne 1 ]]; then
      rm -f "${changed}"
      return 1 # a match or an unreadable source cannot satisfy the gate
    fi
  done < "${changed}"
  rm -f "${changed}"
  return 0
}

#--- Convergence / stuck-loop gate (semantic stall, not just exit codes) ---
# Signature = HEAD tree hash + working-tree diff hash + verify result. CONVERGENCE_WINDOW
# identical signatures in a row => CONVERGENCE_STALL (no net progress despite "success").
# Tree hash advances on every real commit, so healthy autocommit loops never false-trip.
SIG_LOG="${LOOP_DIR}/.action-sig.log"
record_signature() {
  local verify="$1" tree wt sig path repo_root
  repo_root=$(git rev-parse --show-toplevel 2>/dev/null || true)
  tree=$(git rev-parse 'HEAD^{tree}' 2>/dev/null || echo "no-tree")
  wt=$( {
    git diff HEAD 2>/dev/null || true
    if [[ -n "${repo_root}" ]]; then
      git -C "${repo_root}" ls-files --others --exclude-standard -z |
      while IFS= read -r -d '' path; do
        # Runtime logs/checkpoints change each turn but are not goal progress.
        [[ "${repo_root}/${path}" == "${LOOP_DIR}/"* ]] && continue
        printf '%s\0' "${path}"
        if [[ -L "${repo_root}/${path}" ]]; then
          readlink "${repo_root}/${path}"
        elif [[ -f "${repo_root}/${path}" ]]; then
          shasum -a 256 < "${repo_root}/${path}"
        fi
      done
    fi
  } | shasum -a 256 | awk '{print $1}')
  sig=$(printf '%s:%s:%s' "${tree}" "${wt}" "${verify}" | shasum -a 256 | awk '{print $1}')
  echo "${sig}" >> "${SIG_LOG}"
}
convergence_stalled() {
  [[ -f "${SIG_LOG}" ]] || return 1
  local n; n="${CONVERGENCE_WINDOW}"
  local lines; lines=$(tail -n "${n}" "${SIG_LOG}")
  [[ "$(echo "${lines}" | wc -l | tr -d ' ')" -lt "${n}" ]] && return 1
  [[ "$(echo "${lines}" | sort -u | wc -l | tr -d ' ')" -eq 1 ]]
}

# Parse checkpoint data without evaluating shell code or assigning environment keys.
load_state() {
  local key value
  [[ -f "${LOOP_DIR}/state.env" ]] || return 0
  while IFS='=' read -r key value || [[ -n "${key}" ]]; do
    case "${key}" in
      NEXT_ITERATION)
        [[ "${value}" =~ ^[1-9][0-9]*$ ]] || continue ;;
      LAST_STATUS)
        [[ "${value}" =~ ^(READY|CONTINUE|DONE|BLOCKED)$ ]] || continue ;;
      TOTAL_TOKENS|TOTAL_API_CALLS|ITER_TOKENS|ITER_API_CALLS)
        [[ "${value}" =~ ^[0-9]+$ ]] || continue ;;
      ESTIMATED_COST_USD)
        [[ "${value}" =~ ^[0-9]+([.][0-9]+)?$ ]] || continue ;;
      CONTRACT_VERSION)
        [[ "${value}" =~ ^[0-9]+[.][0-9]+[.][0-9]+$ ]] || continue ;;
      LAST_UPDATED_AT|ORIGIN_BRANCH|ITER_BRANCH|RECOVERED_FROM|LOOP_BASE) ;;
      *) continue ;;
    esac
    printf -v "${key}" '%s' "${value}"
  done < "${LOOP_DIR}/state.env"
}

write_state() {
  local next="$1" status="$2" tmp key
  tmp=$(mktemp "${LOOP_DIR}/state.env.XXXXXX")
  cat > "${tmp}" <<STATE_EOF
NEXT_ITERATION=${next}
LAST_STATUS=${status}
LAST_UPDATED_AT=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
ORIGIN_BRANCH=${ORIGIN_BRANCH:-}
ITER_BRANCH=${ITER_BRANCH:-}
LOOP_BASE=${LOOP_BASE:-}
CONTRACT_VERSION=${CONTRACT_VERSION:-1.2.0}
STATE_EOF
  for key in TOTAL_TOKENS TOTAL_API_CALLS ESTIMATED_COST_USD; do
    if [[ -n "${!key:-}" ]]; then
      printf '%s=%s\n' "${key}" "${!key}" >> "${tmp}"
    fi
  done
  mv "${tmp}" "${LOOP_DIR}/state.env"
  shasum -a 256 "${LOOP_DIR}/state.env" | awk '{print $1}' > "${LOOP_DIR}/state.env.sha256"
}

#--- Graceful shutdown (SIGINT/SIGTERM) ---
SHUTDOWN=0
cleanup() {
  echo "[SIGNAL] Caught signal — initiating graceful shutdown"
  SHUTDOWN=1

  # Step 1: State snapshot
  write_state "${ITER:-1}" CONTINUE

  # Step 2: Partial results summary
  {
    echo ""
    echo "## Iteration ${ITER} — INTERRUPTED"
    echo "- Signal: graceful shutdown"
    echo "- Timestamp: $(date -u +"%Y-%m-%dT%H:%M:%SZ")"
    echo "- Last verify: ${VERIFY_RESULT:-N/A}"
    echo "- Partial work preserved for resume"
  } >> "${LOOP_DIR}/progress.md"

  # Step 3: Structured log
  emit_log "WARN" "graceful_shutdown" "iteration" "${ITER}" "verify" "${VERIFY_RESULT:-N/A}"

  # Step 4: Cleanup
  rm -f "${LOOP_DIR}/.run-loop.lock"
  echo "[SIGNAL] State saved — safe to resume from iteration ${ITER}"
  exit 130
}
trap cleanup SIGINT SIGTERM

#--- Validate checksum before consuming checkpoint values ---
ITER=1
STATUS="READY"
if [[ -f "${LOOP_DIR}/state.env.sha256" ]]; then
  EXPECTED_SHA=$(cat "${LOOP_DIR}/state.env.sha256")
  ACTUAL_SHA=""
  if [[ -f "${LOOP_DIR}/state.env" ]]; then
    ACTUAL_SHA=$(shasum -a 256 "${LOOP_DIR}/state.env" | awk '{print $1}')
  fi
  if [[ "${EXPECTED_SHA}" != "${ACTUAL_SHA}" ]]; then
    echo "[WARN] state.env checksum mismatch — recovering before loading state"
    if [[ -f "${LOOP_DIR}/recover.sh" ]]; then
      bash "${LOOP_DIR}/recover.sh" "${LOOP_DIR}"
    else
      echo "[ABORT] Run recover.sh to rebuild the corrupted checkpoint"
      exit 1
    fi
  fi
fi
load_state
ITER="${NEXT_ITERATION:-1}"
STATUS="${LAST_STATUS:-READY}"
LOOP_BASE="${LOOP_BASE:-$(git rev-parse --verify "${ORIGIN_BRANCH:-HEAD}" 2>/dev/null || true)}"

#--- Branch isolation (pre-loop) ---
if [[ "${BRANCH_ISOLATION}" == "true" ]] && [[ "${AUTOCOMMIT}" == "true" ]]; then
  LOOP_NAME=$(basename "${LOOP_DIR}" | sed 's/^\.//')
  ITER_BRANCH="loop/iter-${LOOP_NAME}"
  SUMMARY_BRANCH="loop/summary-${LOOP_NAME}"

  # Determine origin branch (resume: from state.env, first run: current HEAD)
  if [[ -z "${ORIGIN_BRANCH:-}" ]]; then
    ORIGIN_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
  fi

  CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
  # DONE can be resumed after squash has already removed the iteration branch.
  if [[ "${STATUS}" != "DONE" ]] && [[ "${CURRENT_BRANCH}" != "${ITER_BRANCH}" ]]; then
    # Stash dirty worktree before branch switch
    STASHED_FOR_BRANCH=false
    if ! git diff --quiet 2>/dev/null || ! git diff --cached --quiet 2>/dev/null; then
      git stash push -m "orbit-branch-isolation-pre-switch"
      STASHED_FOR_BRANCH=true
    fi

    if git rev-parse --verify "${ITER_BRANCH}" >/dev/null 2>&1; then
      git checkout "${ITER_BRANCH}"
    else
      git checkout -b "${ITER_BRANCH}"
    fi

    if [[ "${STASHED_FOR_BRANCH}" == "true" ]]; then
      git stash pop --index || { echo "[ABORT] Stash restore conflict — resolve before resuming"; exit 1; }
    fi
  fi
fi

#--- Dirty baseline snapshot (NUL preserves spaces, quotes, and newlines) ---
if [[ "${AUTOCOMMIT}" == "true" ]]; then
  {
    git -C "${REPO_ROOT}" diff --name-only -z -- 2>/dev/null || true
    git -C "${REPO_ROOT}" diff --cached --name-only -z -- 2>/dev/null || true
    git -C "${REPO_ROOT}" ls-files --others --exclude-standard -z 2>/dev/null || true
  } > "${LOOP_DIR}/dirty-start-paths.nul"
fi

#--- Adaptive timeout ---
EFFECTIVE_TIMEOUT="${EXEC_TIMEOUT}"
TIMING_LOG="${LOOP_DIR}/.iter-timings.log"
if [[ "${ADAPTIVE_TIMEOUT}" == "true" ]] && [[ -f "${TIMING_LOG}" ]]; then
  # Calculate median of last 5 timings x 2, bounded by [EXEC_TIMEOUT, EXEC_TIMEOUT*3]
  TIMINGS=$(tail -5 "${TIMING_LOG}" | sort -n)
  COUNT=$(echo "${TIMINGS}" | wc -l | tr -d ' ')
  if [[ "${COUNT}" -ge 3 ]]; then
    MEDIAN=$(echo "${TIMINGS}" | sed -n "$(( (COUNT + 1) / 2 ))p")
    ADAPTIVE_VAL=$((MEDIAN * 2))
    MAX_TIMEOUT=$((EXEC_TIMEOUT * 3))
    if [[ "${ADAPTIVE_VAL}" -lt "${EXEC_TIMEOUT}" ]]; then
      EFFECTIVE_TIMEOUT="${EXEC_TIMEOUT}"
    elif [[ "${ADAPTIVE_VAL}" -gt "${MAX_TIMEOUT}" ]]; then
      EFFECTIVE_TIMEOUT="${MAX_TIMEOUT}"
    else
      EFFECTIVE_TIMEOUT="${ADAPTIVE_VAL}"
    fi
    echo "[ADAPTIVE] Timeout adjusted to ${EFFECTIVE_TIMEOUT}s (median=${MEDIAN}s x 2, bounds=[${EXEC_TIMEOUT},${MAX_TIMEOUT}])"
  fi
fi

#--- Goal/AC immutability pin (AP-16: mid-run goal drift ABORTs) ---
GOAL_SHA_FILE="${LOOP_DIR}/.goal.sha256"
if [[ "${GOAL_IMMUTABLE}" == "true" ]] && [[ -f "${LOOP_DIR}/goal.md" ]]; then
  if [[ ! -f "${GOAL_SHA_FILE}" ]]; then
    shasum -a 256 "${LOOP_DIR}/goal.md" | awk '{print $1}' > "${GOAL_SHA_FILE}"
  fi
fi
check_goal_immutable() {
  [[ "${GOAL_IMMUTABLE}" == "true" ]] || return 0
  [[ -f "${GOAL_SHA_FILE}" ]] || return 0
  local now; now=$(shasum -a 256 "${LOOP_DIR}/goal.md" 2>/dev/null | awk '{print $1}')
  [[ "${now}" == "$(cat "${GOAL_SHA_FILE}")" ]]
}

#--- Loop-level external terminator (wall clock) ---
LOOP_START_TS=$(date +%s)
LOOP_DEADLINE=0
[[ "${LOOP_TIMEOUT}" -gt 0 ]] && LOOP_DEADLINE=$((LOOP_START_TS + LOOP_TIMEOUT))

# Executor attempts, retry delays, and verification share this one deadline.
# A zero command limit means no local limit; the remaining loop budget still applies.
run_with_budget() {
  local limit="$1" remaining; shift
  if [[ "${LOOP_DEADLINE}" -gt 0 ]]; then
    remaining=$((LOOP_DEADLINE - $(date +%s)))
    [[ "${remaining}" -gt 0 ]] || return 124
    if [[ "${limit}" -eq 0 || "${remaining}" -lt "${limit}" ]]; then
      limit="${remaining}"
    fi
  fi
  if [[ "${limit}" -gt 0 ]]; then
    portable_timeout "${limit}" "$@"
  else
    "$@"
  fi
}

loop_timeout_reached() {
  [[ "${LOOP_DEADLINE}" -gt 0 ]] && [[ "$(date +%s)" -ge "${LOOP_DEADLINE}" ]]
}

write_terminal_state() {
  write_state "${ITER}" "$1"
}

#--- Main loop ---
VERIFY_RESULT="N/A"
COMMIT_HASH="no-commit"

while [[ "${STATUS}" != "DONE" ]] && [[ "${ITER}" -le "${MAX_ITERATIONS}" ]]; do
  [[ "${SHUTDOWN}" -eq 1 ]] && break

  #--- External terminators: wall-clock timeout & budget caps ---
  if [[ "${LOOP_DEADLINE}" -gt 0 ]] && [[ "$(date +%s)" -ge "${LOOP_DEADLINE}" ]]; then
    echo "[TIMEOUT] LOOP_TIMEOUT=${LOOP_TIMEOUT}s exceeded — external terminator" | tee -a "${LOOP_DIR}/runner.log"
    emit_log "WARN" "loop_timeout" "elapsed" "$(( $(date +%s) - LOOP_START_TS ))"
    STATUS="BLOCKED"; write_terminal_state BLOCKED; break
  fi
  if BUDGET_MSG=$(budget_exceeded); then
    echo "[ABORT] ${BUDGET_MSG} — pausing; explicit human resume required" | tee -a "${LOOP_DIR}/runner.log"
    emit_log "ERROR" "budget_exceeded" "detail" "${BUDGET_MSG}"
    STATUS="BLOCKED"; write_terminal_state BLOCKED; break
  fi
  if ! check_goal_immutable; then
    echo "[ABORT] goal.md changed mid-run (GOAL_DRIFT / AP-16)" | tee -a "${LOOP_DIR}/runner.log"
    emit_log "ERROR" "goal_drift" "file" "goal.md"
    STATUS="BLOCKED"; write_terminal_state BLOCKED; break
  fi
  if convergence_stalled; then
    echo "[CONVERGENCE:STALL] ${CONVERGENCE_WINDOW} identical-signature iterations — no net progress" | tee -a "${LOOP_DIR}/runner.log"
    emit_log "ERROR" "convergence_stall" "window" "${CONVERGENCE_WINDOW}"
    STATUS="BLOCKED"; write_terminal_state BLOCKED; break
  fi

  # Circuit breaker gate
  if ! check_circuit; then
    echo "[CIRCUIT:OPEN] Execution blocked — waiting for cooldown or manual reset" | tee -a "${LOOP_DIR}/runner.log"
    STATUS="BLOCKED"
    write_state "${ITER}" "BLOCKED"
    emit_log "ERROR" "circuit_breaker_block" "state" "OPEN"
    break
  fi

  ITER_START=$(date +%s)
  VERIFY_RESULT="N/A"
  COMMIT_HASH="no-commit"
  echo ""
  echo "=== Iteration ${ITER}/${MAX_ITERATIONS} ==="

  #--- Iteration health check ---
  HEALTH_AVAIL=$(df -k "${LOOP_DIR}" | awk 'NR==2{print $4}')
  if [[ "${HEALTH_AVAIL}" -lt 51200 ]]; then
    echo "[HEALTH:BLOCKED] Disk space low: ${HEALTH_AVAIL}KB (< 50MB)" | tee -a "${LOOP_DIR}/runner.log"
    STATUS="BLOCKED"
    write_state "${ITER}" "BLOCKED"
    break
  fi
  if [[ "${AUTOCOMMIT}" == "true" ]]; then
    if [[ -d "$(git rev-parse --git-path rebase-merge)" ]] || [[ -d "$(git rev-parse --git-path rebase-apply)" ]]; then
      echo "[HEALTH:BLOCKED] Git rebase in progress" | tee -a "${LOOP_DIR}/runner.log"
      STATUS="BLOCKED"
      write_state "${ITER}" "BLOCKED"
      break
    fi
  fi
  rotate_log

  #--- Bounded retry execution with error classification ---
  EXEC_SUCCESS=false
  RETRY_COUNT=0
  LAST_EXIT_CODE=0
  while [[ "${RETRY_COUNT}" -lt "${RETRY_LIMIT}" ]]; do
    LAST_EXIT_CODE=0
    # EXEC_CMD is trusted operator-authored shell configuration, never model output.
    run_with_budget "${EFFECTIVE_TIMEOUT}" bash -c "${EXEC_CMD}" 2>&1 | tee -a "${LOOP_DIR}/runner.log" || LAST_EXIT_CODE=$?
    if loop_timeout_reached; then
      echo "[TIMEOUT] LOOP_TIMEOUT=${LOOP_TIMEOUT}s exceeded during executor" | tee -a "${LOOP_DIR}/runner.log"
      STATUS="BLOCKED"; write_terminal_state BLOCKED; break 2
    fi

    if [[ "${LAST_EXIT_CODE}" -eq 0 ]]; then
      EXEC_SUCCESS=true
      record_circuit_success
      emit_log "INFO" "exec_success" "attempt" "$((RETRY_COUNT + 1))"
      break
    fi

    # Error classification: permanent errors skip retry
    ERROR_SIG="exit_${LAST_EXIT_CODE}"
    case "${LAST_EXIT_CODE}" in
      126|127) # permission denied / command not found
        emit_log "ERROR" "permanent_failure" "exit_code" "${LAST_EXIT_CODE}" "category" "PERMANENT"
        record_circuit_failure "${ERROR_SIG}"
        break
        ;;
    esac

    RETRY_COUNT=$((RETRY_COUNT + 1))
    record_circuit_failure "${ERROR_SIG}"
    emit_log "WARN" "exec_retry" "attempt" "${RETRY_COUNT}" "exit_code" "${LAST_EXIT_CODE}" "category" "TRANSIENT"
    # Opening the circuit also stops this retry loop, including a failed probe.
    if [[ "${CIRCUIT_BREAKER}" == "true" && "${CB_STATE}" == "OPEN" ]]; then
      echo "[CIRCUIT:OPEN] Execution blocked until cooldown or manual reset"
      break
    fi

    if [[ "${RETRY_COUNT}" -lt "${RETRY_LIMIT}" ]]; then
      JITTER=$((RANDOM % (RETRY_BACKOFF_BASE ** RETRY_COUNT / 2 + 1)))
      BACKOFF=$((RETRY_BACKOFF_BASE ** RETRY_COUNT + JITTER))
      echo "[RETRY] Attempt ${RETRY_COUNT}/${RETRY_LIMIT} failed (exit=${LAST_EXIT_CODE}) — waiting ${BACKOFF}s"
      BACKOFF_EXIT=0
      run_with_budget 0 sleep "${BACKOFF}" || BACKOFF_EXIT=$?
      if [[ "${BACKOFF_EXIT}" -ne 0 ]] || loop_timeout_reached; then
        echo "[TIMEOUT] LOOP_TIMEOUT=${LOOP_TIMEOUT}s exhausted during retry delay" | tee -a "${LOOP_DIR}/runner.log"
        STATUS="BLOCKED"; write_terminal_state BLOCKED; break 2
      fi
    fi
  done

  if [[ "${EXEC_SUCCESS}" != "true" ]]; then
    echo "[BLOCKED] EXEC_CMD failed after ${RETRY_LIMIT} retries (TOOL_FAILURE)" | tee -a "${LOOP_DIR}/runner.log"
    {
      echo ""
      echo "## Iteration ${ITER} — BLOCKED"
      echo "- TOOL_FAILURE: ${EXEC_CMD} failed after ${RETRY_LIMIT} retries"
      echo "- Timestamp: $(date -u +"%Y-%m-%dT%H:%M:%SZ")"
    } >> "${LOOP_DIR}/progress.md"
    STATUS="BLOCKED"
    # Atomic state write before break (keep same iteration for retry)
    write_state "${ITER}" "BLOCKED"
    break
  fi

  #--- Verification gate ---
  VERIFY_RESULT="SKIP"
  if [[ -f "${LOOP_DIR}/verify.sh" ]]; then
    if run_with_budget 0 bash "${LOOP_DIR}/verify.sh"; then
      VERIFY_RESULT="PASS"
    else
      VERIFY_RESULT="FAIL"
    fi
  fi

  # Recheck after executor/verification, including the final iteration: neither
  # goal mutation nor newly emitted cost may bypass a gate by creating done.md.
  if ! check_goal_immutable; then
    echo "[ABORT] goal.md changed mid-run (GOAL_DRIFT / AP-16)" | tee -a "${LOOP_DIR}/runner.log"
    STATUS="BLOCKED"; write_terminal_state BLOCKED; break
  fi
  if BUDGET_MSG=$(budget_exceeded); then
    echo "[ABORT] ${BUDGET_MSG}" | tee -a "${LOOP_DIR}/runner.log"
    STATUS="BLOCKED"; write_terminal_state BLOCKED; break
  fi
  if [[ "${LOOP_DEADLINE}" -gt 0 ]] && [[ "$(date +%s)" -ge "${LOOP_DEADLINE}" ]]; then
    echo "[TIMEOUT] LOOP_TIMEOUT=${LOOP_TIMEOUT}s exceeded" | tee -a "${LOOP_DIR}/runner.log"
    STATUS="BLOCKED"; write_terminal_state BLOCKED; break
  fi

  #--- Scoped auto-commit ---
  if [[ "${AUTOCOMMIT}" == "true" ]]; then
    {
      git -C "${REPO_ROOT}" diff --name-only -z -- 2>/dev/null || true
      git -C "${REPO_ROOT}" diff --cached --name-only -z -- 2>/dev/null || true
      git -C "${REPO_ROOT}" ls-files --others --exclude-standard -z 2>/dev/null || true
    } > "${LOOP_DIR}/current-changes.nul"
    CANDIDATES=()
    while IFS= read -r -d '' path; do
      # Runtime files must never enter a source commit, even without .gitignore.
      [[ "${REPO_ROOT}/${path}" == "${LOOP_DIR}/"* ]] && continue
      BASELINE_PATH=false
      while IFS= read -r -d '' baseline; do
        if [[ "${path}" == "${baseline}" ]]; then BASELINE_PATH=true; break; fi
      done < "${LOOP_DIR}/dirty-start-paths.nul"
      if [[ "${BASELINE_PATH}" != "true" ]]; then
        CANDIDATES+=("${path}")
      fi
    done < "${LOOP_DIR}/current-changes.nul"
    rm -f "${LOOP_DIR}/current-changes.nul"
    if [[ "${#CANDIDATES[@]}" -gt 0 ]]; then
      git -C "${REPO_ROOT}" --literal-pathspecs add --all -- "${CANDIDATES[@]}"
      if ! git -C "${REPO_ROOT}" --literal-pathspecs diff --cached --quiet -- "${CANDIDATES[@]}"; then
        # --only leaves pre-existing staged work in the index, outside this commit.
        git -C "${REPO_ROOT}" --literal-pathspecs commit --only -m "${COMMIT_MSG_PREFIX}(iter-${ITER}): auto-commit [verify=${VERIFY_RESULT}]" -- "${CANDIDATES[@]}"
        COMMIT_HASH=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
      fi
    fi
  fi

  #--- DONE detection (triple gate: done.md + verify + placeholder-clean) ---
  if [[ -f "${LOOP_DIR}/done.md" ]]; then
    if [[ "${VERIFY_RESULT}" == "PASS" || "${VERIFY_RESULT}" == "SKIP" ]]; then
      if placeholder_clean; then
        STATUS="DONE"
      else
        STATUS="CONTINUE"
        echo "[INFO] done.md + verify=${VERIFY_RESULT} but placeholders found in changed src — continuing (AP-12)"
        emit_log "WARN" "placeholder_block" "verify" "${VERIFY_RESULT}"
      fi
    else
      STATUS="CONTINUE"
      echo "[INFO] done.md exists but verification failed — continuing"
    fi
  else
    STATUS="CONTINUE"
  fi

  #--- Record action signature for convergence detection ---
  record_signature "${VERIFY_RESULT}"

  #--- Atomic state write ---
  NEXT_ITER=$((ITER + 1))
  write_state "${NEXT_ITER}" "${STATUS}"

  #--- Iteration notification (|| true — never fatal) ---
  ITER_END=$(date +%s)
  ITER_DURATION=$((ITER_END - ITER_START))
  echo "${ITER_DURATION}" >> "${LOOP_DIR}/.iter-timings.log"
  if [[ "${NOTIFY_ENABLED}" == "true" ]] && [[ -f "${LOOP_DIR}/notify.sh" ]]; then
    bash "${LOOP_DIR}/notify.sh" "${ITER}" "${STATUS}" "${VERIFY_RESULT}" "${ITER_DURATION}" "${LOOP_DIR}" "${COMMIT_HASH}" || true
  fi

  emit_log "INFO" "iteration_complete" \
    "status" "${STATUS}" "verify" "${VERIFY_RESULT}" \
    "commit" "${COMMIT_HASH}" "duration" "${ITER_DURATION}" \
    "retries" "${RETRY_COUNT}" "exit_code" "${LAST_EXIT_CODE}"

  echo "[ITER ${ITER}] status=${STATUS} verify=${VERIFY_RESULT} commit=${COMMIT_HASH} duration=${ITER_DURATION}s"
  ITER=${NEXT_ITER}
done

#--- Branch isolation (post-loop squash) ---
squash_iteration_branch() {
  # Empty loops and changes reverted during the loop have nothing to summarize.
  if git diff --quiet "${ORIGIN_BRANCH}" "${ITER_BRANCH}" --; then
    git checkout "${ORIGIN_BRANCH}"
    git branch -D "${ITER_BRANCH}"
    echo "[BRANCH] No source changes to squash — returned to ${ORIGIN_BRANCH}"
    return 0
  fi

  # Preserve prior summaries: a repeated loop name must not delete user commits.
  if git show-ref --verify --quiet "refs/heads/${SUMMARY_BRANCH}"; then
    echo "[ABORT] Summary branch ${SUMMARY_BRANCH} already exists — choose another loop name"
    return 1
  fi

  # Scoped iteration commits leave prior staged work untouched. Keep that work
  # out of the squash index too, then restore its original staged/unstaged state.
  local stashed=false
  if ! git diff --quiet || ! git diff --cached --quiet; then
    git stash push -m "orbit-pre-squash"
    stashed=true
  fi

  ITER_COMMIT_COUNT=$(git rev-list --count "${ORIGIN_BRANCH}..${ITER_BRANCH}")
  echo "[BRANCH] Loop DONE — squashing ${ITER_COMMIT_COUNT} iteration commits"
  git checkout "${ORIGIN_BRANCH}"
  git checkout -b "${SUMMARY_BRANCH}"

  # Squash merge with conflict handling
  if git merge --squash "${ITER_BRANCH}"; then

    #--- LLM-generated commit message (notify.sh pattern) ---
    LOOP_NAME=$(basename "${LOOP_DIR}" | sed 's/^\.//')
    DIFF_STAT=$(git diff --cached --stat 2>/dev/null | tail -20)
    GOAL_CONTENT=$(head -30 "${LOOP_DIR}/goal.md" 2>/dev/null || echo "")
    DONE_CONTENT=$(head -20 "${LOOP_DIR}/done.md" 2>/dev/null || echo "")

    SQUASH_PROMPT="以下の情報を元に、conventional commit形式(type(scope): description)のコミットメッセージを生成してください。
typeはfeat/fix/refactor/test/docs/chore/perfから適切なものを選択。scopeは「${LOOP_NAME}」。
本文(body)は変更内容を簡潔に説明。日本語OK。

## Goal
${GOAL_CONTENT}

## Done
${DONE_CONTENT}

## Diff Summary (${ITER_COMMIT_COUNT} commits squashed)
${DIFF_STAT}

## Iterations: $((ITER - 1)), Verify: ${VERIFY_RESULT}

コミットメッセージのみを出力してください(他の説明不要):"

    SQUASH_MSG=""

    # Optional text generation is bounded and uses supported capture channels.
    # agy needs real pty + artifact/sentinel capture; do not launch its interactive
    # pipe mode merely to generate a commit message (_common/CLI_COMPATIBILITY.md §9.2).
    if [[ "${SQUASH_MSG_ENGINE}" == "agy" ]]; then
      echo "[BRANCH] agy text capture requires a dedicated wrapper — using heuristic"
    fi
    SQUASH_MSG_FILE=$(mktemp "${LOOP_DIR}/squash-message.XXXXXX")
    if [[ "${SQUASH_MSG_ENGINE}" == "auto" || "${SQUASH_MSG_ENGINE}" == "claude" ]]; then
      if command -v claude >/dev/null 2>&1; then
        if run_with_budget "${TOOL_TIMEOUT}" claude -p "${SQUASH_PROMPT}" --max-turns 1 > "${SQUASH_MSG_FILE}" 2>/dev/null; then
          SQUASH_MSG=$(cat "${SQUASH_MSG_FILE}")
        fi
      fi
    fi
    if [[ -z "${SQUASH_MSG}" ]] && [[ "${SQUASH_MSG_ENGINE}" == "auto" || "${SQUASH_MSG_ENGINE}" == "codex" ]]; then
      if command -v codex >/dev/null 2>&1; then
        : > "${SQUASH_MSG_FILE}"
        if run_with_budget "${TOOL_TIMEOUT}" codex exec --full-auto -o "${SQUASH_MSG_FILE}" "${SQUASH_PROMPT}" >/dev/null 2>&1; then
          [[ ! -s "${SQUASH_MSG_FILE}" ]] || SQUASH_MSG=$(cat "${SQUASH_MSG_FILE}")
        fi
      fi
    fi
    rm -f "${SQUASH_MSG_FILE}"

    # Heuristic fallback when no LLM available
    if [[ -z "${SQUASH_MSG}" ]]; then
      GOAL_OBJECTIVE=$(sed -n '/^## Objective/,/^##/{/^##/d;/^$/d;p;}' "${LOOP_DIR}/goal.md" 2>/dev/null | head -1)
      SQUASH_MSG="feat(${LOOP_NAME}): ${GOAL_OBJECTIVE:-loop completion}

Squashed from ${ITER_COMMIT_COUNT} iteration commits.
Iterations: $((ITER - 1)), Verify: ${VERIFY_RESULT}"
      echo "[BRANCH] LLM unavailable — using heuristic commit message"
    fi

    git commit -m "${SQUASH_MSG}"

    if [[ "${stashed}" == "true" ]]; then
      git stash pop --index || { echo "[ABORT] Stash restore conflict — resolve before resuming"; return 1; }
    fi

    # Delete iteration branch
    git branch -D "${ITER_BRANCH}" 2>/dev/null || true
    echo "[BRANCH] Squash complete on ${SUMMARY_BRANCH}"

    # Granularity hint for large loops
    if [[ "${ITER_COMMIT_COUNT}" -gt 10 ]]; then
      echo "[BRANCH:HINT] ${ITER_COMMIT_COUNT} commits squashed. For finer granularity:"
      echo "  git reset --soft ${ORIGIN_BRANCH} && create topic-based commits"
    fi
  else
    echo "[BRANCH:CONFLICT] Squash failed — ORIGIN_BRANCH may have diverged"
    echo "[BRANCH:CONFLICT] Resolve: git checkout ${SUMMARY_BRANCH} && fix conflicts && git commit"
    echo "[BRANCH:CONFLICT] Or abort: git reset --merge && git checkout ${ITER_BRANCH}"
    if [[ "${stashed}" == "true" ]]; then
      echo "[BRANCH:CONFLICT] After resolving or aborting, restore prior work: git stash pop --index"
    fi
    return 1
  fi
}

if [[ "${BRANCH_ISOLATION}" == "true" ]] && [[ "${AUTOCOMMIT}" == "true" ]] \
   && [[ -n "${ORIGIN_BRANCH:-}" ]] && [[ "${STATUS}" == "DONE" ]] \
   && [[ "${SQUASH_ON_DONE}" == "true" ]] \
   && git show-ref --verify --quiet "refs/heads/${ITER_BRANCH}"; then
  squash_iteration_branch
elif [[ "${BRANCH_ISOLATION}" == "true" ]] && [[ "${STATUS}" != "DONE" ]] && [[ -n "${ITER_BRANCH:-}" ]]; then
  echo "[BRANCH] STATUS=${STATUS} — staying on ${ITER_BRANCH} for resume"
fi

#--- Release lock ---
rm -f "${LOOP_DIR}/.run-loop.lock"

#--- Status footer ---
FINAL_STATUS="${STATUS}"
if [[ "${FINAL_STATUS}" != "DONE" ]]; then
  FINAL_STATUS="CONTINUE"
fi
emit_log "INFO" "loop_complete" "final_status" "${FINAL_STATUS}" "iterations" "$((ITER - 1))" "max" "${MAX_ITERATIONS}"

echo ""
echo "NEXUS_LOOP_STATUS: ${FINAL_STATUS}"
echo "NEXUS_LOOP_SUMMARY: Iteration ${ITER}/${MAX_ITERATIONS}, status=${STATUS}, verify=${VERIFY_RESULT}"

Source: SKILL.md on GitHub

1 alert13d5 checks · Risk SAFE
  • Gen Agent Trust Hub13d

    The orbit skill is a comprehensive framework for engineering and managing autonomous agent loops. It generates and audits shell scripts designed to execute tasks via various AI engines (Codex, Claude, Gemini). While the skill enables high-autonomy behaviors—including arbitrary command execution and bypassing tool permissions—it incorporates extensive safety controls such as budget caps, wall-clock timeouts, circuit breakers, and mandatory independent critic reviews to mitigate potential risks.

  • Socket13d

    2 alerts: gptAnomaly

  • Snyk13d

    Risk: LOW · No issues

  • Runlayer6mo

    5/11 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 35ffd55. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Activeupdated 2 weeks ago

README badge

README badge for simota/agent-skills/orbit