#!/usr/bin/env python3
"""Bank batch-259: Rule 217 low-frequency body-part reference lexical expansion."""

from __future__ import annotations

import datetime as dt
import json
import re
import sqlite3

from process_ledger import ensure_schema, record_event

DB = "/mnt/donto-data/donto-resources/research/translation-training/kuku-yalanji-runpod-2026-06-30/synthetic/claude-synthetic-v1-2026-07-02/synthetic.db"
LABEL = "batch-259"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
PROCESS_LOG = "process_logs/batch-259-low-frequency-body-part-reference-lexical-expansion-after-rule216-process.md"

TARGET_HEADS = {
    "barrkar": "upper jaw",
    "baru": "lap",
    "jaljan": "pharynx",
    "jamalka": "shoulder blade",
    "jinbar": "wrist",
    "kabari": "armpit",
    "kuburrubun": "crown",
    "makal": "calf muscles",
    "mirrimar": "rib",
    "mudu": "lower back",
}
SUPPORT = {"yinya", "yaluy", "yinyay"}
DENY_KUKU = {
    "ngayu", "nyulu", "yundu", "jana", "ngana", "nganya", "yununy", "nyunguny",
    "ngayku", "nyungu", "nyunba", "janangan", "kari", "kuli", "kaka", "bambay",
    "badi", "badin", "badil", "nyaji", "nyajin", "nyajil", "nuka", "nukal", "nukan",
    "dungay", "dungan", "kaday", "kadan", "karrba", "karrban", "balka", "balkan",
    "bajaku", "mara", "milka", "miyil", "jina", "bangkarr", "dukul", "ngandal",
    "wubul", "muku", "jibar", "jiba", "dirra", "yala", "yanyu", "bama", "mayi", "minya",
}
DENY_ENGLISH = (
    "my", "your", "his", "her", "their", "person's", "body", "body part", "pain", "sore", "sickness",
    "sick", "medicine", "heal", "healing", "cut", "cuts", "broken", "blood", "bleeding", "scar",
    "initiation", "mark", "pierced", "bone", "flesh", "animal", "beast", "tail", "wing", "shell",
    "tree", "river", "side of", "hair", "mucus", "discharge", "saliva", "fluid", "eat", "eating",
    "butcher", "butchery", "carry", "holding", "touch", "touching",
)


def js(values: list[str]) -> str:
    return json.dumps(values, ensure_ascii=False)


def row(
    seq: int,
    english: str,
    kuku: str,
    analysis: str,
    frame: str,
    words: list[str],
    evidence: str,
) -> tuple:
    return (seq, english, kuku, analysis, frame, 2, js(words), js([]), evidence, "0.86")


