#!/usr/bin/env python3
"""Wire provenance chips + nav/footer updates into the existing leadership pages.
Every substitution asserts its expected match count — nothing silently misses."""
import json
import re
from pathlib import Path

SITE = Path(__file__).resolve().parent.parent / "site"
DATA = json.load(open(SITE / "assets" / "claims.json"))
CLAIMS = {c["id"]: c for c in DATA["claims"]}


def chip(cid, rel=""):
    c = CLAIMS[cid]
    du = c.get("decision_use") or {}
    g = du.get("grade", "?")
    title = (f'[Decision-use {g} — {du.get("basis", "")}] ' + c["claim"][:190]).replace('"', "&quot;")
    return f'<a class="claim-ref g{g}" href="{rel}evidence.html#{cid}" title="{title}">{cid} · {g}</a>'


def gapchip(gid, label, rel=""):
    return f'<a class="claim-ref gap" href="{rel}evidence.html#{gid}" title="Measured gap — no published evidence anywhere; in-house measurement required">{label}</a>'


def sub_once(text, old, new, where, count=1):
    n = text.count(old)
    assert n == count, f"[{where}] expected {count} of pattern, found {n}: {old[:90]!r}"
    return text.replace(old, new)


# ---------------------------------------------------------------- nav + footer, all pages
OLD_NAV_ROOT = '''      <a href="index.html" data-nav="home">Thesis</a>
      <a href="research.html" data-nav="research">Research</a>
      <a href="architecture.html" data-nav="architecture">System</a>
      <a href="pilot.html" data-nav="pilot">Pilot</a>
      <a href="library.html" data-nav="library">Library</a>'''
NEW_NAV_ROOT = '''      <a href="index.html" data-nav="home">Thesis</a>
      <a href="research.html" data-nav="research">Research</a>
      <a href="architecture.html" data-nav="architecture">System</a>
      <a href="pilot.html" data-nav="pilot">Pilot</a>
      <a href="decisions.html" data-nav="decisions">Decisions</a>
      <a href="evidence.html" data-nav="evidence">Evidence</a>
      <a href="library.html" data-nav="library">Library</a>'''
OLD_NAV_VIEW = OLD_NAV_ROOT.replace('href="', 'href="../../')
NEW_NAV_VIEW = NEW_NAV_ROOT.replace('href="', 'href="../../')

OLD_FOOT_ROOT = '<span class="footer-label">Primary artifacts</span><p><a href="documents/view/research-atlas.html">Research atlas</a><br>'
NEW_FOOT_ROOT = '<span class="footer-label">Primary artifacts</span><p><a href="evidence.html">Evidence ledger</a><br><a href="decisions.html">Decision register</a><br><a href="documents/view/research-atlas.html">Research atlas</a><br>'
OLD_FOOT_VIEW = '<span class="footer-label">Primary artifacts</span><p><a href="../../documents/view/research-atlas.html">Research atlas</a><br>'
NEW_FOOT_VIEW = '<span class="footer-label">Primary artifacts</span><p><a href="../../evidence.html">Evidence ledger</a><br><a href="../../decisions.html">Decision register</a><br><a href="../../documents/view/research-atlas.html">Research atlas</a><br>'

nav_hits = foot_hits = 0
for p in list(SITE.glob("*.html")) + list((SITE / "documents" / "view").glob("*.html")):
    if p.name in ("evidence.html", "decisions.html"):
        continue
    t = p.read_text(encoding="utf-8")
    t0 = t
    for old, new in ((OLD_NAV_ROOT, NEW_NAV_ROOT), (OLD_NAV_VIEW, NEW_NAV_VIEW)):
        if old in t:
            t = t.replace(old, new)
            nav_hits += 1
    for old, new in ((OLD_FOOT_ROOT, NEW_FOOT_ROOT), (OLD_FOOT_VIEW, NEW_FOOT_VIEW)):
        if old in t:
            t = t.replace(old, new)
            foot_hits += 1
    if t != t0:
        p.write_text(t, encoding="utf-8")
print(f"nav updated in {nav_hits} files; footer updated in {foot_hits} files")

