#!/usr/bin/env bash
# Behavioral checks for the autonomy supervisor build pipeline.
set -uo pipefail

HERE="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "$HERE/../../../.." && pwd)"
SUPERVISOR="$REPO_ROOT/recoil/pipeline/tools/autonomy/supervisor.sh"

PASS=0
FAIL=0

ok() {
  echo "  OK: $1"
  PASS=$((PASS + 1))
}

no() {
  echo "  FAIL: $1"
  FAIL=$((FAIL + 1))
}

SBX="$(mktemp -d)"
cleanup() {
  rm -rf "$SBX"
}
trap cleanup EXIT

export HOME="$SBX/home"
export PYTHONPATH="$REPO_ROOT${PYTHONPATH:+:$PYTHONPATH}"
export PATH="$SBX/bin:$PATH"
export AUTONOMY_EVENTS_LEDGER="$SBX/events.jsonl"
export AUTONOMY_HARNESS="$SBX/bin/harness_orchestrator.sh"
export AUTONOMY_SUPERVISOR_ISSUE_BODY="Implement the test issue body without exposing lin_api_SECRET."
export AUTONOMY_SPEC_GEN_TIMEOUT_SECONDS=5
export CLAUDE_CALLS="$SBX/claude.calls"
export HARNESS_CALLS="$SBX/harness.calls"
export GH_CALLS="$SBX/gh.calls"

mkdir -p "$SBX/bin" "$HOME/Code/recoil-sessions"

cat > "$SBX/bin/claude" <<'STUB'
#!/usr/bin/env bash
printf '%s\n' "$*" >> "$CLAUDE_CALLS"
case "${CLAUDE_MODE:-ok}" in
  fail)
    echo "spec failed with lin_api_SECRET" >&2
    exit 42
    ;;
  empty)
    exit 0
    ;;
  *)
    printf '# BUILD_SPEC\n\n## Phase 0\nIssue body captured.\n'
    ;;
esac
STUB
chmod +x "$SBX/bin/claude"

cat > "$SBX/bin/harness_orchestrator.sh" <<'STUB'
#!/usr/bin/env bash
printf '%s\n' "$*" >> "$HARNESS_CALLS"
log=""
while [ "$#" -gt 0 ]; do
  case "$1" in
    --log)
      log="${2:-}"
      shift 2
      ;;
    *)
      shift
      ;;
  esac
done
[ -n "$log" ] && printf '%s\n' "${HARNESS_LOG_TEXT:-## Phase Harness}" >> "$log"
exit "${HARNESS_STATUS:-0}"
STUB
chmod +x "$SBX/bin/harness_orchestrator.sh"

cat > "$SBX/bin/gh" <<'STUB'
#!/usr/bin/env bash
printf '%s\n' "$*" >> "$GH_CALLS"
if [ -n "${GH_URL:-}" ]; then
  printf '%s\n' "$GH_URL"
fi
STUB
chmod +x "$SBX/bin/gh"

reset_case() {
  rm -rf "$HOME/.local/state/studio-autonomy"
  rm -f "$AUTONOMY_EVENTS_LEDGER" "$CLAUDE_CALLS" "$HARNESS_CALLS" "$GH_CALLS"
  unset CLAUDE_MODE HARNESS_STATUS HARNESS_LOG_TEXT GH_URL
}

make_worktree() {
  local run_id="$1"
  local worktree="$HOME/Code/recoil-sessions/$run_id"
  mkdir -p "$worktree"
  git -C "$worktree" init -q
  git -C "$worktree" config user.email "autonomy-test@example.com"
  git -C "$worktree" config user.name "Autonomy Test"
  printf 'test\n' > "$worktree/README.md"
  git -C "$worktree" add README.md
  git -C "$worktree" commit -q -m init
  git -C "$worktree" checkout -q -b "autonomy/$run_id"
  mkdir -p "$worktree/recoil/pipeline/tools"
  printf '%s\n' "$worktree"
}