ROWS = [
    row(1, "The upper jaw is here.", "Barrkar yaluy.", "barrkar yaluy | upper.jaw here", "r217_body_ref_here_barrkar", ["barrkar", "yaluy"], "Dictionary barrkar noun 'upper jaw'; Patz section 3.1 nouns include body parts; Patz section 3.7 yaluy 'here'."),
    row(2, "The lap is here.", "Baru yaluy.", "baru yaluy | lap here", "r217_body_ref_here_baru", ["baru", "yaluy"], "Dictionary baru noun 'lap'; possession/use prose closed; Patz section 3.7 yaluy."),
    row(3, "The pharynx is here.", "Jaljan yaluy.", "jaljan yaluy | pharynx here", "r217_body_ref_here_jaljan", ["jaljan", "yaluy"], "Dictionary jaljan noun 'pharynx'; illness/anatomy-event prose closed; Patz section 3.7 yaluy."),
    row(4, "The shoulder blade is here.", "Jamalka yaluy.", "jamalka yaluy | shoulder.blade here", "r217_body_ref_here_jamalka", ["jamalka", "yaluy"], "Dictionary jamalka noun 'shoulder blade'; Patz section 3.7 yaluy."),
    row(5, "The wrist is here.", "Jinbar yaluy.", "jinbar yaluy | wrist here", "r217_body_ref_here_jinbar", ["jinbar", "yaluy"], "Dictionary jinbar noun 'wrist'; Patz section 3.7 yaluy 'here'."),
    row(6, "The armpit is here.", "Kabari yaluy.", "kabari yaluy | armpit here", "r217_body_ref_here_kabari", ["kabari", "yaluy"], "Dictionary kabari noun 'armpit'; Patz section 3.7 yaluy."),
    row(7, "The crown of the head is here.", "Kuburrubun yaluy.", "kuburrubun yaluy | crown.of.head here", "r217_body_ref_here_kuburrubun", ["kuburrubun", "yaluy"], "Dictionary kuburrubun noun 'crown of head'; Patz section 3.7 yaluy."),
    row(8, "The calf muscles are here.", "Makal yaluy.", "makal yaluy | calf.muscles here", "r217_body_ref_here_makal", ["makal", "yaluy"], "Dictionary makal noun 'muscles of calf on leg'; Patz section 3.7 yaluy; no plural morphology opened."),
    row(9, "The rib is here.", "Mirrimar yaluy.", "mirrimar yaluy | rib here", "r217_body_ref_here_mirrimar", ["mirrimar", "yaluy"], "Dictionary mirrimar noun 'rib'; Patz section 3.7 yaluy."),
    row(10, "The lower back is here.", "Mudu yaluy.", "mudu yaluy | lower.back here", "r217_body_ref_here_mudu", ["mudu", "yaluy"], "Dictionary mudu noun 'lower back'; Patz section 3.7 yaluy."),
    row(11, "The upper jaw is there.", "Barrkar yinyay.", "barrkar yinyay | upper.jaw there", "r217_body_ref_there_barrkar", ["barrkar", "yinyay"], "Dictionary barrkar noun 'upper jaw'; Patz section 3.7 yinyay 'there'."),
    row(12, "The lap is there.", "Baru yinyay.", "baru yinyay | lap there", "r217_body_ref_there_baru", ["baru", "yinyay"], "Dictionary baru noun 'lap'; Patz section 3.7 yinyay."),
    row(13, "The pharynx is there.", "Jaljan yinyay.", "jaljan yinyay | pharynx there", "r217_body_ref_there_jaljan", ["jaljan", "yinyay"], "Dictionary jaljan noun 'pharynx'; Patz section 3.7 yinyay."),
    row(14, "The shoulder blade is there.", "Jamalka yinyay.", "jamalka yinyay | shoulder.blade there", "r217_body_ref_there_jamalka", ["jamalka", "yinyay"], "Dictionary jamalka noun 'shoulder blade'; Patz section 3.7 yinyay."),
    row(15, "The wrist is there.", "Jinbar yinyay.", "jinbar yinyay | wrist there", "r217_body_ref_there_jinbar", ["jinbar", "yinyay"], "Dictionary jinbar noun 'wrist'; Patz section 3.7 yinyay."),
    row(16, "The armpit is there.", "Kabari yinyay.", "kabari yinyay | armpit there", "r217_body_ref_there_kabari", ["kabari", "yinyay"], "Dictionary kabari noun 'armpit'; Patz section 3.7 yinyay."),
    row(17, "The crown of the head is there.", "Kuburrubun yinyay.", "kuburrubun yinyay | crown.of.head there", "r217_body_ref_there_kuburrubun", ["kuburrubun", "yinyay"], "Dictionary kuburrubun noun 'crown of head'; Patz section 3.7 yinyay."),
    row(18, "The calf muscles are there.", "Makal yinyay.", "makal yinyay | calf.muscles there", "r217_body_ref_there_makal", ["makal", "yinyay"], "Dictionary makal noun 'calf muscles'; no number morphology opened; Patz section 3.7 yinyay."),
    row(19, "The rib is there.", "Mirrimar yinyay.", "mirrimar yinyay | rib there", "r217_body_ref_there_mirrimar", ["mirrimar", "yinyay"], "Dictionary mirrimar noun 'rib'; Patz section 3.7 yinyay."),
    row(20, "The lower back is there.", "Mudu yinyay.", "mudu yinyay | lower.back there", "r217_body_ref_there_mudu", ["mudu", "yinyay"], "Dictionary mudu noun 'lower back'; Patz section 3.7 yinyay."),
    row(21, "That upper jaw is there.", "Yinya barrkar yinyay.", "yinya barrkar yinyay | that upper.jaw there", "r217_that_body_ref_there_barrkar", ["yinya", "barrkar", "yinyay"], "Patz section 3.7 yinya can co-occur with a noun; dictionary barrkar noun 'upper jaw'."),
    row(22, "That lap is there.", "Yinya baru yinyay.", "yinya baru yinyay | that lap there", "r217_that_body_ref_there_baru", ["yinya", "baru", "yinyay"], "Patz section 3.7 yinya with noun; dictionary baru noun 'lap'."),
    row(23, "That pharynx is there.", "Yinya jaljan yinyay.", "yinya jaljan yinyay | that pharynx there", "r217_that_body_ref_there_jaljan", ["yinya", "jaljan", "yinyay"], "Patz section 3.7 yinya with noun; dictionary jaljan noun 'pharynx'."),
    row(24, "That shoulder blade is there.", "Yinya jamalka yinyay.", "yinya jamalka yinyay | that shoulder.blade there", "r217_that_body_ref_there_jamalka", ["yinya", "jamalka", "yinyay"], "Patz section 3.7 yinya with noun; dictionary jamalka noun 'shoulder blade'."),
    row(25, "That wrist is there.", "Yinya jinbar yinyay.", "yinya jinbar yinyay | that wrist there", "r217_that_body_ref_there_jinbar", ["yinya", "jinbar", "yinyay"], "Patz section 3.7 yinya with noun; dictionary jinbar noun 'wrist'."),
    row(26, "That armpit is there.", "Yinya kabari yinyay.", "yinya kabari yinyay | that armpit there", "r217_that_body_ref_there_kabari", ["yinya", "kabari", "yinyay"], "Patz section 3.7 yinya with noun; dictionary kabari noun 'armpit'."),
    row(27, "That crown of the head is there.", "Yinya kuburrubun yinyay.", "yinya kuburrubun yinyay | that crown.of.head there", "r217_that_body_ref_there_kuburrubun", ["yinya", "kuburrubun", "yinyay"], "Patz section 3.7 yinya with noun; dictionary kuburrubun noun 'crown of head'."),
    row(28, "Those calf muscles are there.", "Yinya makal yinyay.", "yinya makal yinyay | those calf.muscles there", "r217_that_body_ref_there_makal", ["yinya", "makal", "yinyay"], "Patz section 3.7 yinya can imply plural by context; dictionary makal noun 'calf muscles'."),
    row(29, "That rib is there.", "Yinya mirrimar yinyay.", "yinya mirrimar yinyay | that rib there", "r217_that_body_ref_there_mirrimar", ["yinya", "mirrimar", "yinyay"], "Patz section 3.7 yinya with noun; dictionary mirrimar noun 'rib'."),
    row(30, "That lower back is there.", "Yinya mudu yinyay.", "yinya mudu yinyay | that lower.back there", "r217_that_body_ref_there_mudu", ["yinya", "mudu", "yinyay"], "Patz section 3.7 yinya with noun; dictionary mudu noun 'lower back'."),
    row(31, "That upper jaw is there.", "Barrkar yinya yinyay.", "barrkar yinya yinyay | that upper.jaw there", "r217_body_that_there_barrkar", ["barrkar", "yinya", "yinyay"], "Patz section 3.7 yinya can follow a noun; dictionary barrkar noun 'upper jaw'."),
    row(32, "That lap is there.", "Baru yinya yinyay.", "baru yinya yinyay | that lap there", "r217_body_that_there_baru", ["baru", "yinya", "yinyay"], "Patz section 3.7 yinya can follow a noun; dictionary baru noun 'lap'."),
    row(33, "That pharynx is there.", "Jaljan yinya yinyay.", "jaljan yinya yinyay | that pharynx there", "r217_body_that_there_jaljan", ["jaljan", "yinya", "yinyay"], "Patz section 3.7 yinya can follow a noun; dictionary jaljan noun 'pharynx'."),
    row(34, "That shoulder blade is there.", "Jamalka yinya yinyay.", "jamalka yinya yinyay | that shoulder.blade there", "r217_body_that_there_jamalka", ["jamalka", "yinya", "yinyay"], "Patz section 3.7 yinya can follow a noun; dictionary jamalka noun 'shoulder blade'."),
    row(35, "That wrist is there.", "Jinbar yinya yinyay.", "jinbar yinya yinyay | that wrist there", "r217_body_that_there_jinbar", ["jinbar", "yinya", "yinyay"], "Patz section 3.7 yinya can follow a noun; dictionary jinbar noun 'wrist'."),
    row(36, "That armpit is there.", "Kabari yinya yinyay.", "kabari yinya yinyay | that armpit there", "r217_body_that_there_kabari", ["kabari", "yinya", "yinyay"], "Patz section 3.7 yinya can follow a noun; dictionary kabari noun 'armpit'."),
    row(37, "That crown of the head is there.", "Kuburrubun yinya yinyay.", "kuburrubun yinya yinyay | that crown.of.head there", "r217_body_that_there_kuburrubun", ["kuburrubun", "yinya", "yinyay"], "Patz section 3.7 yinya can follow a noun; dictionary kuburrubun noun 'crown of head'."),
    row(38, "Those calf muscles are there.", "Makal yinya yinyay.", "makal yinya yinyay | those calf.muscles there", "r217_body_that_there_makal", ["makal", "yinya", "yinyay"], "Patz section 3.7 yinya can follow a noun and imply plural by context; dictionary makal noun 'calf muscles'."),
    row(39, "That rib is there.", "Mirrimar yinya yinyay.", "mirrimar yinya yinyay | that rib there", "r217_body_that_there_mirrimar", ["mirrimar", "yinya", "yinyay"], "Patz section 3.7 yinya can follow a noun; dictionary mirrimar noun 'rib'."),
    row(40, "That lower back is there.", "Mudu yinya yinyay.", "mudu yinya yinyay | that lower.back there", "r217_body_that_there_mudu", ["mudu", "yinya", "yinyay"], "Patz section 3.7 yinya can follow a noun; dictionary mudu noun 'lower back'."),
    row(41, "That upper jaw is here.", "Yinya barrkar yaluy.", "yinya barrkar yaluy | that upper.jaw here", "r217_that_body_ref_here_barrkar", ["yinya", "barrkar", "yaluy"], "Patz section 3.7 yinya with noun; dictionary barrkar noun 'upper jaw'; yaluy 'here'."),
    row(42, "That lap is here.", "Yinya baru yaluy.", "yinya baru yaluy | that lap here", "r217_that_body_ref_here_baru", ["yinya", "baru", "yaluy"], "Patz section 3.7 yinya with noun; dictionary baru noun 'lap'; yaluy 'here'."),
    row(43, "That pharynx is here.", "Yinya jaljan yaluy.", "yinya jaljan yaluy | that pharynx here", "r217_that_body_ref_here_jaljan", ["yinya", "jaljan", "yaluy"], "Patz section 3.7 yinya with noun; dictionary jaljan noun 'pharynx'."),
    row(44, "That shoulder blade is here.", "Yinya jamalka yaluy.", "yinya jamalka yaluy | that shoulder.blade here", "r217_that_body_ref_here_jamalka", ["yinya", "jamalka", "yaluy"], "Patz section 3.7 yinya with noun; dictionary jamalka noun 'shoulder blade'."),
    row(45, "That wrist is here.", "Yinya jinbar yaluy.", "yinya jinbar yaluy | that wrist here", "r217_that_body_ref_here_jinbar", ["yinya", "jinbar", "yaluy"], "Patz section 3.7 yinya with noun; dictionary jinbar noun 'wrist'."),
    row(46, "That armpit is here.", "Yinya kabari yaluy.", "yinya kabari yaluy | that armpit here", "r217_that_body_ref_here_kabari", ["yinya", "kabari", "yaluy"], "Patz section 3.7 yinya with noun; dictionary kabari noun 'armpit'."),
    row(47, "That crown of the head is here.", "Yinya kuburrubun yaluy.", "yinya kuburrubun yaluy | that crown.of.head here", "r217_that_body_ref_here_kuburrubun", ["yinya", "kuburrubun", "yaluy"], "Patz section 3.7 yinya with noun; dictionary kuburrubun noun 'crown of head'."),
    row(48, "Those calf muscles are here.", "Yinya makal yaluy.", "yinya makal yaluy | those calf.muscles here", "r217_that_body_ref_here_makal", ["yinya", "makal", "yaluy"], "Patz section 3.7 yinya can imply plural by context; dictionary makal noun 'calf muscles'."),
    row(49, "That rib is here.", "Yinya mirrimar yaluy.", "yinya mirrimar yaluy | that rib here", "r217_that_body_ref_here_mirrimar", ["yinya", "mirrimar", "yaluy"], "Patz section 3.7 yinya with noun; dictionary mirrimar noun 'rib'."),
    row(50, "That lower back is here.", "Yinya mudu yaluy.", "yinya mudu yaluy | that lower.back here", "r217_that_body_ref_here_mudu", ["yinya", "mudu", "yaluy"], "Patz section 3.7 yinya with noun; dictionary mudu noun 'lower back'."),
]


