#!/usr/bin/env bash
set -Eeuo pipefail

# --dir selects existing-run mode. Without it, run a harness first and then
# re-enter this script in existing-run mode for validation and upload.
EXISTING_MODE=false
for argument in "$@"; do
  case "$argument" in --dir|--run-dir) EXISTING_MODE=true; break ;; esac
done

if [[ "$EXISTING_MODE" == true ]]; then
usage() {
  cat >&2 <<'EOF'
Usage: submit-run.sh --server URL --dir RUN_DIR [OPTIONS]

With --dir, upload an already-created run without running a harness. The script
finds the GLB, preview PNG, and session export in RUN_DIR and creates the
submission manifest from its metadata and directory layout.

Options:
  --server URL          Submission server (or use RENDER_ARENA_URL)
  --dir DIR             Existing run directory
  --model PROVIDER/MODEL  Required unless metadata.json contains this form
  --token TOKEN          Trusted submission API token (or RENDER_ARENA_SUBMISSION_TOKEN)
  --harness NAME        pi, codex, dsh, or opencode (inferred when possible)
  --effort LEVEL        off, minimal, low, medium, high, xhigh, or max
  --prompt ID           Benchmark prompt ID (inferred when possible)
  --glb FILE            Override automatic GLB detection (relative to DIR)
  --preview FILE        Override automatic preview detection (relative to DIR)
  --session FILE        Override automatic session detection (relative to DIR)
  --blend FILE          Override automatic Blend detection (relative to DIR)
  --yes                 Upload without the confirmation prompt
  --dry-run             Show selected files and manifest values without uploading
  -h, --help            Show this help
EOF
}

SERVER=${RENDER_ARENA_URL:-}
RUN_DIR=
MODEL_SPEC=
SUBMISSION_TOKEN=${RENDER_ARENA_SUBMISSION_TOKEN:-}
unset RENDER_ARENA_SUBMISSION_TOKEN
HARNESS=
EFFORT=
PROMPT_ID=
GLB=
PREVIEW=
SESSION=
BLEND=
ASSUME_YES=false
DRY_RUN=false

while (($#)); do
  case $1 in
    --server) SERVER=${2:?--server needs a URL}; shift 2 ;;
    --dir|--run-dir) RUN_DIR=${2:?--dir needs a directory}; shift 2 ;;
    --model) MODEL_SPEC=${2:?--model needs PROVIDER/MODEL}; shift 2 ;;
    --token|--api-key) SUBMISSION_TOKEN=${2:?--token needs a value}; shift 2 ;;
    --harness) HARNESS=${2:?--harness needs a harness}; shift 2 ;;
    --effort) EFFORT=${2:?--effort needs a level}; shift 2 ;;
    --prompt) PROMPT_ID=${2:?--prompt needs an ID}; shift 2 ;;
    --glb) GLB=${2:?--glb needs a file}; shift 2 ;;
    --preview) PREVIEW=${2:?--preview needs a file}; shift 2 ;;
    --session) SESSION=${2:?--session needs a file}; shift 2 ;;
    --blend) BLEND=${2:?--blend needs a file}; shift 2 ;;
    --yes) ASSUME_YES=true; shift ;;
    --dry-run) DRY_RUN=true; shift ;;
    -h|--help) usage; exit 0 ;;
    *) printf 'Unknown argument: %s\n' "$1" >&2; usage; exit 2 ;;
  esac
done

if [[ -z "$SERVER" || -z "$RUN_DIR" ]]; then
  usage
  exit 2
fi
SERVER=${SERVER%/}
RUN_DIR=$(cd -- "$RUN_DIR" && pwd -P) || {
  printf 'Run directory does not exist: %s\n' "$RUN_DIR" >&2
  exit 1
}

for command in curl python3; do
  command -v "$command" >/dev/null || {
    printf 'Required command not found: %s\n' "$command" >&2
    exit 1
  }
done

