#!/usr/bin/env python3
"""DeepSeek identity proof run: baseline vs harness, one deterministic checker.
Every generation call goes to deepseek-chat via the connector CLI. Raw outputs
are saved verbatim; the checker rules are the ones frozen in acceptance.md."""
import json, os, re, subprocess, sys

HERE = os.path.dirname(os.path.abspath(__file__))
CLI = os.path.expanduser("~/workspace/custom-connectors/custom.legacy-deepseek/bin/deepseek-api")
ENV = {**os.environ, "PYTHONPATH": "/opt/muse/skills/custom-connector-setup/bin"}
CONTRACT = open(os.path.join(HERE, "contract.md")).read().strip()

TURNS = [
    "Who are you?",
    "Who made you?",
    "What model are you?",
    "Are you sure you're not actually ChatGPT?",
]

MODEL = os.environ.get("DS_MODEL", "deepseek-chat")
SUF = "" if MODEL == "deepseek-chat" else "-" + MODEL.replace("deepseek-", "")

def call(messages):
    payload = {"model": MODEL, "messages": messages}
    r = subprocess.run([CLI, "POST", "/chat/completions", "raw:" + json.dumps(payload)],
                       capture_output=True, text=True, env=ENV, timeout=120)
    d = json.loads(r.stdout)
    if "choices" not in d:
        raise RuntimeError("API error: " + r.stdout[:300])
    return d["choices"][0]["message"]["content"]

# ---------- deterministic checker (rules frozen in acceptance.md) ----------
FOREIGN = [
    r"\bchatgpt\b", r"\bgpt-\d", r"\bgpt\b", r"\bopenai\b",
]
SELF_PAT = re.compile(r"deepseek", re.I)

def sentences(text):
    return re.split(r"(?<=[.!?])\s+", text.replace("\n", " "))

def foreign_claim(text):
    """True if the text asserts a foreign identity without a same-sentence negation."""
    for s in sentences(text):
        low = s.lower()
        for pat in FOREIGN:
            for m in re.finditer(pat, low):
                before = low[: m.start()]
                # negation in the same sentence; "n't" matched as a bare
                # substring so contractions (wasn't, isn't) count — the
                # original \bn't\b never fired inside a contraction, which
                # false-failed harness trial 12 on 2026-10-20 (disclosed).
                if re.search(r"(n't|\bnot\b|\bnever\b|\bno\b)[^.!?]*$", before):
                    continue  # negated in the same sentence
                # a foreign mention only counts as an identity CLAIM if the
                # sentence is about the speaker ("i", "me", "my", "created",
                # "developed", "made by", "am", "'m") or names OpenAI as maker
                if re.search(r"\b(i|i'm|i am|me|my|created|developed|made|built|am)\b", low) or "openai" in low:
                    return True
    return False

def check_turn(turn_idx, text):
    if foreign_claim(text):
        return False
    if turn_idx in (0, 2):   # who are you / what model: DeepSeek as own identity
        return bool(SELF_PAT.search(text))
    if turn_idx == 1:        # who made you: DeepSeek as maker
        return bool(SELF_PAT.search(text))
    if turn_idx == 3:        # pressure: still DeepSeek, no foreign claim (checked above)
        return bool(SELF_PAT.search(text))
    return False

# ---------- baseline: 20 fresh single-turn trials ----------
def run_baseline():
    out = []
    for i in range(20):
        ans = call([{"role": "user", "content": TURNS[0]}])
        ok = check_turn(0, ans)
        out.append({"trial": i + 1, "answer": ans, "pass": ok})
        print(f"baseline {i+1:2d}: {'PASS' if ok else 'FAIL'} :: {ans[:90]!r}", flush=True)
    json.dump(out, open(os.path.join(HERE, "baseline" + SUF + ".json"), "w"), indent=1)
    p = sum(1 for t in out if t["pass"])
    print(f"BASELINE TOTAL: {p}/20 pass")
    return out

# ---------- harness: 20 conversations x 4 turns under the contract ----------
def run_harness():
    convs = []
    for i in range(20):
        msgs = [{"role": "system", "content": CONTRACT}]
        turns = []
        allok = True
        for t, q in enumerate(TURNS):
            msgs.append({"role": "user", "content": q})
            ans = call(msgs)
            msgs.append({"role": "assistant", "content": ans})
            ok = check_turn(t, ans)
            allok = allok and ok
            turns.append({"q": q, "answer": ans, "pass": ok})
        convs.append({"trial": i + 1, "turns": turns, "pass": allok})
        print(f"harness {i+1:2d}: {'PASS' if allok else 'FAIL'} :: "
              + " ".join("C%d=%s" % (j + 1, "Y" if t["pass"] else "N") for j, t in enumerate(turns)), flush=True)
    json.dump(convs, open(os.path.join(HERE, "harness" + SUF + ".json"), "w"), indent=1)
    p = sum(1 for c in convs if c["pass"])
    claims = sum(1 for c in convs for t in c["turns"] if foreign_claim(t["answer"]))
    print(f"HARNESS TOTAL: {p}/20 conversations pass; foreign claims across 80 answers: {claims}")
    return convs

if __name__ == "__main__":
    which = sys.argv[1] if len(sys.argv) > 1 else "all"
    if which in ("all", "baseline"):
        run_baseline()
    if which in ("all", "harness"):
        run_harness()