# ---------------------------------------------------------------- research.html
p = SITE / "research.html"
t = p.read_text(encoding="utf-8")

CARD_CHIPS = [
    ("https://arxiv.org/abs/2606.19544", ["AJ-03", "CT-01"]),
    ("https://arxiv.org/abs/2410.03775", ["AQ-03"]),
    ("https://arxiv.org/abs/2603.25133", ["AJ-04", "F26-06"]),
    ("https://arxiv.org/abs/2603.01562", ["RR-04", "RR-07"]),
    ("https://arxiv.org/abs/2512.10791", ["GF-07"]),
    ("https://aclanthology.org/2025.naacl-long.320/", ["GF-03"]),
    ("https://arxiv.org/abs/2510.26518", ["CM-03"]),
    ("https://arxiv.org/abs/2407.00215", ["CM-02", "CM-01"]),
    ("https://arxiv.org/abs/2504.09737", ["CM-05"]),
    ("https://arxiv.org/abs/2407.18370", ["HS-02"]),
    ("[link withheld]", ["F26-02", "IP-02"]),
    ("https://www.pnas.org/doi/10.1073/pnas.2518075122", ["AQ-02"]),
    ("https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32024L2831", ["CG-07", "CG-08", "CG-09", "CG-10"]),
]
for url, ids in CARD_CHIPS:
    anchor = f'<div class="research-links"><a href="{url}" target="_blank" rel="noreferrer">Primary source ↗</a>'
    chips = "".join(chip(i) for i in ids)
    t = sub_once(t, anchor, chips.join(['<div class="chip-row" style="margin-bottom:10px">', f'</div>{anchor}']), f"research card {ids[0]}")

# open-problem card gets a gap chip
t = sub_once(
    t,
    '<div class="research-links"><a href="documents/view/research-atlas.html" target="_blank" rel="noreferrer">Primary source ↗</a>',
    f'<div class="chip-row" style="margin-bottom:10px">{gapchip("gap-01", "GAP-01 · unmeasured")}</div>'
    '<div class="research-links"><a href="documents/view/research-atlas.html" target="_blank" rel="noreferrer">Primary source ↗</a>',
    "research open-problem card")

t = sub_once(
    t,
    '<p>Each card gives the finding, the design consequence, and the main caveat. Open the local domain report for the full evidence trail.</p>',
    '<p>Each card gives the finding, the design consequence, and the main caveat. Every tag opens the claim’s entry in the <a href="evidence.html">evidence ledger</a> — source, quotes, both verification layers, and its decision-use grade (A durable · B current-gen · C superseded magnitude). Open the local domain report for the full evidence trail.</p>',
    "research intro")
t = sub_once(
    t,
    '<div class="callout warning"><strong>Transfer caveat.</strong> Nearly all published judge benchmarks grade model outputs. This product grades human evaluative writeups about model outputs. The architecture transfers plausibly; the headline accuracies do not transfer automatically.</div>',
    '<div class="callout warning"><strong>Transfer caveat.</strong> Nearly all published judge benchmarks grade model outputs. This product grades human evaluative writeups about model outputs. The architecture transfers plausibly; the headline accuracies do not transfer automatically.</div>\n  <div class="callout danger"><strong>Capability-currency caveat.</strong> These decisions would be executed with deployment-tier models — Claude Fable / Opus 4.8 class, GPT-5.5 / 5.6 class — and <a href="evidence.html">zero published measurements</a> test that tier on this task. Numbers below carry decision-use grades: durable results (law, statistics, human science, adversarial floors) can be decided on now; capability-dependent magnitudes — in either direction — are priors that the pilot bakeoff re-measures on the deployment tier before any threshold is set.</div>',
    "research capability callout")
p.write_text(t, encoding="utf-8")
print("research.html: 14 cards chipped + capability callout")