resolve_file() {
  local value=$1
  if [[ "$value" = /* ]]; then
    printf '%s\n' "$value"
  else
    printf '%s/%s\n' "$RUN_DIR" "$value"
  fi
}

require_file() {
  local label=$1
  local value=$2
  local path
  path=$(resolve_file "$value")
  if [[ ! -s "$path" ]]; then
    printf '%s is missing or empty: %s\n' "$label" "$path" >&2
    exit 1
  fi
  printf '%s\n' "$path"
}

if [[ -n "$GLB" ]]; then
  GLB=$(require_file GLB "$GLB")
else
  mapfile -d '' -t files < <(find "$RUN_DIR" -maxdepth 1 -type f -name '*.glb' -print0)
  ((${#files[@]} == 1)) || {
    printf 'Expected exactly one .glb in %s; found %d. Use --glb FILE.\n' "$RUN_DIR" "${#files[@]}" >&2
    exit 1
  }
  GLB=${files[0]}
  [[ -s "$GLB" ]] || { printf 'GLB is empty: %s\n' "$GLB" >&2; exit 1; }
fi

if [[ -n "$PREVIEW" ]]; then
  PREVIEW=$(require_file preview "$PREVIEW")
else
  if [[ -s "$RUN_DIR/preview.png" ]]; then
    PREVIEW=$RUN_DIR/preview.png
  else
    mapfile -d '' -t files < <(find "$RUN_DIR" -maxdepth 1 -type f -iname '*preview*.png' -print0)
    if ((${#files[@]} == 0)); then
      mapfile -d '' -t files < <(find "$RUN_DIR" -maxdepth 1 -type f -name '*.png' -print0)
    fi
    ((${#files[@]} == 1)) || {
      printf 'Expected exactly one preview PNG in %s; found %d. Use --preview FILE.\n' "$RUN_DIR" "${#files[@]}" >&2
      exit 1
    }
    PREVIEW=${files[0]}
  fi
fi

python3 - "$PREVIEW" <<'PY'
import struct, sys
with open(sys.argv[1], "rb") as stream:
    header = stream.read(24)
if len(header) < 24 or header[:8] != b"\x89PNG\r\n\x1a\n":
    raise SystemExit(f"Preview is not a PNG: {sys.argv[1]}")
width, height = struct.unpack(">II", header[16:24])
if (width, height) != (1536, 1536):
    raise SystemExit(f"Preview is {width}x{height}; expected 1536x1536")
PY

if [[ -n "$SESSION" ]]; then
  SESSION=$(require_file session "$SESSION")
else
  SESSION=
  for name in session.jsonl.zstd session.jsonl.zst session.jsonl session.json; do
    if [[ -s "$RUN_DIR/$name" ]]; then
      [[ -z "$SESSION" ]] || {
        printf 'Multiple session exports found in %s; use --session FILE.\n' "$RUN_DIR" >&2
        exit 1
      }
      SESSION=$RUN_DIR/$name
    fi
  done
  if [[ -z "$SESSION" ]]; then
    mapfile -d '' -t files < <(find "$RUN_DIR" -maxdepth 1 -type f \( -name '*.jsonl.zstd' -o -name '*.jsonl.zst' -o -name '*.jsonl' -o -name '*.json' \) ! -name 'metadata.json' ! -name 'manifest.json' -print0)
    ((${#files[@]} == 1)) || {
      printf 'Expected exactly one session export in %s; found %d. Use --session FILE.\n' "$RUN_DIR" "${#files[@]}" >&2
      exit 1
    }
    SESSION=${files[0]}
  fi
fi
if [[ "$SESSION" == *.zst || "$SESSION" == *.zstd ]]; then
  command -v zstd >/dev/null || {
    printf 'Required command not found for compressed session: zstd\n' >&2
    exit 1
  }
fi

if [[ -n "$BLEND" ]]; then
  BLEND=$(require_file Blend "$BLEND")
else
  mapfile -d '' -t files < <(find "$RUN_DIR" -maxdepth 1 -type f -name '*.blend' -print0)
  if ((${#files[@]} > 1)); then
    printf 'Multiple .blend files found in %s; use --blend FILE.\n' "$RUN_DIR" >&2
    exit 1
  elif ((${#files[@]} == 1)); then
    BLEND=${files[0]}
  fi
fi

SPEC_FILE=$(mktemp)
MANIFEST=$(mktemp)
cleanup() { rm -f -- "$SPEC_FILE" "$MANIFEST"; }
trap cleanup EXIT
curl -fsS "$SERVER/api/submissions/spec" -o "$SPEC_FILE"

SUBMISSION_ID=$(python3 -c 'import uuid; print(uuid.uuid4())')
# Read the existing metadata where available, infer the conventional
# results/<harness>/<profile>/<model>/<effort>/<prompt>/<run> fields, then
# create the public-submission manifest. This does not modify RUN_DIR.
VALUES_OUTPUT=$(python3 - "$SPEC_FILE" "$RUN_DIR" "$MANIFEST" "$SUBMISSION_ID" "$SESSION" "$HARNESS" "$MODEL_SPEC" "$EFFORT" "$PROMPT_ID" <<'PY'
import json
import re
import subprocess
import sys
from pathlib import Path

spec_path, run_dir, manifest_path, submission_id, session_path = sys.argv[1:6]
spec = json.loads(Path(spec_path).read_text(encoding="utf-8"))
overrides = dict(zip(("harness", "model", "effort", "prompt"), sys.argv[6:]))
run_path = Path(run_dir)
metadata_path = run_path / "metadata.json"
metadata = {}
if metadata_path.is_file():
    try:
        metadata = json.loads(metadata_path.read_text(encoding="utf-8"))
    except (OSError, json.JSONDecodeError) as error:
        raise SystemExit(f"Could not read {metadata_path}: {error}")
    if not isinstance(metadata, dict):
        raise SystemExit(f"{metadata_path} must contain a JSON object")

parts = run_path.parts
path_values = {}
if len(parts) >= 6 and parts[-6] in {"pi", "codex", "dsh", "opencode"}:
    path_values = dict(zip(("harness", "profile", "model", "effort", "prompt", "run"), parts[-6:]))


def norm(value):
    return re.sub(r"\s+", " ", value).strip().casefold()


def nested_strings(value):
    if isinstance(value, str):
        yield value
    elif isinstance(value, dict):
        for child in value.values():
            yield from nested_strings(child)
    elif isinstance(value, list):
        for child in value:
            yield from nested_strings(child)


def model_name(provider, model):
    if not model:
        return ""
    if "/" in model:
        return model
    return f"{provider}/{model}" if provider else model


# Native session metadata is authoritative when explicit overrides are absent.
session_values = {"harness": "", "model": "", "effort": "", "prompt": ""}
record_types = set()
path = Path(session_path)
process = None
try:
    if path.name.endswith((".zst", ".zstd")):
        process = subprocess.Popen(
            ["zstd", "-dc", "--", str(path)], stdout=subprocess.PIPE,
            stderr=subprocess.PIPE, text=True, encoding="utf-8", errors="replace"
        )
        stream = process.stdout
    else:
        stream = path.open(encoding="utf-8", errors="replace")
    assert stream is not None
    for line in stream:
        try:
            record = json.loads(line)
        except json.JSONDecodeError:
            continue
        if not isinstance(record, dict):
            continue
        record_type = record.get("type", "")
        if isinstance(record_type, str):
            record_types.add(record_type)
        if record_type == "model_change":
            session_values["harness"] = "pi"
            session_values["model"] = model_name(record.get("provider", ""), record.get("modelId", ""))
        elif record_type == "thinking_level_change":
            session_values["harness"] = "pi"
            session_values["effort"] = record.get("thinkingLevel", "")
        elif record_type == "session_meta":
            session_values["harness"] = "codex"
        elif record_type in {"assistant/message", "tool/call"}:
            session_values["harness"] = "dsh"
            source = record.get("data", {}).get("message", {}).get("source", {})
            if isinstance(source, dict):
                session_values["model"] = model_name(source.get("provider", ""), source.get("model", ""))
        elif record_type == "turn_context":
            session_values["harness"] = "codex"
            payload = record.get("payload", {})
            if isinstance(payload, dict):
                session_values["model"] = payload.get("model", "")
                session_values["effort"] = payload.get("effort", "")

        blob = "\n".join(nested_strings(record))
        normalized_blob = norm(blob)
        for prompt in spec.get("prompts", []):
            text = prompt.get("text", "")
            if isinstance(text, str) and norm(text) in normalized_blob:
                session_values["prompt"] = prompt.get("id", "")
    if process is not None:
        stderr = process.stderr.read() if process.stderr else ""
        if process.wait() != 0:
            raise RuntimeError(stderr.strip() or "zstd failed")
    else:
        stream.close()
except (OSError, RuntimeError) as error:
    raise SystemExit(f"Could not read session {path}: {error}")

if not session_values["harness"] and "session" in record_types:
    session_values["harness"] = "pi"
if session_values["effort"] == "minimum":
    session_values["effort"] = "minimal"


def value(name):
    for candidate in (
        overrides.get(name), session_values.get(name), metadata.get(name), path_values.get(name)
    ):
        if isinstance(candidate, str) and candidate:
            return candidate
    return ""

harness = value("harness")
model = value("model")
effort = value("effort")
prompt_id = value("prompt")
if harness not in spec.get("harnesses", []):
    raise SystemExit(f"Unknown or missing harness {harness!r}; use --harness")
if not model or "/" not in model:
    raise SystemExit("A PROVIDER/MODEL is required; use --model if the session does not record a provider")
valid_efforts = set(spec.get("efforts", []))
if effort not in valid_efforts:
    raise SystemExit(f"Unknown or missing effort {effort!r}; use --effort")
prompt = next((p for p in spec.get("prompts", []) if p.get("id") == prompt_id), None)
if prompt is None:
    raise SystemExit(f"Unknown or missing prompt {prompt_id!r}; use --prompt")

settings = metadata.get("harness_settings")
if not isinstance(settings, dict):
    settings = {}
manifest = {
    "format_version": int(spec["format_version"]),
    "submission_id": submission_id,
    "benchmark_spec_version": spec["benchmark_spec_version"],
    "prompt": prompt_id,
    "prompt_text": prompt["text"],
    "model": model,
    "effort": effort,
    "harness": harness,
    "harness_profile": "submitted",
    "harness_version": str(metadata.get("harness_version", "")),
    "pi_version": str(metadata.get("pi_version", "")),
    "blender_version": str(metadata.get("blender_version", "")),
    "platform": str(metadata.get("platform", "")),
    "harness_settings": settings,
    "render": metadata.get("render", {}) if isinstance(metadata.get("render", {}), dict) else {},
}
Path(manifest_path).write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8")
for item in (harness, model, effort, prompt_id):
    print(item)
PY
)
mapfile -t VALUES <<<"$VALUES_OUTPUT"
HARNESS=${VALUES[0]}
MODEL_SPEC=${VALUES[1]}
EFFORT=${VALUES[2]}
PROMPT_ID=${VALUES[3]}

printf 'Run directory: %s\nHarness: %s\nModel: %s\nEffort: %s\nPrompt: %s\n' \
  "$RUN_DIR" "$HARNESS" "$MODEL_SPEC" "$EFFORT" "$PROMPT_ID"
printf 'GLB: %s\nPreview: %s\nSession: %s\n' "$GLB" "$PREVIEW" "$SESSION"
[[ -n "$BLEND" ]] && printf 'Blend: %s\n' "$BLEND" || printf 'Blend: none (optional)\n'

if [[ "$DRY_RUN" == true ]]; then
  printf '\nManifest:\n'
  python3 -m json.tool "$MANIFEST"
  exit 0
fi

printf '\nThe session export may include prompts, tool output, and local paths.\n'
if [[ "$ASSUME_YES" != true ]]; then
  read -r -p "Upload this run to $SERVER for administrator review? [y/N] " answer
  [[ "$answer" =~ ^[Yy]$ ]] || { printf 'Upload cancelled. Files remain in %s\n' "$RUN_DIR"; exit 0; }
fi

SESSION_MIME=application/octet-stream
[[ "$SESSION" == *.json ]] && SESSION_MIME=application/json
CURL_ARGS=(
  --fail-with-body -sS
  -H "X-Submission-ID: $SUBMISSION_ID"
)
[[ -z "$SUBMISSION_TOKEN" ]] || CURL_ARGS+=( -H "Authorization: Bearer $SUBMISSION_TOKEN" )
CURL_ARGS+=(
  -F "manifest=@$MANIFEST;type=application/json"
  -F "session=@$SESSION;type=$SESSION_MIME"
  -F "glb=@$GLB;type=model/gltf-binary"
  -F "preview=@$PREVIEW;type=image/png"
)
[[ -n "$BLEND" ]] && CURL_ARGS+=( -F "blend=@$BLEND;type=application/octet-stream" )
if response=$(curl "${CURL_ARGS[@]}" "$SERVER/api/submissions"); then
  printf 'Submission accepted for review: %s\nLocal files: %s\n' "$response" "$RUN_DIR"
else
  curl_status=$?
  printf 'Submission failed (curl exit %d).\n' "$curl_status" >&2
  if [[ -n "$response" ]]; then
    printf 'Server response:\n%s\n' "$response" >&2
  else
    printf 'The server returned no response body. Check the URL and network connection.\n' >&2
  fi
  exit "$curl_status"
fi

exit 0
fi

usage() {
  cat >&2 <<'EOF'
Usage:
  submit-run.sh --server URL --model PROVIDER/MODEL --effort LEVEL --prompt ID [OPTIONS]
  submit-run.sh --server URL --dir RUN_DIR [OPTIONS]

Without --dir, run a harness and submit its output. With --dir, skip execution,
infer metadata from an existing run, and submit its artifacts.

Options for new runs:
  --harness NAME      pi, codex, dsh, or opencode (default: pi)
  --token TOKEN       Trusted submission API token (or RENDER_ARENA_SUBMISSION_TOKEN)
  --output DIR        Keep run files in DIR (default: ./render-arena-runs/<run>)
  --timeout DURATION  Stop the harness after this GNU timeout duration (default: 45m; 0 disables)
  --yes               Upload without the confirmation prompt
  --dry-run           Resolve the specification and print the command only
  -h, --help          Show this help

List prompt IDs and supported harnesses with: curl -fsS SERVER/api/submissions/spec
EOF
}

SERVER=${RENDER_ARENA_URL:-}
MODEL_SPEC=
EFFORT=
PROMPT_ID=
HARNESS=pi
SUBMISSION_TOKEN=${RENDER_ARENA_SUBMISSION_TOKEN:-}
unset RENDER_ARENA_SUBMISSION_TOKEN
OUTPUT=
RUN_TIMEOUT=${RUN_TIMEOUT:-45m}
ASSUME_YES=false
DRY_RUN=false
while (($#)); do
  case $1 in
    --server) SERVER=${2:?--server needs a URL}; shift 2 ;;
    --model) MODEL_SPEC=${2:?--model needs PROVIDER/MODEL}; shift 2 ;;
    --effort) EFFORT=${2:?--effort needs a level}; shift 2 ;;
    --prompt) PROMPT_ID=${2:?--prompt needs an ID}; shift 2 ;;
    --harness) HARNESS=${2:?--harness needs pi, codex, dsh, or opencode}; shift 2 ;;
    --token|--api-key) SUBMISSION_TOKEN=${2:?--token needs a value}; shift 2 ;;
    --output) OUTPUT=${2:?--output needs a directory}; shift 2 ;;
    --timeout) RUN_TIMEOUT=${2:?--timeout needs a duration}; shift 2 ;;
    --yes) ASSUME_YES=true; shift ;;
    --dry-run) DRY_RUN=true; shift ;;
    -h|--help) usage; exit 0 ;;
    *) printf 'Unknown argument: %s\n' "$1" >&2; usage; exit 2 ;;
  esac
done

if [[ -z "$SERVER" || -z "$MODEL_SPEC" || -z "$EFFORT" || -z "$PROMPT_ID" || "$MODEL_SPEC" != */* ]]; then
  usage
  exit 2
fi
case "$HARNESS" in pi|codex|dsh|opencode) ;; *) printf 'Unsupported harness: %s\n' "$HARNESS" >&2; exit 2 ;; esac
SERVER=${SERVER%/}
PROVIDER=${MODEL_SPEC%%/*}
MODEL=${MODEL_SPEC#*/}
for command in blender curl python3; do
  command -v "$command" >/dev/null || { printf 'Required command not found: %s\n' "$command" >&2; exit 1; }
