#!/usr/bin/env bash
# agent-dispatch.sh — Generate a lane-aware prompt for any agent
#
# Usage: agent-dispatch.sh <agent_name> <issue_num> <repo>
#   agent-dispatch.sh groq 42 Timmy_Foundation/the-nexus
#
# Outputs a prompt to stdout. Copy-paste into the agent's interface.
# The prompt includes issue context, repo setup, lane coaching, and
# a short review checklist so dispatch itself teaches the right habits.

set -euo pipefail

AGENT_NAME="${1:?Usage: agent-dispatch.sh <agent> <issue_num> <owner/repo>}"
ISSUE_NUM="${2:?Usage: agent-dispatch.sh <agent> <issue_num> <owner/repo>}"
REPO="${3:?Usage: agent-dispatch.sh <agent> <issue_num> <owner/repo>}"

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LANES_FILE="${SCRIPT_DIR%/bin}/playbooks/agent-lanes.json"

resolve_gitea_url() {
  if [ -n "${GITEA_URL:-}" ]; then
    printf '%s\n' "${GITEA_URL%/}"
    return 0
  fi
  if [ -f "$HOME/.hermes/gitea_api" ]; then
    python3 - "$HOME/.hermes/gitea_api" <<'PY'
from pathlib import Path
import sys

raw = Path(sys.argv[1]).read_text().strip().rstrip("/")
print(raw[:-7] if raw.endswith("/api/v1") else raw)
PY
    return 0
  fi
  if [ -f "$HOME/.config/gitea/base-url" ]; then
    tr -d '[:space:]' < "$HOME/.config/gitea/base-url"
    return 0
  fi
  echo "ERROR: set GITEA_URL or create ~/.hermes/gitea_api" >&2
  return 1
}

GITEA_URL="$(resolve_gitea_url)"

resolve_token_file() {
  local agent="$1"
  local normalized
  normalized="$(printf '%s' "$agent" | tr '[:upper:]' '[:lower:]')"
  for candidate in \
    "$HOME/.hermes/${agent}_token" \
    "$HOME/.hermes/${normalized}_token" \
    "$HOME/.config/gitea/${agent}-token" \
    "$HOME/.config/gitea/${normalized}-token"; do
    if [ -f "$candidate" ]; then
      printf '%s\n' "$candidate"
      return 0
    fi
  done
  for candidate in \
    "$HOME/.config/gitea/timmy-token" \
    "$HOME/.hermes/gitea_token_vps" \
    "$HOME/.hermes/gitea_token_timmy"; do
    if [ -f "$candidate" ]; then
      printf '%s\n' "$candidate"
      return 0
    fi
  done
  return 1
}

TOKEN_FILE="$(resolve_token_file "$AGENT_NAME" || true)"
if [ -z "${TOKEN_FILE:-}" ]; then
  echo "ERROR: No token found for '$AGENT_NAME'." >&2
  echo "Expected one of ~/.hermes/<agent>_token or ~/.config/gitea/<agent>-token" >&2
  exit 1
fi

GITEA_TOKEN="$(cat "$TOKEN_FILE")"
REPO_OWNER="${REPO%%/*}"
REPO_NAME="${REPO##*/}"
BRANCH="${AGENT_NAME}/issue-${ISSUE_NUM}"

python3 - "$LANES_FILE" "$AGENT_NAME" "$ISSUE_NUM" "$REPO" "$REPO_OWNER" "$REPO_NAME" "$BRANCH" "$GITEA_URL" "$GITEA_TOKEN" "$TOKEN_FILE" <<'PY'
import json
import sys
import textwrap
import urllib.error
import urllib.request

lanes_path, agent, issue_num, repo, repo_owner, repo_name, branch, gitea_url, token, token_file = sys.argv[1:]

with open(lanes_path) as f:
    lanes = json.load(f)

lane = lanes.get(agent, {
    "lane": "bounded work with explicit verification and a clean PR handoff",
    "skills_to_practice": ["verification", "scope control", "clear handoff writing"],
    "missing_skills": ["escalate instead of guessing when the scope becomes unclear"],
    "anti_lane": ["self-directed backlog growth", "unbounded architectural wandering"],
    "review_checklist": [
        "Did I stay within scope?",
        "Did I verify the result?",
        "Did I leave a clean PR and issue handoff?"
    ],
})

headers = {"Authorization": f"token {token}"}

def fetch_json(path):
    req = urllib.request.Request(f"{gitea_url}/api/v1{path}", headers=headers)
    with urllib.request.urlopen(req, timeout=10) as resp:
        return json.loads(resp.read().decode())

try:
    issue = fetch_json(f"/repos/{repo}/issues/{issue_num}")
    comments = fetch_json(f"/repos/{repo}/issues/{issue_num}/comments")
except urllib.error.HTTPError as exc:
    raise SystemExit(f"Failed to fetch issue context: {exc}") from exc

