#!/usr/bin/env python3
"""Force deepseek-chat to produce an exactly-100-word product description.
Harness method frozen in acceptance-100.md: 4 sealed 25-word sections, each
machine-counted by this utility; bounded repair (max 5 attempts/section)
with the measured delta fed back. The operator edits nothing."""
import json, os, re, subprocess

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"}
MODEL = "deepseek-chat"
MAX_ATTEMPTS = 5

RULE = ("Counting rule: a word is a token separated by whitespace; punctuation attached "
        "to a word is part of that word. Output ONLY the section text — no numbering, "
        "no counting notes, no quotation marks around it.")

SECTIONS = [
    ("S1-hook", "the opening hook: introduce this coffee mug and the feeling it promises in the first sip"),
    ("S2-craft", "materials and craft: ceramic body, glaze, weight, handle design, how it is made and finished"),
    ("S3-experience", "the daily experience: morning coffee at home, desk at work, warmth in the hands, easy washing"),
    ("S4-close", "the close: who this mug is for and a gentle invitation to make it theirs"),
]

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)
    return d["choices"][0]["message"]["content"].strip()

def wc(text):
    return len([w for w in re.split(r"\s+", text.strip()) if w])

def run_section(name, brief, assembly_no):
    attempts = []
    prompt = (f"You are writing one section of a coffee-mug product description. "
              f"This section's job: {brief}. Write EXACTLY 25 words. {RULE}")
    msgs = [{"role": "user", "content": prompt}]
    for a in range(1, MAX_ATTEMPTS + 1):
        ans = call(msgs)
        n = wc(ans)
        attempts.append({"attempt": a, "words": n, "text": ans})
        print(f"  A{assembly_no} {name} attempt {a}: {n} words", flush=True)
        if n == 25:
            return ans, attempts
        delta = n - 25
        fix = (f"That was {n} words, not 25 — {'remove ' + str(delta) if delta > 0 else 'add ' + str(-delta)} "
               f"word{'s' if abs(delta) != 1 else ''}. Rewrite the section at EXACTLY 25 words, "
               f"keeping its job: {brief}. {RULE}")
        msgs.append({"role": "assistant", "content": ans})
        msgs.append({"role": "user", "content": fix})
    return None, attempts

def run_assembly(no):
    print(f"ASSEMBLY {no}", flush=True)
    parts, record, ok = [], [], True
    for name, brief in SECTIONS:
        text, attempts = run_section(name, brief, no)
        record.append({"section": name, "attempts": attempts, "passed": text is not None})
        if text is None:
            ok = False
            break
        parts.append(text)
    full = " ".join(parts) if ok else None
    total = wc(full) if full else None
    print(f"ASSEMBLY {no}: {'PASS total=' + str(total) if ok and total == 100 else 'FAIL total=' + str(total)}", flush=True)
    return {"assembly": no, "sections": record, "text": full, "total_words": total,
            "pass": bool(ok and total == 100)}

results = [run_assembly(i) for i in (1, 2, 3)]
json.dump(results, open(os.path.join(HERE, "force100.json"), "w"), indent=1)
print("FORCE100 DONE:", sum(1 for r in results if r["pass"]), "/3 assemblies pass")