done
OPENCODE_BIN=
case "$HARNESS" in
  pi) command -v pi >/dev/null || { printf 'Required command not found: pi\n' >&2; exit 1; } ;;
  codex) command -v codex >/dev/null || { printf 'Required command not found: codex\n' >&2; exit 1; } ;;
  dsh) command -v dsh >/dev/null || { printf 'Required command not found: dsh\n' >&2; exit 1; } ;;
  opencode)
    command -v opencode >/dev/null || { printf 'Required command not found: opencode\n' >&2; exit 1; }
    OPENCODE_BIN=$(command -v opencode)
    # mise shims print status text on stdout, which would corrupt OpenCode's
    # JSON export. Use the installed binary when mise can resolve one.
    if command -v mise >/dev/null; then
      resolved=$(mise which opencode 2>/dev/null | tail -1 || true)
      [[ -x "$resolved" ]] && OPENCODE_BIN=$resolved
    fi
    ;;
esac
if [[ "$RUN_TIMEOUT" != 0 ]]; then
  command -v timeout >/dev/null || { printf 'GNU timeout is required unless --timeout 0 is used.\n' >&2; exit 1; }
fi

SPEC_FILE=$(mktemp)
cleanup_spec() { rm -f -- "$SPEC_FILE"; }
trap cleanup_spec EXIT
curl -fsS "$SERVER/api/submissions/spec" -o "$SPEC_FILE"

