#!/usr/bin/env python3
"""Generate appendix-logs.tex: verbatim prompt + seeded-random completions
for every key condition, straight from the logged JSONL. Full texts, no
truncation. Also the gpt-4o-mini failed-calibration receipts."""

import json
import random
from pathlib import Path

OUT = Path(__file__).parent
TEX = OUT.parent.parent / "appendix-logs.tex"
SEED = 11235
N_SHOW = 8


def esc(s):
    s = s.replace("\\", r"\textbackslash{}")
    for a, b in [("&", r"\&"), ("%", r"\%"), ("$", r"\$"), ("#", r"\#"),
                 ("_", r"\_"), ("{", r"\{"), ("}", r"\}"),
                 ("~", r"\textasciitilde{}"), ("^", r"\textasciicircum{}")]:
        s = s.replace(a, b)
    s = s.replace("\n", r"\;\textsf{\small[newline]}\;")
    return s


def load(fname):
    return [json.loads(l) for l in open(OUT / fname)]


def block(title, prompt_desc, records, textkey, n=N_SHOW, note=""):
    rng = random.Random(SEED)
    idx = sorted(rng.sample(range(len(records)), min(n, len(records))))
    lines = [f"\\subsection*{{{title}}}", ""]
    lines.append(prompt_desc)
    if note:
        lines.append(note)
    lines.append("\\begin{itemize}[itemsep=2pt]")
    for i in idx:
        t = esc(records[i][textkey].strip())
        lines.append(f"\\item[\\#{i}:] \\textit{{{t}}}")
    lines.append("\\end{itemize}")
    lines.append("")
    return lines


L = []
L.append("% AUTO-GENERATED by experiments/fork-pilot/gen_appendix.py — do not hand-edit")
L.append("\\section{Experiment log excerpts}\\label{app:logs}")
L.append("")
L.append(
    "Every text sampled in this paper is logged verbatim, with its full "
    "prompt context, in the supplementary data package "
    "(\\S\\ref{sec:empirics}, data availability). This appendix reproduces, "
    "for each key condition, the exact prompt and a seeded random sample of "
    "the logged outputs ($\\mathrm{seed}=11235$, indices shown) --- "
    "unabridged and uncorrected, exactly as generated. The reader can check "
    "every quoted text against the package by its index.")
L.append("")

# --- pilot 3 (cone) ---
p3 = {c: load(f"p3_continuations_{c}.jsonl") for c in ["AMB", "FIN", "RIV"]}
L.append("\\subsection*{Free-completion pilot (\\texttt{gpt-3.5-turbo-instruct}, $T=1.0$, $n=300$/condition)}")
L.append("Each record: the prompt below, completed freely; first sentences "
         "of the completions were embedded. The four completions of "
         "Example~\\ref{ex:miniature} are records \\#114, \\#64, \\#89 and "
         "\\#199 of the AMB log.")
L.append("")
for cond, label in [("AMB", "AMB (calibrated ambiguous boundary)"),
                    ("FIN", "FIN control"), ("RIV", "RIV control")]:
    prompt = p3[cond][0]["prompt"]
    L += block(f"Cone / {label}",
               f"\\noindent Prompt (verbatim): \\textit{{``{esc(prompt)}''}}",
               p3[cond], "continuation")

# --- 2-horn (FIM) ---
h = {c: load(f"h_infills_{c}.jsonl") for c in ["NEU", "FIN", "RIV"]}
L.append("\\subsection*{The $2$-horn (FIM) experiment "
         "(\\texttt{gpt-3.5-turbo-instruct}, prompted infilling, $T=1.0$, "
         "$n=200$/horn)}")
L.append("Each record: prefix and suffix below, both held fixed; the model "
         "samples the bridge. The FIM template is reproduced in the "
         "supplementary package and in \\texttt{run\\_horn.py}.")
L.append("")
for cond, label in [("NEU", "neutral suffix --- the $2$-horn fork test"),
                    ("FIN", "financial suffix"), ("RIV", "riparian suffix")]:
    r0 = h[cond][0]
    desc = (f"\\noindent Prefix: \\textit{{``{esc(r0['prefix'])}''}} "
            f"\\quad Suffix: \\textit{{``{esc(r0['suffix'])}''}}")
    L += block(f"Horn / {label}", desc, h[cond], "infill")

# --- native FIM ---
hn = {c: load(f"hn_infills_{c}.jsonl") for c in ["NEU", "FIN", "RIV"]}
L.append("\\subsection*{Native FIM (API suffix conditioning, "
         "\\texttt{gpt-3.5-turbo-instruct}, $T=1.0$, $n=200$/horn)}")
L.append("Same horns as above, no instruction template: the prefix is the "
         "prompt, the suffix is passed natively. Note the scene-bridging "
         "register --- the basis of the two-instruments finding.")
L.append("")
for cond, nshow in [("NEU", 8), ("FIN", 4), ("RIV", 4)]:
    r0 = hn[cond][0]
    desc = (f"\\noindent Suffix: \\textit{{``{esc(r0['suffix'])}''}}")
    L += block(f"Native FIM / {cond}", desc, hn[cond], "infill", n=nshow)

# --- gpt-4o-mini failed calibration ---
hc = {c: load(f"hcal_infills_{c}.jsonl") for c in ["NEU", "FIN", "RIV"]}
L.append("\\subsection*{The failed instrument: \\texttt{gpt-4o-mini} "
         "calibration ($T=1.0$, $n=10$/horn)}")
L.append("The basis of the mode-collapse finding (\\S\\ref{sec:empirics}): "
         "the instruction-tuned model's bridges, same horns as above. Note "
         "the near-identical sociable register and the weak uptake of the "
         "suffix constraint.")
L.append("")
for cond in ["NEU", "FIN", "RIV"]:
    r0 = hc[cond][0]
    desc = (f"\\noindent Suffix: \\textit{{``{esc(r0['suffix'])}''}}")
    L += block(f"\\texttt{{gpt-4o-mini}} / {cond}", desc, hc[cond], "infill", n=4)

TEX.write_text("\n".join(L) + "\n")
print(f"wrote {TEX} ({len(L)} lines)")