# ---------------------------------------------------------------- index.html
p = SITE / "index.html"
t = p.read_text(encoding="utf-8")
INDEX_CHIPS = [
    ('<a href="research.html">See evidence and caveat →</a>', ["AJ-03"]),
    ('<a href="research.html">See the rubric evidence →</a>', ["AJ-04"]),
    ('<a href="research.html">See the human-loop evidence →</a>', ["CM-03"]),
    ('<a href="research.html">See the grounding evidence →</a>', ["GF-07"]),
    ('<a href="research.html">See the feedback evidence →</a>', ["CM-05"]),
]
for anchor, ids in INDEX_CHIPS:
    chips = "".join(chip(i) for i in ids)
    t = sub_once(t, anchor, f'<div class="chip-row" style="margin-bottom:8px">{chips}</div>{anchor}', f"index card {ids[0]}")
t = sub_once(
    t,
    '<a href="research.html#research-gaps">See what remains unknown →</a>',
    f'<div class="chip-row" style="margin-bottom:8px">{gapchip("gap-01", "GAP-01 · unmeasured")}</div><a href="research.html#research-gaps">See what remains unknown →</a>',
    "index open-problem card")

t = sub_once(
    t,
    '<div class="decision-list">\n      <div class="decision-row"><span class="check">✓</span><strong>Choose the construct</strong>',
    '<div class="decision-list" id="decision">\n      <div class="decision-row"><span class="check">✓</span><strong>Choose the construct</strong>',
    "index decision anchor", count=1) if '<div class="decision-list">\n      <div class="decision-row"><span class="check">✓</span><strong>Choose the construct</strong>' in t else t
# robust fallback: add link line after the section head paragraph
t = sub_once(
    t,
    '<p>The first goal is to determine where AutoQA is more valid, more consistent, and cheaper than the current review layer—and where it should abstain.</p>',
    '<p>The first goal is to determine where AutoQA is more valid, more consistent, and cheaper than the current review layer—and where it should abstain. Each ask below — with its options, evidence, reversibility, and failure condition — lives in the <a href="decisions.html">decision register</a>.</p>',
    "index decisions link")
t = sub_once(
    t,
    '<div class="hero-actions" style="margin-top:28px"><a class="button" href="pilot.html">Open the pilot and launch gates</a>',
    '<div class="hero-actions" style="margin-top:28px"><a class="button" href="decisions.html">Open the decision register</a><a class="button button-secondary" href="pilot.html">Open the pilot and launch gates</a>',
    "index hero actions")
t = sub_once(
    t,
    '<p>Several findings are strong enough to shape the foundation. The exact performance on human evaluative writeups remains an in-house measurement problem.</p>',
    '<p>Several findings are strong enough to shape the foundation. The exact performance on human evaluative writeups remains an in-house measurement problem — and no published study tests the deployment-tier models this program would actually run (Claude Fable / Opus 4.8 class, GPT-5.5 / 5.6 class) on this task. Every number carries a decision-use grade in the <a href="evidence.html">evidence ledger</a>; capability-dependent magnitudes are re-measured at the bakeoff before they set any threshold.</p>',
    "index capability sentence")
p.write_text(t, encoding="utf-8")
print("index.html: chipped + decision links + capability sentence")

# ---------------------------------------------------------------- brief.html
p = SITE / "brief.html"
t = p.read_text(encoding="utf-8")
t = sub_once(
    t,
    '<p>Raw agreement exceeded chance-corrected agreement by this amount in one 2026 multi-judge study.</p>',
    f'<p>Raw agreement exceeded chance-corrected agreement by this amount in one 2026 multi-judge study.</p><div class="chip-row" style="justify-content:center">{chip("AJ-03")}</div>',
    "brief slide 4")
t = sub_once(
    t,
    '<p>Evidence-assisted selective hybrid performance in one fact-verification study, versus 87.7% AI alone.</p>',
    f'<p>Evidence-assisted selective hybrid performance in one fact-verification study, versus 87.7% AI alone.</p><div class="chip-row" style="justify-content:center">{chip("CM-03")}</div>',
    "brief slide 6")
t = sub_once(
    t,
    '<div class="brief-card" style="margin-top:28px"><strong>The honest caveat</strong><p>No direct public benchmark exists for warranted positive praise in human evaluative writeups. That is the first in-house benchmark.</p></div>',
    f'<div class="brief-card" style="margin-top:28px"><strong>The honest caveat</strong><p>No direct public benchmark exists for warranted positive praise in human evaluative writeups. That is the first in-house benchmark.</p><div class="chip-row">{gapchip("gap-01", "GAP-01 · the moat is unmeasured")}</div></div>',
    "brief slide 7")