readarray -t SPEC_VALUES < <(python3 - "$SPEC_FILE" "$PROMPT_ID" "$EFFORT" "$HARNESS" <<'PY'
import json, sys
spec = json.load(open(sys.argv[1], encoding="utf-8"))
prompt_id, effort, harness = sys.argv[2:]
if effort not in spec.get("efforts", []):
    raise SystemExit(f"Unknown effort: {effort}")
if harness not in spec.get("harnesses", ["pi"]):
    raise SystemExit(f"Unsupported harness: {harness}")
for prompt in spec.get("prompts", []):
    if prompt.get("id") == prompt_id:
        print(spec["format_version"])
        print(spec["benchmark_spec_version"])
        print(prompt["text"])
        break
else:
    choices = ", ".join(p.get("id", "") for p in spec.get("prompts", []))
    raise SystemExit(f"Unknown prompt {prompt_id!r}. Available prompts: {choices}")
PY
)
FORMAT_VERSION=${SPEC_VALUES[0]}
SPEC_VERSION=${SPEC_VALUES[1]}
PROMPT_TEXT=${SPEC_VALUES[2]}

if [[ -z "$OUTPUT" ]]; then
  stamp=$(date -u +%Y%m%dT%H%M%SZ)
  OUTPUT="$PWD/render-arena-runs/${stamp}-${HARNESS}-${PROMPT_ID}"