def has_token(low: str, token: str) -> bool:
    return re.search(rf"(?<![a-z-]){re.escape(token)}(?![a-z-])", low) is not None


def has_target_morphology(low: str, head: str) -> bool:
    suffixes = "ngka|ngku|angka|nga|ngu|ba|mba|mbu|muny|darr|burr|bu|ka|nka|nku|ji|jirr|ku|mundu|amu|mu|iji|nda|ndu|anda|undu|unji|nji|kari|baka|baja|bungal|bungan|mal|man|rriny"
    return re.search(rf"(?<![a-z-]){re.escape(head)}-(?:{suffixes})\b", low) is not None


def english_has_denied(english_low: str, denied: str) -> bool:
    return denied in english_low if " " in denied else re.search(rf"\b{re.escape(denied.strip())}\b", english_low) is not None


def scan_static() -> list[str]:
    issues: list[str] = []
    if len(ROWS) != 50:
        issues.append(f"{LABEL}: expected 50 rows, found {len(ROWS)}")
    seen_ku: set[str] = set()
    for expected, row_data in enumerate(ROWS, start=1):
        seq, english, kuku, analysis, frame, _tier, words_used, loans_used, evidence, confidence = row_data
        label = f"{LABEL}.{seq:02d}"
        low = kuku.lower()
        english_low = english.lower()
        words = json.loads(words_used)
        if seq != expected:
            issues.append(f"{label}: sequence mismatch; expected {expected}")
        if not english[:1].isupper() or english[-1:] not in ".!?":
            issues.append(f"{label}: English punctuation/capitalization failure")
        if " | " not in analysis:
            issues.append(f"{label}: analysis missing gloss separator")
        if not frame.startswith("r217_"):
            issues.append(f"{label}: Rule 217 frame must start with r217_")
        if low in seen_ku:
            issues.append(f"{label}: duplicate Kuku surface within batch")
        seen_ku.add(low)
        if json.loads(loans_used):
            issues.append(f"{label}: no loans are admitted in Rule 217")
        for denied in DENY_KUKU:
            if has_token(low, denied):
                issues.append(f"{label}: denied carry-forward token {denied!r}")
        targets = [head for head in TARGET_HEADS if has_token(low, head)]
        if len(targets) != 1:
            issues.append(f"{label}: expected exactly one Rule 217 target noun, found {targets}")
        for head in targets:
            selected = TARGET_HEADS[head]
            dotted = selected.replace("-", ".").replace(" ", ".")
            if head not in words:
                issues.append(f"{label}: target head {head} missing from words_used")
            if selected not in english_low:
                issues.append(f"{label}: English must include selected sense {selected!r}")
            if selected not in analysis and dotted not in analysis:
                issues.append(f"{label}: analysis must gloss {head} as {selected}")
            if has_target_morphology(low, head):
                issues.append(f"{label}: target head {head} has forbidden morphology")
        for support in SUPPORT:
            if has_token(low, support) and support not in words:
                issues.append(f"{label}: support {support} missing from words_used")
        if 1 <= seq <= 10 and (has_token(low, "yinya") or has_token(low, "yinyay") or not low.endswith(" yaluy.") or len(low.split()) != 2):
            issues.append(f"{label}: rows 1-10 require TARGET yaluy")
        if 11 <= seq <= 20 and (has_token(low, "yinya") or has_token(low, "yaluy") or not low.endswith(" yinyay.") or len(low.split()) != 2):
            issues.append(f"{label}: rows 11-20 require TARGET yinyay")
        if 21 <= seq <= 30 and (not low.startswith("yinya ") or has_token(low, "yaluy") or not low.endswith(" yinyay.") or len(low.split()) != 3):
            issues.append(f"{label}: rows 21-30 require Yinya TARGET yinyay")
        if 31 <= seq <= 40 and (not has_token(low, "yinya") or has_token(low, "yaluy") or not low.endswith(" yinyay.") or len(low.split()) != 3 or low.startswith("yinya ")):
            issues.append(f"{label}: rows 31-40 require TARGET yinya yinyay")
        if 41 <= seq <= 50 and (not low.startswith("yinya ") or has_token(low, "yinyay") or not low.endswith(" yaluy.") or len(low.split()) != 3):
            issues.append(f"{label}: rows 41-50 require Yinya TARGET yaluy")
        if any(english_has_denied(english_low, bad) for bad in DENY_ENGLISH):
            issues.append(f"{label}: denied possession/body-state/medical/polysemy field in English")
        if not evidence or not confidence:
            issues.append(f"{label}: missing evidence/confidence")
    return issues