seed_claim() {
  local issue_id="$1"
  local identifier="$2"
  local run_id="$3"
  python3 - "$issue_id" "$identifier" "$run_id" <<'PY'
import sys
from recoil.pipeline.tools.autonomy import claim_ledger, constants

claim_ledger.claim(sys.argv[1], sys.argv[2], sys.argv[3], constants.current_night_id())
PY
}

run_supervisor() {
  local run_id="$1"
  local issue="$2"
  local worktree="$3"
  shift 3
  bash "$SUPERVISOR" --run-id "$run_id" --issue "$issue" --worktree "$worktree" "$@" >/dev/null 2>&1
}

event_exists() {
  local event_name="$1"
  local run_id="$2"
  local key="${3:-}"
  local value="${4:-}"
  python3 - "$AUTONOMY_EVENTS_LEDGER" "$event_name" "$run_id" "$key" "$value" <<'PY'
import json
import sys
from pathlib import Path

ledger = Path(sys.argv[1])
event_name, run_id, key, value = sys.argv[2:6]
if not ledger.exists():
    raise SystemExit(1)
for line in ledger.read_text(encoding="utf-8").splitlines():
    event = json.loads(line)
    if event.get("event") != f"autonomy.{event_name}":
        continue
    if run_id and event.get("run_id") != run_id:
        continue
    if key and str(event.get(key)) != value:
        continue
    raise SystemExit(0)
raise SystemExit(1)
PY
}

claim_is() {
  local issue_id="$1"
  local run_id="$2"
  local state="$3"
  local signature="${4:-}"
  python3 - "$issue_id" "$run_id" "$state" "$signature" <<'PY'
import json
import sys
from recoil.pipeline.tools.autonomy import claim_ledger

issue_id, run_id, state, signature = sys.argv[1:5]
records = claim_ledger.CLAIM_LEDGER.read_text(encoding="utf-8").splitlines()
for line in reversed(records):
    record = json.loads(line)
    if record.get("issue_id") == issue_id and record.get("run_id") == run_id:
        if record.get("state") != state:
            raise SystemExit(1)
        if signature and record.get("failure_signature") != signature:
            raise SystemExit(1)
        raise SystemExit(0)
raise SystemExit(1)
PY
}

breaker_exists() {
  python3 - <<'PY'
from recoil.pipeline.tools.autonomy import constants, resource_gate

raise SystemExit(0 if resource_gate.breaker_tripped(constants.current_night_id()) else 1)
PY
}

reset_case
RUN="tier0"
ISSUE="TEST-1"
LINEAR_ID="linear-tier0"
WORKTREE="$(make_worktree "$RUN")"
seed_claim "$LINEAR_ID" "$ISSUE" "$RUN"
if run_supervisor "$RUN" "$ISSUE" "$WORKTREE" --shadow tier0; then
  ok "tier0 exits successfully"
else
  no "tier0 exits successfully"
fi
[ ! -f "$CLAUDE_CALLS" ] && ok "tier0 stops before spec generation" || no "tier0 stops before spec generation"
[ ! -f "$HARNESS_CALLS" ] && ok "tier0 does not run harness" || no "tier0 does not run harness"
event_exists "shadow_would_dispatch" "$RUN" && ok "tier0 emits shadow_would_dispatch" || no "tier0 emits shadow_would_dispatch"

reset_case
RUN="tier1"
ISSUE="TEST-2"
LINEAR_ID="linear-tier1"
WORKTREE="$(make_worktree "$RUN")"
seed_claim "$LINEAR_ID" "$ISSUE" "$RUN"
if run_supervisor "$RUN" "$ISSUE" "$WORKTREE" --shadow tier1; then
  ok "tier1 exits successfully"
else
  no "tier1 exits successfully"
fi
[ -s "$WORKTREE/BUILD_SPEC.md" ] && ok "tier1 generates spec" || no "tier1 generates spec"
[ ! -f "$HARNESS_CALLS" ] && ok "tier1 stops before harness" || no "tier1 stops before harness"
event_exists "shadow_would_dispatch" "$RUN" && ok "tier1 emits shadow_would_dispatch" || no "tier1 emits shadow_would_dispatch"