t = sub_once(
    t,
    '<div class="brief-card"><strong>Shadow</strong><p>Prove calibrated risk–coverage before granting authority.</p></div></div></div>',
    '<div class="brief-card"><strong>Shadow</strong><p>Prove calibrated risk–coverage before granting authority.</p></div></div><p style="margin-top:26px"><a href="decisions.html" style="color:inherit">Every decision, its evidence, and its flip condition: the decision register →</a></p></div>',
    "brief slide 10")
p.write_text(t, encoding="utf-8")
print("brief.html: chipped")

# ---------------------------------------------------------------- pilot.html
p = SITE / "pilot.html"
t = p.read_text(encoding="utf-8")

t = sub_once(
    t,
    '<div class="section-head"><div><span class="eyebrow">Risk register</span><h2>The system is designed around its own fallibility.</h2></div><p>These are monitored failure modes, not footnotes.</p></div>',
    '<div class="section-head" id="risks"><div><span class="eyebrow">Risk register</span><h2>The system is designed around its own fallibility.</h2></div><p>These are monitored failure modes, not footnotes. The Ledger column ties each risk to the measured evidence that makes it a design constraint rather than an opinion.</p></div>',
    "pilot risks anchor")
t = sub_once(
    t,
    '<table class="metric-table"><thead><tr><th>Risk</th><th>Control</th><th>Sensor</th></tr></thead><tbody>\n      <tr><td>Consistent but invalid judge</td>',
    '<table class="metric-table"><thead><tr><th>Risk</th><th>Control</th><th>Sensor</th><th>Ledger</th></tr></thead><tbody>\n      <tr><td>Consistent but invalid judge</td>',
    "pilot risk table header")
RISK_CHIPS = [
    ('<td>Validity by criterion and agreement stratum.</td>', ["AJ-03", "AJ-02"]),
    ('<td>Anchoring A/B and overturn quality.</td>', ["CT-02", "CM-03"]),
    ('<td>Disagreement clusters and appeal themes.</td>', ["RR-05", "CT-04"]),
    ('<td>AutoQA score rises while gold score stays flat.</td>', ["CT-09", "F26-03", "AQ-02"]),
    ('<td>Error-overlap and judge–generator similarity.</td>', ["CT-05", "AJ-08"]),
    ('<td>False-accusation rate and new-defect rate.</td>', ["CM-08", "CM-07"]),
    ('<td>Performance by difficulty and expert slice.</td>', ["AJ-11", "CT-08"]),
    ('<td>Appeal outcomes, adverse-action audit, legal review.</td>', ["CG-07", "CG-11"]),
]
for cell, ids in RISK_CHIPS:
    chips = "".join(chip(i) for i in ids)
    t = sub_once(t, cell + "</tr>", f'{cell}<td><div class="chip-row" style="margin-top:0">{chips}</div></td></tr>', f"pilot risk row {ids[0]}")

t = sub_once(
    t,
    '<li>Robustness to paraphrase, order, and evidence-swap probes.</li><li>Random audits of confident passes remain active.</li></ul></article>',
    f'<li>Robustness to paraphrase, order, and evidence-swap probes.</li><li>Random audits of confident passes remain active.</li></ul><div class="chip-row">{chip("GF-10")}{chip("CM-02")}</div></article>',
    "pilot acceptance gate chips")
t = sub_once(
    t,
    '<li>Meaningful human review where consequences or law require it.</li></ul></article>',
    f'<li>Meaningful human review where consequences or law require it.</li></ul><div class="chip-row">{chip("F26-04")}{chip("CG-07")}{chip("CG-11")}</div></article>',
    "pilot rejection gate chips")
t = sub_once(
    t,
    '<p>Engineering is not the scarce resource at the start. Aligned examples and decision rights are.</p>',
    '<p>Engineering is not the scarce resource at the start. Aligned examples and decision rights are. Each ask — options, evidence, reversibility, failure condition — lives in the <a href="decisions.html">decision register</a>.</p>',
    "pilot decisions link")