def main() -> int:
    issues = scan_static()
    if issues:
        print("pre-bank scan failed:")
        for issue in issues:
            print(f"  - {issue}")
        return 1

    db = sqlite3.connect(DB)
    db.execute("PRAGMA foreign_keys = ON")
    db.execute("BEGIN")
    ensure_schema(db)
    existing = db.execute("SELECT id FROM batches WHERE label=?", (LABEL,)).fetchone()
    if existing:
        batch_id = existing[0]
        accepted = db.execute(
            "SELECT COUNT(*) FROM sentences WHERE batch_id=? AND status IN ('accepted','revised')",
            (batch_id,),
        ).fetchone()[0]
        if accepted:
            raise SystemExit(f"{LABEL} already has accepted/revised rows; refusing to overwrite")
        db.execute("DELETE FROM reviews WHERE sentence_id IN (SELECT id FROM sentences WHERE batch_id=?)", (batch_id,))
        db.execute("DELETE FROM sentences WHERE batch_id=?", (batch_id,))
        db.execute("UPDATE batches SET notes=?, created_at=? WHERE id=?", ("rebanked under_review", NOW, batch_id))
    else:
        cur = db.execute(
            "INSERT INTO batches(label, cheatsheet_version, guide_version, notes, created_at) VALUES(?,?,?,?,?)",
            (
                LABEL,
                "Rule 217 draft: low-frequency body-part reference lexical expansion after Rule 216",
                "operator-guide-2026-07-08",
                "under_review",
                NOW,
            ),
        )
        batch_id = cur.lastrowid

    dupes: list[str] = []
    for seq, _english, kuku, *_rest in ROWS:
        hit = db.execute(
            """
            SELECT b.label, s.seq
            FROM sentences s JOIN batches b ON b.id=s.batch_id
            WHERE lower(trim(s.kuku))=lower(trim(?))
              AND s.status!='rejected'
              AND s.batch_id!=?
            """,
            (kuku, batch_id),
        ).fetchone()
        if hit:
            dupes.append(f"{LABEL}.{seq:02d} duplicates {hit[0]}.{hit[1]:02d}: {kuku}")
    if dupes:
        db.rollback()
        print("cross-corpus duplicate check failed:")
        for dupe in dupes:
            print(f"  - {dupe}")
        return 1

    db.executemany(
        """
        INSERT INTO sentences(
          batch_id, seq, english, kuku, analysis, frame, tier, words_used,
          loans_used, evidence, status, confidence, author, created_at
        ) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)
        """,
        [
            (batch_id, seq, english, kuku, analysis, frame, tier, words_used, loans_used, evidence, "under_review", confidence, "claude", NOW)
            for seq, english, kuku, analysis, frame, tier, words_used, loans_used, evidence, confidence in ROWS
        ],
    )

    verified_before, words_before = db.execute(
        """
        SELECT
          COUNT(*),
          SUM(LENGTH(kuku)-LENGTH(REPLACE(kuku,' ',''))+1)
        FROM sentences
        WHERE status IN ('accepted','revised')
        """
    ).fetchone()
    under_review = db.execute(
        "SELECT COUNT(*) FROM sentences WHERE batch_id=? AND status='under_review'",
        (batch_id,),
    ).fetchone()[0]

    record_event(
        db,
        batch_label=LABEL,
        phase="source",
        event_type="source-pass",
        actor="claude-main",
        detail=(
            "Checked Patz section 3.1 noun/body-part basis, Patz section 3.7 yinya/yaluy/yinyay support, and dictionary entries "
            "for barrkar, baru, jaljan, jamalka, jinbar, kabari, kuburrubun, makal, mirrimar, and mudu. "
            "Admitted only selected bare body-part reference senses."
        ),
        artifact_path=PROCESS_LOG,
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="scope",
        event_type="candidate-rejection",
        actor="claude-main",
        detail=(
            "Selected low-frequency body-part reference only after excluding taboo, loan, dialect-only, animal-only, body-fluid, scar/initiation, "
            "medical, possession-heavy, and polysemy-heavy entries. Held murun, nyidu, nyumbul, wulurringkal, yimbi, and yinkan in reserve."
        ),
        artifact_path=PROCESS_LOG,
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="preflight",
        event_type="duplicate-preflight",
        actor="claude-main",
        detail="Exact duplicate preflight over all 50 planned Rule 217 Kuku surfaces returned no accepted, revised, or under-review collisions.",
        command="python3 batch_scripts/bank_259.py cross-corpus duplicate scan",
        artifact_path="batch_scripts/bank_259.py",
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="preflight",
        event_type="static-guard-pass",
        actor="claude-main",
        detail=(
            "bank_259.py static guards passed: 50 explicit hand-authored rows, exactly one body-part reference target noun per row, "
            "no loans, no target morphology, no possession/body-state/medical/polysemy English, and only the five sourced deictic frame bands."
        ),
        artifact_path="batch_scripts/bank_259.py",
        created_at=NOW,
    )
    db.commit()
    print(
        f"banked {LABEL}: rows={len(ROWS)}, under_review={under_review}, "
        f"verified_before_close={verified_before}, words_before={words_before or 0}"
    )
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
