#!/usr/bin/env bash
# Run a canonical verifier test against a runtime; emit a JSON transcript.
# See fleet/harness/README.md (runtimes, no-self-grading protocol).
set -euo pipefail

usage() {
  cat >&2 <<'EOF'
usage: run-verifier.sh <locate|backlog> <ornith|mlx|mistral> [options]
       run-verifier.sh <locate|backlog> --print-prompt [options]

options:
  --agents-file PATH   AGENTS.md to pin (default: repo-root AGENTS.md)
  --status-file PATH   STATUS.md to pin (required for the backlog test)
  --model ID           model id (required for mlx; optional override for ornith)
  --endpoint URL       OpenAI-style base (default: http://127.0.0.1:18080/v1)
  --out DIR            transcript dir (default: $TMPDIR/harness-runs)
  --print-prompt       print the assembled prompt to stdout and exit
EOF
  exit 2
}

TEST="${1:-}"; shift || usage
case "$TEST" in locate|backlog) ;; *) usage ;; esac

RUNTIME="" PRINT_ONLY=0 MODEL="" ENDPOINT="http://127.0.0.1:18080/v1"
AGENTS_FILE="" STATUS_FILE="" OUT_DIR="${TMPDIR:-/tmp}/harness-runs"
while [ $# -gt 0 ]; do
  case "$1" in
    ornith|mlx|mistral) RUNTIME="$1" ;;
    --print-prompt) PRINT_ONLY=1 ;;
    --agents-file) AGENTS_FILE="$2"; shift ;;
    --status-file) STATUS_FILE="$2"; shift ;;
    --model) MODEL="$2"; shift ;;
    --endpoint) ENDPOINT="$2"; shift ;;
    --out) OUT_DIR="$2"; shift ;;
    *) usage ;;
  esac
  shift
done
[ "$PRINT_ONLY" = 1 ] || [ -n "$RUNTIME" ] || usage

HERE="$(cd "$(dirname "$0")/.." && pwd)"
REPO_ROOT="$(git -C "$HERE" rev-parse --show-toplevel)"
[ -n "$AGENTS_FILE" ] || AGENTS_FILE="$REPO_ROOT/AGENTS.md"
[ -f "$AGENTS_FILE" ] || { echo "missing AGENTS.md: $AGENTS_FILE" >&2; exit 1; }

case "$TEST" in
  locate)
    PROMPT_HEAD="You are in the erp repo; using AGENTS.md alone, state where the atom registry, the class skeletons and the environment rules live."
    ;;
  backlog)
    [ -f "${STATUS_FILE:-}" ] || { echo "backlog test requires --status-file" >&2; exit 1; }
    PROMPT_HEAD="You are a cold reader auditing the Arcodange AI back-office backlog. Using ONLY the two documents below — no other knowledge, no tools — answer:
1. What shipped most recently?
2. What should be worked on next, and why that item?
3. What would you verify before trusting these documents, and in what order?"
    ;;
esac

PROMPT="$PROMPT_HEAD

--- AGENTS.md ---
$(cat "$AGENTS_FILE")"
if [ "$TEST" = backlog ]; then
  PROMPT="$PROMPT

--- STATUS.md ---
$(cat "$STATUS_FILE")"
fi

if [ "$PRINT_ONLY" = 1 ]; then
  printf '%s\n' "$PROMPT"
  exit 0
fi

mkdir -p "$OUT_DIR"
TS="$(date +%Y%m%dT%H%M%S)"
OUT_FILE="$OUT_DIR/${TEST}-${RUNTIME}${MODEL:+-$(basename "$MODEL")}-$TS.json"
START="$(date +%s)"

case "$RUNTIME" in
  ornith|mlx)
    if [ "$RUNTIME" = ornith ]; then MODEL="${MODEL:-leonsarmiento/Ornith-1.0-35B-5bit-mlx}"; fi
    [ -n "$MODEL" ] || { echo "mlx runtime requires --model" >&2; exit 1; }
    RESPONSE="$(PROMPT="$PROMPT" MODEL="$MODEL" python3 - "$ENDPOINT" <<'PY'
import json, os, sys, urllib.request
body = json.dumps({
    "model": os.environ["MODEL"],
    "messages": [{"role": "user", "content": os.environ["PROMPT"]}],
    "temperature": 0,
    "max_tokens": 3000,
}).encode()
req = urllib.request.Request(sys.argv[1].rstrip("/") + "/chat/completions",
                             data=body, headers={"Content-Type": "application/json"})
with urllib.request.urlopen(req, timeout=900) as r:
    print(json.load(r)["choices"][0]["message"]["content"])
PY
)"
    ;;
  mistral)
    # Plain -p, no tool filtering: --enabled-tools with a no-match pattern hangs
    # vibe 2.21.0. --max-turns 1 makes tool use moot for a pure-answer test.
    MODEL="vibe-active-model"
    RESPONSE="$(vibe -p "$PROMPT" --max-turns 1 --output text)"
    ;;
esac

LATENCY=$(( $(date +%s) - START ))
RESPONSE="$RESPONSE" PROMPT="$PROMPT" TEST="$TEST" RUNTIME="$RUNTIME" MODEL="$MODEL" \
ENDPOINT="$ENDPOINT" LATENCY="$LATENCY" TS="$TS" AGENTS_FILE="$AGENTS_FILE" STATUS_FILE="${STATUS_FILE:-}" \
python3 - > "$OUT_FILE" <<'PY'
import hashlib, json, os
def sha(p):
    return hashlib.sha256(open(p, "rb").read()).hexdigest() if p and os.path.exists(p) else None
e = os.environ
inputs = {"AGENTS.md": {"path": e["AGENTS_FILE"], "sha256": sha(e["AGENTS_FILE"])}}
if e["STATUS_FILE"]:
    inputs["STATUS.md"] = {"path": e["STATUS_FILE"], "sha256": sha(e["STATUS_FILE"])}
print(json.dumps({
    "test": e["TEST"], "runtime": e["RUNTIME"], "model": e["MODEL"],
    "endpoint": e["ENDPOINT"] if e["RUNTIME"] != "mistral" else "vibe -p",
    "timestamp": e["TS"], "latency_s": int(e["LATENCY"]),
    "prompt_sha256": hashlib.sha256(e["PROMPT"].encode()).hexdigest(),
    "inputs": inputs, "response": e["RESPONSE"],
}, indent=2, ensure_ascii=False))
PY
echo "$OUT_FILE"