body = (issue.get("body") or "").strip()
body = body[:4000] + ("\n...[truncated]" if len(body) > 4000 else "")
recent_comments = comments[-3:]
comment_block = []
for c in recent_comments:
    author = c.get("user", {}).get("login", "unknown")
    text = (c.get("body") or "").strip().replace("\r", "")
    text = text[:600] + ("\n...[truncated]" if len(text) > 600 else "")
    comment_block.append(f"- {author}: {text}")

comment_text = "\n".join(comment_block) if comment_block else "- (no comments yet)"

skills = "\n".join(f"- {item}" for item in lane["skills_to_practice"])
gaps = "\n".join(f"- {item}" for item in lane["missing_skills"])
anti_lane = "\n".join(f"- {item}" for item in lane["anti_lane"])
review = "\n".join(f"- {item}" for item in lane["review_checklist"])

prompt = f"""You are {agent}, working on {repo_name} for Timmy Foundation.

YOUR ISSUE: #{issue_num} — "{issue.get('title', f'Issue #{issue_num}')}"

REPO: {repo}
GITEA API: {gitea_url}/api/v1
GITEA TOKEN FILE: {token_file}
WORK BRANCH: {branch}

LANE:
{lane['lane']}

SKILLS TO PRACTICE ON THIS ASSIGNMENT:
{skills}

COMMON FAILURE MODE TO AVOID:
{gaps}

ANTI-LANE:
{anti_lane}

ISSUE BODY:
{body or "(empty issue body)"}

RECENT COMMENTS:
{comment_text}

WORKFLOW:
1. Read the issue body and recent comments carefully before touching code.
2. Clone the repo into /tmp/{agent}-work-{issue_num}.
3. Check whether {branch} already exists on origin; reuse it if it does.
4. Read the repo docs and follow its own tooling and conventions.
5. Do only the scoped work from the issue. If the task grows, stop and comment instead of freelancing expansion.
6. Run the repo's real verification commands.
7. Open a PR and summarize:
   - what changed
   - how you verified it
   - any remaining risk or follow-up
8. Comment on the issue with the PR link and the same concise summary.

GIT / API SETUP:
export GITEA_URL="{gitea_url}"
export GITEA_TOKEN_FILE="{token_file}"
export GITEA_TOKEN="$(tr -d '[:space:]' < "$GITEA_TOKEN_FILE")"
git config --global http."$GITEA_URL/".extraHeader "Authorization: token $GITEA_TOKEN"
git clone "$GITEA_URL/{repo}.git" /tmp/{agent}-work-{issue_num}
cd /tmp/{agent}-work-{issue_num}
git ls-remote --exit-code origin {branch} >/dev/null 2>&1 && git fetch origin {branch} && git checkout {branch} || git checkout -b {branch}

ISSUE FETCH COMMANDS:
curl -s -H "Authorization: token $GITEA_TOKEN" "{gitea_url}/api/v1/repos/{repo}/issues/{issue_num}"
curl -s -H "Authorization: token $GITEA_TOKEN" "{gitea_url}/api/v1/repos/{repo}/issues/{issue_num}/comments"

PR CREATION TEMPLATE:
curl -s -X POST "{gitea_url}/api/v1/repos/{repo}/pulls" \\
  -H "Authorization: token $GITEA_TOKEN" \\
  -H "Content-Type: application/json" \\
  -d '{{"title":"[{agent}] <description> (#{issue_num})","body":"Fixes #{issue_num}\\n\\n## Summary\\n- <change>\\n\\n## Verification\\n- <command/output>\\n\\n## Risks\\n- <if any>","head":"{branch}","base":"main"}}'

ISSUE COMMENT TEMPLATE:
curl -s -X POST "{gitea_url}/api/v1/repos/{repo}/issues/{issue_num}/comments" \\
  -H "Authorization: token $GITEA_TOKEN" \\
  -H "Content-Type: application/json" \\
  -d '{{"body":"PR submitted.\\n\\nSummary:\\n- <change>\\n\\nVerification:\\n- <command/output>\\n\\nRisks:\\n- <if any>"}}'

REVIEW CHECKLIST BEFORE YOU PUSH:
{review}

COMMIT DISCIPLINE (CRITICAL):
- Commit every 3-5 tool calls. Do NOT wait until the end.
- After every meaningful file change: git add -A && git commit -m "WIP: <what changed>"
- Before running any destructive command: commit current state first.
- If you are unsure whether to commit: commit. WIP commits are safe. Lost work is not.
- Never use --no-verify.
- The auto-commit-guard is your safety net, but do not rely on it. Commit proactively.

RECOVERY COMMANDS (if interrupted, another agent can resume):
git log --oneline -10          # see your WIP commits
git diff HEAD~1                # see what the last commit changed
git status                     # see uncommitted work

RULES:
- Do not skip hooks with --no-verify.
- Do not silently widen the scope.
- If verification fails twice or the issue is underspecified, stop and comment with what blocked you.
- Always create a PR instead of pushing to main.
- Clean up /tmp/{agent}-work-{issue_num} when done.
"""

print(textwrap.dedent(prompt).strip())
PY