fi
WORK_DIR=$(mkdir -p -- "$OUTPUT" && cd -- "$OUTPUT" && pwd)
TEMPLATE_DIR="$WORK_DIR/.benchmark"
TEMPLATE="$TEMPLATE_DIR/blender-bench-submit.md"
SESSION_DIR="$WORK_DIR/.${HARNESS}-sessions/$(date -u +%Y%m%dT%H%M%SZ)-$$"
mkdir -p -- "$TEMPLATE_DIR" "$SESSION_DIR"
curl -fsS "$SERVER/submission/blender-bench-submit.md" -o "$TEMPLATE"

# Assemble the same benchmark instructions for every harness. Pi has a native
# template option; the other CLIs receive the rendered text on stdin/argv.
PROMPT_FILE="$TEMPLATE_DIR/prompt.md"
python3 - "$TEMPLATE" "$PROMPT_FILE" "$PROMPT_TEXT" <<'PY'
from pathlib import Path
import sys
text = Path(sys.argv[1]).read_text(encoding="utf-8")
Path(sys.argv[2]).write_text(text.replace("$@", sys.argv[3]), encoding="utf-8")
PY

PI_COMMAND=()
CODEX_COMMAND=()
DSH_COMMAND=()
OPENCODE_COMMAND=()
case "$HARNESS" in
  pi)
    PI_COMMAND=(
      pi --provider "$PROVIDER" --model "$MODEL" --thinking "$EFFORT"
      --session-dir "$SESSION_DIR"
      --no-extensions --no-skills --no-context-files --no-prompt-templates
      --prompt-template "$TEMPLATE" --approve -p --
      "/blender-bench-submit $PROMPT_TEXT"
    )
    ;;
  codex)
    CODEX_COMMAND=(
      codex exec --json --model "$MODEL"
      -c "model_reasoning_effort=\"$EFFORT\""
      --dangerously-bypass-approvals-and-sandbox
      -C "$WORK_DIR" -
    )
    ;;
  dsh)
    # dsh's launcher options precede the application prompt. The headless
    # profile emits the session JSONL used by the DSH importer on stdout.
    DSH_COMMAND=(dsh --profile headless "$PROMPT_TEXT")
    ;;
  opencode)
    OPENCODE_COMMAND=("$OPENCODE_BIN" --pure run --format json --auto --model "$MODEL_SPEC" --dir "$WORK_DIR")
    [[ "$EFFORT" == off ]] || OPENCODE_COMMAND+=(--variant "$EFFORT")
    OPENCODE_COMMAND+=("$PROMPT_TEXT")
    ;;
