#!/usr/bin/env python3
"""Real-app evidence driver. Pass a checkout and an output root; no credentials are embedded.

configure: run with the development server stopped.
launch: run with T3CODE_DEV_SEED=0 vp run dev (no global Codex launch-args override).
Set EVIDENCE_CODEX_MODEL to a model supported by the local Codex installation.
claude-launch: set EVIDENCE_CLAUDE_MODEL to the canonical id reported by Claude's
modelUsage result (an alias can leave T3's capacity unknown). Configure first.
Zero/negative cases may enter immediate compaction: stop those turns in the UI.
report: reads only the isolated checkout database and exports numeric context usage.
"""
import argparse
import datetime
import json
import os
import pathlib
import sqlite3
import subprocess

CASES = {
    "known": "-c model_auto_compact_token_limit=100000 -c features.token_budget=false",
    "budget": "-c model_auto_compact_token_limit=100000 -c features.token_budget=true",
    "body": "-c model_auto_compact_token_limit=100000 -c features.token_budget=false -c model_auto_compact_token_limit_scope=body_after_prefix",
    "absent": "-c features.token_budget=false",
    "zero": "-c model_auto_compact_token_limit=0 -c features.token_budget=false",
    "negative": "-c model_auto_compact_token_limit=-1 -c features.token_budget=false",
    "capacity": "-c model_auto_compact_token_limit=258400 -c features.token_budget=false",
    "above": "-c model_auto_compact_token_limit=300000 -c features.token_budget=false",
    "clamped": "-c model_auto_compact_token_limit=240000 -c features.token_budget=false",
    "child": "-c model_auto_compact_token_limit=100000 -c features.token_budget=false -c features.multi_agent=true",
}
P = argparse.ArgumentParser()
P.add_argument("phase", choices=["configure", "launch", "claude-launch", "report"])
P.add_argument("--checkout", required=True, type=pathlib.Path)
P.add_argument("--output", required=True, type=pathlib.Path)
P.add_argument("--project", required=True, type=pathlib.Path)
P.add_argument("--cases", nargs="*", default=list(CASES))
a = P.parse_args()
out = a.output / datetime.datetime.now(datetime.timezone.utc).strftime("%Y%m%dT%H%M%S%fZ")
out.mkdir(parents=True)
cli = ["node", "apps/server/src/bin.ts"]

if a.phase == "configure":
    p = a.checkout / ".t3/userdata/settings.json"
    settings = json.loads(p.read_text())
    for case in a.cases:
        settings.setdefault("providerInstances", {})["evidence-" + case] = {
            "driver": "codex", "displayName": "Context " + case,
            "enabled": True, "config": {"launchArgs": CASES[case]},
        }
    settings["providerInstances"]["evidence-claude-limit"] = {
        "driver": "claudeAgent", "displayName": "Claude context limit", "enabled": True,
        "config": {"autoCompactWindow": "150000"},
    }
    p.write_text(json.dumps(settings, indent=2) + "\n")
    (out / "configuration.json").write_text(json.dumps({c: CASES[c] for c in a.cases}, indent=2))
elif a.phase in ["launch", "claude-launch"]:
    model = os.environ["EVIDENCE_CLAUDE_MODEL" if a.phase == "claude-launch" else "EVIDENCE_CODEX_MODEL"]
    a.project.mkdir(parents=True, exist_ok=True)
    # Existing projects are harmless here; all CLI output stays private.
    subprocess.run(cli + ["project", "add", str(a.project), "--title", "Context evidence", "--base-dir", ".t3"], cwd=a.checkout, capture_output=True)
    for case in (["claude-limit"] if a.phase == "claude-launch" else a.cases):
        prompt = "Reply with OK."
        if case == "child":
            prompt = "Use the native spawn_agent tool to create one child agent. Ask it to reply with OK only. Wait for its completion, then reply with OK. Do not use MCP delegation tools."
        cmd = cli + ["thread", "start", "--base-dir", ".t3", "--provider", "evidence-" + case,
                     "--model", model, "--title", "Context " + case, "--json", str(a.project), prompt]
        result = subprocess.run(cmd, cwd=a.checkout, capture_output=True, text=True)
        # Launch output contains ids, not model identifiers. Keep raw errors private.
        try:
            data = json.loads(result.stdout)
        except ValueError:
            data = {"exit": result.returncode, "launched": False}
        (out / (case + "-launch.json")).write_text(json.dumps(data, indent=2))
        print(case, "launched" if "threadId" in data else "launch failed", flush=True)
elif a.phase == "report":
    db = sqlite3.connect(f"file:{a.checkout}/.t3/userdata/statev2.sqlite?mode=ro", uri=True)
    rows = []
    for (payload,) in db.execute("SELECT payload_json FROM orchestration_v2_projection_provider_turns ORDER BY started_at"):
        turn = json.loads(payload)
        rows.append({"status": turn["status"], "ordinal": turn["ordinal"],
                     "tokenUsage": {k:v for k,v in turn.get("tokenUsage", {}).items()
                                    if k in ["usedTokens", "maxTokens", "autoCompactThreshold", "inputTokens", "outputTokens"]}})
    (out / "context-usage.json").write_text(json.dumps(rows, indent=2))
    print(json.dumps(rows, indent=2))
print("Run artifacts created.")
