verify_captions.py

assets/boards/flores_island/BRD_0001/verify_captions.py

#!/usr/bin/env python3
"""Re-prove the six BRD_0001 caption rewrites, mechanically, from the repo's own modules.

Josh's work-order (handoff 8.15c tail) was that the six Flores caption refusals be cleared by
REWRITING the captions and never by loosening the gate. That claim is only worth what a re-run of
it proves, so this runner asserts all four halves of it and exits non-zero on any of them:

  1. THE BAR IS NOT RE-TYPED. The limit is read from `photobook.VISIBLE_BLOCK_MAX`, the module that
     owns it, so this file contains no number that could be raised to make the board pass.
  2. THE SIX BLOCKS PASS AS WRITTEN. Each published subject body is measured exactly as the page
     emits it -- through `render_board.publishable()` and html escaping -- and handed to
     `photobook.prose_gate` itself rather than to a length test that would measure the wrong thing.
  3. THE FOLD NO LONGER CATCHES THEM. The published page is rendered with a no-op image stager and
     must contain zero `<details class="more">` folds, and the gate sweep over the emitted page must
     be clean BOTH as emitted and with the folds bypassed. A page that is clean only because a fold
     hides the block is exactly the posture Josh's order superseded, and this separates the two.
  4. NOTHING JOSH GRADED IS UNRECOVERABLE. Every original in CAPTION_ORIGINALS_2026-08-10.json
     re-hashes to its recorded sha256, and every recorded rewrite is byte-identical to what
     content.json holds now.

Usage: python docs/art_boards/flores_island/BRD_0001/verify_captions.py
"""
import json
import re
import sys
import hashlib
from pathlib import Path

HERE = Path(__file__).resolve().parent
ROOT = HERE.parents[3]
sys.path.insert(0, str(ROOT / "harness" / "boards"))

import render_board as RB          # noqa: E402
import photobook                   # noqa: E402  (imported by render_board's own path insert)

BOARD = "BRD_0001"
SIDECAR = HERE / "CAPTION_ORIGINALS_2026-08-10.json"


def bodies(content):
    """The six published subject bodies, in the order `_panel_published()` emits them."""
    for letter in ("A", "B"):
        for i, opt in enumerate(content["panels"][letter]["options"]):
            key = "rationale" if opt.get("rationale") else "what_was_amplified"
            yield f"panels.{letter}.options[{i}].{key}", opt["id"], opt[key]


def main():
    fails = []
    limit = photobook.VISIBLE_BLOCK_MAX
    b, _out_dir, content, plates = RB._panel_context(BOARD)

    # ---- (2) every published body passes the gate AS WRITTEN ------------------------------------
    print(f"gate: photobook.prose_gate, VISIBLE_BLOCK_MAX = {limit}")
    for path, oid, raw in bodies(content):
        body, held = RB.publishable(raw)
        vis = photobook._plain(RB.E(body))
        hits = photobook.prose_gate(f"<body><p>{RB.E(body)}</p></body>", path)
        verdict = "REFUSED" if hits else "pass"
        print(f"  {oid} {path}: {len(vis)} visible chars -- {verdict}")
        if hits:
            fails.append(f"{path} is over the bar as written ({len(vis)} chars)")
        if held:
            fails.append(f"{path} is WITHHELD by the firewall: {held}")

    # ---- (3) the page renders, folds nothing, and sweeps clean with folds bypassed ---------------
    pub, _rec = RB._panel_published(content, plates, BOARD, b["subject_canon_id"],
                                    lambda src, key, max_w=None: None, "E:/art/boards")
    folds = len(re.findall(r'<details class="more">', pub))
    emitted = photobook.prose_gate(pub, BOARD)
    bypass = re.sub(r'<details class="more"><summary>.*?</summary>', "", pub, flags=re.S)
    bypass = bypass.replace("</details>", "")
    bypassed = photobook.prose_gate(bypass, f"{BOARD}<fold-bypassed>")
    print(f"page: {len(pub)} bytes, {folds} fold(s), {len(emitted)} finding(s) as emitted, "
          f"{len(bypassed)} with folds bypassed")
    if folds:
        fails.append(f"{folds} caption(s) still need the fold on the published page")
    for hit in emitted + bypassed:
        fails.append(f"prose gate refused {hit[1]} ({hit[3]} chars): {hit[4][:80]!r}")

    # ---- (4) the graded originals are recoverable ------------------------------------------------
    rec = json.loads(SIDECAR.read_text(encoding="utf-8"))
    live = {p: raw for p, _oid, raw in bodies(content)}
    for row in rec["captions"]:
        sha = hashlib.sha256(row["original_text"].encode("utf-8")).hexdigest()
        if sha != row["original_sha256"]:
            fails.append(f"{row['leaf_path']}: recorded original does not match its sha256")
        if live.get(row["leaf_path"]) != row["rewritten_text"]:
            fails.append(f"{row['leaf_path']}: content.json has drifted from the recorded rewrite")
    print(f"record: {len(rec['captions'])} original(s) verified against "
          f"{SIDECAR.name}")

    if fails:
        print("\nFAIL")
        for f in fails:
            print(f"  - {f}")
        return 1
    print("\nOK -- six captions inside the bar as written, no fold needed, originals recoverable")
    return 0


if __name__ == "__main__":
    sys.exit(main())

Generated by harness/site/structure_site.py — the URL path is the repo path. review root