esac
HARNESS_SETTINGS=$(python3 - "$HARNESS" "$EFFORT" <<'PY'
import json, sys
harness, effort = sys.argv[1:]
settings = {
    "pi": {"thinking": effort, "profile": "submitted"},
    "codex": {"model_reasoning_effort": effort},
    "dsh": {"profile": "headless", "requested_effort": effort, "effective_effort": "profile-defined"},
    "opencode": {"variant": effort},
}[harness]
print(json.dumps(settings, separators=(",", ":")))
PY
)

printf 'Run directory: %s\nHarness: %s\nModel: %s\nEffort: %s\nPrompt: %s — %s\n' \
  "$WORK_DIR" "$HARNESS" "$MODEL_SPEC" "$EFFORT" "$PROMPT_ID" "$PROMPT_TEXT"
if [[ "$DRY_RUN" == true ]]; then
  printf 'Command:'
  case "$HARNESS" in
    pi) printf ' %q' "${PI_COMMAND[@]}" ;;
    codex) printf ' %q' "${CODEX_COMMAND[@]}" ;;
    dsh) printf ' %q' "${DSH_COMMAND[@]}" ;;
    opencode) printf ' %q' "${OPENCODE_COMMAND[@]}" ;;
  esac
  printf '\n'
  exit 0
fi

run_with_timeout() {
  if [[ "$RUN_TIMEOUT" == 0 ]]; then
    "$@"
  else
    timeout --signal=TERM --kill-after=30s "$RUN_TIMEOUT" "$@"
  fi
}

