#!/bin/bash
# pass-to-chat.sh : hand one self-contained brief to ChatGPT's Codex CLI, archive the
# whole run, and leave a result file for Claude to review.
#
# Free from the AI Open House library: https://aiopenhouse.co/guests/#library
# Use it, change it, ship it. Creative Commons Attribution 4.0.
#
# USAGE: pass-to-chat.sh <brief-file> [slug] [timeout-minutes]
#   brief-file : a self-contained Markdown brief (the worker sees ONLY this file)
#   slug       : name for the work directory (default: the brief's filename)
#   timeout    : watchdog minutes (default 30)
#
# THE GOTCHA: `codex exec` inherits stdin and hangs forever with no terminal
# attached. Every invocation MUST redirect stdin from /dev/null.
#
# Sign Codex in with your SUBSCRIPTION (`codex login`), not an API key: an API key
# bills per token for work your monthly plan already covers.

set -uo pipefail
export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"
VERSION="1.0.0"

BRIEF="${1:-}"
[ -z "$BRIEF" ] && { echo "usage: pass-to-chat.sh <brief-file> [slug] [timeout-minutes]"; exit 2; }
[ -f "$BRIEF" ] || { echo "FAIL: brief not found: $BRIEF"; exit 2; }
BRIEF="$(cd "$(dirname "$BRIEF")" && pwd)/$(basename "$BRIEF")"

SLUG="${2:-$(basename "$BRIEF" .md)}"
TIMEOUT_MIN="${3:-30}"
BASE="${CHAT_WORKER_HOME:-$HOME/chat-worker}"
WORK="$BASE/$SLUG"
ARCHIVE="$BASE/archive/$(date +%F)-$SLUG"
LEDGER="$BASE/LEDGER.md"
RESULT="$(dirname "$BRIEF")/RESULT-$SLUG.md"
TS() { date "+%a %Y-%m-%d %I:%M:%S %p %Z"; }

# Auth gate: subscription login, never an API key.
if [ ! -f "$HOME/.codex/auth.json" ]; then
  echo "FAIL: Codex is not signed in. Run: codex login"
  exit 3
fi

mkdir -p "$WORK" "$BASE/archive"
cp "$BRIEF" "$WORK/BRIEF.md"
LOG="$WORK/codex-run.log"
echo "$(TS) pass-to-chat v$VERSION start: $SLUG (timeout ${TIMEOUT_MIN}m)"
START=$(date +%s)

PROMPT="Read BRIEF.md in the current directory and execute it fully. Work only inside this directory. When done, write a short WORKER-NOTES.md covering what you did, anything you could not do, and any assumption you made."

cd "$WORK" || exit 1
codex exec --skip-git-repo-check --sandbox workspace-write "$PROMPT" </dev/null >"$LOG" 2>&1 &
PID=$!

# Watchdog: a hung run dies instead of hanging all night.
HALF_MIN=0
while kill -0 "$PID" 2>/dev/null; do
  sleep 30; HALF_MIN=$((HALF_MIN+1))
  if [ "$((HALF_MIN/2))" -ge "$TIMEOUT_MIN" ]; then
    echo "$(TS) watchdog kill at ${TIMEOUT_MIN}m"
    kill "$PID" 2>/dev/null; sleep 3; kill -9 "$PID" 2>/dev/null; break
  fi
done
wait "$PID" 2>/dev/null; RC=$?
ELAPSED=$(( $(date +%s) - START ))
MMSS="$((ELAPSED/60))m$((ELAPSED%60))s"

# A throttle is a WAIT, not a bug: the fix is "run it later", not "debug it".
THROTTLED="no"
grep -qiE 'rate limit|rate_limit|quota|usage limit|too many requests|429' "$LOG" 2>/dev/null && THROTTLED="YES"

STATUS="OK"
[ "$RC" -ne 0 ] && STATUS="FAILED (exit $RC)"
[ "$THROTTLED" = "YES" ] && STATUS="THROTTLED (plan limit hit)"

# Permanent archive, so nothing you asked or got back lives only in a vendor's web UI.
mkdir -p "$ARCHIVE"
cp -R "$WORK/." "$ARCHIVE/" 2>/dev/null

{
  echo "# Chat worker result: $SLUG"
  echo
  echo "Ran $(TS) | status: $STATUS | wall time: $MMSS"
  echo "Brief: $BRIEF"
  echo "Work dir: $WORK"
  echo "Archive (permanent): $ARCHIVE"
  [ "$THROTTLED" = "YES" ] && { echo; echo "**THROTTLED: the plan limit was hit. Re-run later or route this one to the other model.**"; }
  echo
  echo "## Files produced"
  echo '```'
  (cd "$WORK" && ls -la | tail -n +2)
  echo '```'
  echo
  echo "## Worker notes"
  if [ -f "$WORK/WORKER-NOTES.md" ]; then cat "$WORK/WORKER-NOTES.md"; else echo "(none written)"; fi
  echo
  echo "## Last 30 lines of the run log"
  echo '```'
  tail -30 "$LOG"
  echo '```'
  echo
  echo "REVIEW REQUIRED: read this, verify it independently rather than trusting the"
  echo "worker's own notes, and state one verdict line (agree / disagree / merged)."
} > "$RESULT"

[ -f "$LEDGER" ] || printf '# Chat worker ledger\n\n| Ran | Slug | Wall | Status |\n|-----|------|------|--------|\n' > "$LEDGER"
printf '| %s | %s | %s | %s |\n' "$(TS)" "$SLUG" "$MMSS" "$STATUS" >> "$LEDGER"

echo "$(TS) done: $STATUS ($MMSS)"
echo "result:  $RESULT"
echo "archive: $ARCHIVE"
[ "$STATUS" = "OK" ] || exit 1