reset_case
RUN="harness-fail"
ISSUE="TEST-3"
LINEAR_ID="linear-harness-fail"
WORKTREE="$(make_worktree "$RUN")"
seed_claim "$LINEAR_ID" "$ISSUE" "$RUN"
export HARNESS_STATUS=17
if run_supervisor "$RUN" "$ISSUE" "$WORKTREE"; then
  no "harness nonzero exits nonzero"
else
  ok "harness nonzero exits nonzero"
fi
event_exists "build_killed" "$RUN" "reason" "harness_failed" && ok "harness nonzero emits build_killed" || no "harness nonzero emits build_killed"
if event_exists "pr_opened" "$RUN"; then
  no "harness nonzero does not emit pr_opened"
else
  ok "harness nonzero does not emit pr_opened"
fi
claim_is "$LINEAR_ID" "$RUN" "failed" "harness_failed" && ok "harness nonzero releases failed" || no "harness nonzero releases failed"

reset_case
RUN="harness-ok-pr"
ISSUE="TEST-4"
LINEAR_ID="linear-harness-ok-pr"
WORKTREE="$(make_worktree "$RUN")"
seed_claim "$LINEAR_ID" "$ISSUE" "$RUN"
export GH_URL="https://github.com/example/repo/pull/123"
if run_supervisor "$RUN" "$ISSUE" "$WORKTREE"; then
  ok "harness success with PR exits zero"
else
  no "harness success with PR exits zero"
fi
event_exists "pr_opened" "$RUN" "pr_url" "$GH_URL" && ok "harness success emits pr_opened" || no "harness success emits pr_opened"
claim_is "$LINEAR_ID" "$RUN" "completed" && ok "harness success releases completed" || no "harness success releases completed"

reset_case
RUN="harness-ok-no-pr"
ISSUE="TEST-5"
LINEAR_ID="linear-harness-ok-no-pr"
WORKTREE="$(make_worktree "$RUN")"
seed_claim "$LINEAR_ID" "$ISSUE" "$RUN"
if run_supervisor "$RUN" "$ISSUE" "$WORKTREE"; then
  no "harness success without PR exits nonzero"
else
  ok "harness success without PR exits nonzero"
fi
event_exists "spec_review_failed" "$RUN" "reason" "pr_lookup" && ok "missing PR emits pr_lookup failure" || no "missing PR emits pr_lookup failure"
claim_is "$LINEAR_ID" "$RUN" "failed" "pr_lookup" && ok "missing PR releases failed" || no "missing PR releases failed"

reset_case
RUN="rate-limit"
ISSUE="TEST-6"
LINEAR_ID="linear-rate-limit"
WORKTREE="$(make_worktree "$RUN")"
seed_claim "$LINEAR_ID" "$ISSUE" "$RUN"
export HARNESS_STATUS=1
export HARNESS_LOG_TEXT="Error: HTTP 429 Too Many Requests"
if run_supervisor "$RUN" "$ISSUE" "$WORKTREE"; then
  no "rate-limited harness exits nonzero"
else
  ok "rate-limited harness exits nonzero"
fi
breaker_exists && ok "rate-limit log trips breaker" || no "rate-limit log trips breaker"
event_exists "rate_limited" "$RUN" && ok "rate-limit log emits rate_limited" || no "rate-limit log emits rate_limited"
event_exists "build_capped" "$RUN" "reason" "rate_limited" && ok "rate-limited harness emits build_capped" || no "rate-limited harness emits build_capped"
claim_is "$LINEAR_ID" "$RUN" "failed" "rate_limited" && ok "rate-limited harness releases failed" || no "rate-limited harness releases failed"

echo "--------"
if [ "$FAIL" -ne 0 ]; then
  echo "AUTONOMY SUPERVISOR PIPELINE: FAIL ($FAIL failed, $PASS passed)"
  exit 1
fi

echo "AUTONOMY SUPERVISOR PIPELINE: PASS ($PASS passed)"