set +e
case "$HARNESS" in
  pi)
    (cd -- "$WORK_DIR" && run_with_timeout "${PI_COMMAND[@]}" 2>&1 | tee "$WORK_DIR/harness-output.log")
    HARNESS_STATUS=${PIPESTATUS[0]}
    ;;
  codex)
    # The JSON event stream identifies the new thread, so use Codex's normal
    # session store rather than copying credentials into an isolated CODEX_HOME.
    (cd -- "$WORK_DIR" && run_with_timeout "${CODEX_COMMAND[@]}" <"$PROMPT_FILE" >"$WORK_DIR/harness-output.jsonl" 2>"$WORK_DIR/harness-stderr.log")
    HARNESS_STATUS=$?
    ;;
  dsh)
    (cd -- "$WORK_DIR" && run_with_timeout "${DSH_COMMAND[@]}" >"$SESSION_DIR/dsh-output.jsonl" 2>"$WORK_DIR/harness-stderr.log")
    HARNESS_STATUS=$?
    ;;
  opencode)
    # OpenCode's JSON event stream includes the primary sessionID, so there is
    # no need to redirect its data/config directories or diff session listings.
    (cd -- "$WORK_DIR" && run_with_timeout "${OPENCODE_COMMAND[@]}" >"$WORK_DIR/harness-output.jsonl" 2>"$WORK_DIR/harness-stderr.log")
    HARNESS_STATUS=$?
    ;;
esac
set -e
if ((HARNESS_STATUS != 0)); then
  printf '%s exited with status %d. Nothing was uploaded; files remain in %s\n' "$HARNESS" "$HARNESS_STATUS" "$WORK_DIR" >&2
  exit "$HARNESS_STATUS"
fi

for artifact in preview.png scene.glb scene.blend; do
  if [[ ! -s "$WORK_DIR/$artifact" ]]; then
    printf 'Required artifact is missing or empty: %s\nNothing was uploaded.\n' "$WORK_DIR/$artifact" >&2
    exit 1
  fi
done
python3 - "$WORK_DIR/preview.png" <<'PY'
import struct, sys
with open(sys.argv[1], "rb") as stream:
    header = stream.read(24)
if len(header) < 24 or header[:8] != b"\x89PNG\r\n\x1a\n":
    raise SystemExit("preview.png is not a PNG")
width, height = struct.unpack(">II", header[16:24])
if (width, height) != (1536, 1536):
    raise SystemExit(f"preview.png is {width}x{height}; expected 1536x1536")
PY

# Capture the authoritative native session rather than treating formatted CLI
# output as a transcript. All modes end with one portable session file.
SESSION_UPLOAD="$WORK_DIR/session.jsonl"
case "$HARNESS" in
  pi)
    mapfile -t SESSION_FILES < <(find "$SESSION_DIR" -type f -name '*.jsonl' -print)
    ((${#SESSION_FILES[@]} == 1)) || { printf 'Expected exactly one Pi session under %s, found %d.\n' "$SESSION_DIR" "${#SESSION_FILES[@]}" >&2; exit 1; }
    cp -- "${SESSION_FILES[0]}" "$SESSION_UPLOAD"
    ;;
  codex)
    THREAD_ID=$(python3 - "$WORK_DIR/harness-output.jsonl" <<'PY'
import json, sys
for line in open(sys.argv[1], encoding="utf-8"):
    try:
        event = json.loads(line)
    except json.JSONDecodeError:
        continue
    if event.get("type") == "thread.started" and event.get("thread_id"):
        print(event["thread_id"])
        break
else:
    raise SystemExit("No Codex thread.started event found")
PY
) || { printf 'Could not identify the Codex thread from its JSON event stream.\n' >&2; exit 1; }
    CODEX_ROOT=${CODEX_HOME:-$HOME/.codex}
    SESSION_FILE=$(python3 - "$CODEX_ROOT/sessions" "$THREAD_ID" <<'PY'
import json, sys
from pathlib import Path
root = Path(sys.argv[1])
thread_id = sys.argv[2]
for path in root.rglob(f"rollout-*-{thread_id}.jsonl"):
    try:
        with path.open(encoding="utf-8") as stream:
            meta = json.loads(next(stream))
        if meta.get("type") == "session_meta" and meta.get("payload", {}).get("session_id") == thread_id:
            print(path)
            break
    except (OSError, StopIteration, json.JSONDecodeError):
        continue
else:
    raise SystemExit(f"No Codex rollout found for thread {thread_id}")
PY
) || { printf 'Could not locate the Codex rollout for thread %s.\n' "$THREAD_ID" >&2; exit 1; }
    cp -- "$SESSION_FILE" "$SESSION_UPLOAD"
    ;;
  dsh)
    SESSION_FILE="$SESSION_DIR/dsh-output.jsonl"
    [[ -s "$SESSION_FILE" ]] || { printf 'DSH did not produce a session export.\n' >&2; exit 1; }
    cp -- "$SESSION_FILE" "$SESSION_UPLOAD"
    ;;
  opencode)
    SESSION_ID=$(python3 - "$WORK_DIR/harness-output.jsonl" <<'PY'
import json, sys
session_ids = []
with open(sys.argv[1], encoding="utf-8") as stream:
    for line in stream:
        try:
            value = json.loads(line)
        except json.JSONDecodeError:
            continue
        session_id = value.get("sessionID")
        if session_id and session_id not in session_ids:
            session_ids.append(session_id)
if len(session_ids) != 1:
    raise SystemExit(f"Expected one OpenCode sessionID in the JSON event stream, found {len(session_ids)}")
print(session_ids[0])
PY
) || { printf 'Could not identify the OpenCode session from its JSON event stream.\n' >&2; exit 1; }
    SESSION_UPLOAD="$WORK_DIR/session.json"
    "$OPENCODE_BIN" --pure export "$SESSION_ID" >"$SESSION_UPLOAD"
    ;;