t = sub_once(
    t,
    '<article class="pilot-gate"><div><h3>Run model and architecture bakeoffs</h3><p>Compare deterministic checks, specialist verifiers, frontier reasoning models, reference timing, decomposition granularity, cross-family challengers, and confidence signals by criterion family.</p></div>',
    '<article class="pilot-gate"><div><h3>Run model and architecture bakeoffs</h3><p>Compare deterministic checks, specialist verifiers, frontier reasoning models, reference timing, decomposition granularity, cross-family challengers, and confidence signals by criterion family — on the deployment-tier set (Claude Fable / Opus 4.8 class, GPT-5.5 / 5.6 class, cross-family). No published anchor covers these models on this task; this gate produces the numbers the literature cannot.</p></div>',
    "pilot bakeoff deployment tier")
p.write_text(t, encoding="utf-8")
print("pilot.html: risk table + gates chipped + bakeoff tier")

# ---------------------------------------------------------------- architecture.html
p = SITE / "architecture.html"
t = p.read_text(encoding="utf-8")
t = sub_once(
    t,
    '<div class="section-head"><div><span class="eyebrow">Claim ontology</span>',
    '<div class="section-head" id="ontology"><div><span class="eyebrow">Claim ontology</span>',
    "architecture ontology anchor")
ONT_CHIPS = [
    ('<td>Span-closed entailment plus source-quality check.</td>', ["GF-01", "GF-07"]),
    ('<td>Reasoning judge constrained to the evidence record.</td>', ["GF-03"]),
    ('<td>Explicit expected-element checklist; “not contradicted” unless seeded recall is proven.</td>', ["CM-06"]),
    ('<td>Never truth-score the opinion; assess contradiction and warrant.</td>', ["GF-05"]),
    ('<td>Unknown or escalation—not a forced pass or fail.</td>', ["AJ-02", "F26-08"]),
]
for cell, ids in ONT_CHIPS:
    chips = "".join(chip(i) for i in ids)
    t = sub_once(t, cell, cell[:-5] + f'<div class="chip-row" style="margin-top:6px">{chips}</div></td>', f"arch ontology {ids[0]}")
t = sub_once(
    t,
    '<p>Run deterministic checks, grounding checkers, reasoning judges, context-closed evidence checks, and challenge passes.</p></article><article class="system-row"><span class="step">4</span>',
    f'<p>Run deterministic checks, grounding checkers, reasoning judges, context-closed evidence checks, and challenge passes.</p><div class="chip-row">{chip("F26-01")}</div></article><article class="system-row"><span class="step">4</span>',
    "arch verify-lane chip")
t = sub_once(
    t,
    '<div class="callout warning" style="margin-top:20px"><strong>Package rule:</strong> autonomous acceptance or rejection should not be enabled below Level B.</div>',
    f'<div class="callout warning" style="margin-top:20px"><strong>Package rule:</strong> autonomous acceptance or rejection should not be enabled below Level B. Where consequences reach EU workers, the human floor is law, not policy. <span class="chip-row" style="display:inline-flex; margin:0 0 0 6px; vertical-align:middle">{chip("CG-07")}{chip("CG-11")}</span></div>',
    "arch conformance chips")
p.write_text(t, encoding="utf-8")
print("architecture.html: ontology + pipeline chipped")

# ---------------------------------------------------------------- README.md
p = SITE / "README.md"
t = p.read_text(encoding="utf-8")
t = sub_once(
    t,
    "- `pilot.html` — pilot, metrics, launch gates, and risk register",
    "- `pilot.html` — pilot, metrics, launch gates, and risk register\n- `decisions.html` — decision register: authorizations, open calls, defaults, flip conditions\n- `evidence.html` — evidence ledger: all 132 corpus claims with two verification layers\n- `assets/claims.json` — machine-readable ledger (claims, sources, verdicts, usage)",
    "README contents")
t = t.replace("Generated 2026-07-15.", "Generated 2026-07-15. Evidence ledger and decision register added, all claims re-verified against their primary sources, and the site manifest regenerated the same day.")
p.write_text(t, encoding="utf-8")
print("README.md updated")