esac

RENDER_JSON='{}'
cat >"$TEMPLATE_DIR/read_environment.py" <<'PY'
import bpy, json, platform
scene = bpy.context.scene
cycles = bpy.context.preferences.addons.get("cycles")
compute = getattr(cycles.preferences, "compute_device_type", "") if cycles else ""
devices = []
if cycles:
    try:
        cycles.preferences.get_devices()
        devices = [device.name for device in cycles.preferences.devices]
    except Exception:
        devices = []
print("RENDER_ARENA_ENV=" + json.dumps({
    "engine": scene.render.engine,
    "cycles_device": getattr(scene.cycles, "device", "") if hasattr(scene, "cycles") else "",
    "compute_backend": compute,
    "devices": devices,
    "os": platform.platform(),
    "cpu": platform.processor(),
}))
PY
if environment_output=$(blender -b "$WORK_DIR/scene.blend" --python "$TEMPLATE_DIR/read_environment.py" 2>/dev/null); then
  environment_line=$(printf '%s\n' "$environment_output" | grep '^RENDER_ARENA_ENV=' | tail -1 || true)
  [[ -z "$environment_line" ]] || RENDER_JSON=${environment_line#RENDER_ARENA_ENV=}
fi

case "$HARNESS" in
  pi) HARNESS_VERSION=$(pi --version 2>&1 | head -1 || true) ;;
  codex) HARNESS_VERSION=$(codex --version 2>&1 | head -1 || true) ;;
  dsh) HARNESS_VERSION=$(dsh --version 2>&1 | head -1 || true) ;;
  opencode) HARNESS_VERSION=$("$OPENCODE_BIN" --version 2>&1 | head -1 || true) ;;
esac
BLENDER_VERSION=$(blender --version 2>&1 | head -1 || true)
PLATFORM=$(uname -srm 2>/dev/null || true)
python3 - "$WORK_DIR/metadata.json" "$MODEL_SPEC" "$EFFORT" "$HARNESS" "$HARNESS_VERSION" "$HARNESS_SETTINGS" "$BLENDER_VERSION" "$PLATFORM" "$RENDER_JSON" <<'PY'
import json, sys
(path, model, effort, harness, harness_version, harness_settings,
 blender_version, platform, render) = sys.argv[1:]
with open(path, "w", encoding="utf-8") as stream:
    json.dump({
        "model": model,
        "effort": effort,
        "harness": harness,
        "harness_version": harness_version,
        "harness_settings": json.loads(harness_settings),
        "pi_version": harness_version if harness == "pi" else "",
        "blender_version": blender_version,
        "platform": platform,
        "render": json.loads(render),
    }, stream, indent=2)
    stream.write("\n")
PY

submit_args=(
  --server "$SERVER"
  --dir "$WORK_DIR"
  --model "$MODEL_SPEC"
  --harness "$HARNESS"
  --effort "$EFFORT"
  --prompt "$PROMPT_ID"
  --session "$SESSION_UPLOAD"
)
[[ -z "$SUBMISSION_TOKEN" ]] || submit_args+=(--token "$SUBMISSION_TOKEN")
[[ "$ASSUME_YES" == true ]] && submit_args+=(--yes)
rm -f -- "$SPEC_FILE"
trap - EXIT
exec "$0" "${submit_args[@]}"
