#!/usr/bin/env python3
"""Bank batch-295: Rule 253 mammal-reference perception debt sweep."""

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-295"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
PROCESS_LOG = "process_logs/batch-295-mammal-perception-debt-sweep-after-rule252-process.md"

TARGET_HEADS = {
    "bala": "sugar glider",
    "darrba": "grass wallaby",
    "jarrabina": "tree kangaroo",
    "jayju": "kangaroo rat",
    "jungarr": "marsupial native cat",
    "kukur": "rat",
    "mali": "small bat",
    "murramu": "dingo",
    "ngumbi": "bandicoot",
    "yawa": "possum",
}
SUPPORT = {"ngayu", "nyulu", "yurra", "bula", "jana", "yaluy", "yinyay", "nyajil"}
PRONOUN_SUPPORT = {"ngayu", "nyulu", "yurra", "bula", "jana"}
DENY_KUKU = {
    # Rule 177-178 and Rule 219 mammal exclusions and high-pressure traps.
    "bimbarrbay", "durrkin", "jibul", "kirbaji", "jumar", "murrumu",
    "nyarrkali", "wambiji", "waykal", "yalmburrajaka", "biki", "bikibiki",
    "biwuy", "buji", "danda", "kadar", "kambi", "kaya", "kaya-kaya",
    "kulngu", "mayarriji", "murral", "ngamu-murramu", "ngangkin",
    "yarraman", "baban", "bububay", "ngalkun", "walkan", "barrbal",
    "jalkay", "janbal", "jijirr", "kurrubal", "murraja",
    # Behavior/use/habitat/story/body/source-material drift.
    "badur", "bana", "bubu", "jalun", "juku", "kalka", "karrba",
    "makarr", "mandurr", "munyun", "wawubaja", "yinba",
    # Pronoun/demonstrative case, perception compounds, and support inflection.
    "nganya", "nyunguny", "yurrangan", "yurraniny", "yurranka", "yurranda",
    "yurranji", "yurranga", "bulangan", "bulaniny", "bulanka", "bulanda",
    "bulanji", "bulanga", "ianangan", "iananiny", "iananka", "iananda",
    "iananji", "iananga", "yinyangka", "yinyayngka", "yinyayanka",
    "yinyamba", "yinyayanda", "yinyamuny", "yinyamundu", "yinyanji",
    "yinyarriny", "yalungku", "yaluyngku", "yaluyunku", "yaluymbu",
    "yaluyundu", "yalamuny", "yalamundu", "yalanji", "nyaji-nka",
    "nyaji-nyaku", "nyaji-l-nyaji",
    # Recent closed domains: reptile/amphibian, fish, bird, dwelling, fire, body, landform/geography.
    "bajuy", "bilngkumu", "binanjal", "bindimu", "bubal", "jijirrbay",
    "kabul", "kalajarr", "kundurr", "yuday", "kubija", "mujarrka",
    "barrbal", "wuyumbu", "bayil", "dalmbal", "balarri", "bilmbin",
    "jalkay", "jijirr", "birmba", "jamarbina", "nili-nili", "mabal",
    "wungku", "kuludu", "kururrungka", "karrambil", "yinjul", "kadanji",
    "bakarr", "bayan", "bira", "jiji", "kilili", "wurun", "jakway",
    "yulal", "kararr", "bilangkurr", "baya", "jimal", "jirramar", "kubu",
    "kunjin", "miyilkura", "ngalku", "ngaluri", "ngunjil", "wula",
    "bandin", "bari", "bibar", "birri", "jiba", "jina", "maka", "milka",
    "nguman", "mabil", "karrirrangkal", "jalngarr", "jinali", "kangku",
    "yalmba", "kambal-kambal", "jalkar", "janku", "jamba",
}
DENY_ENGLISH = (
    "hunt", "hunting", "hunter", "catch", "caught", "catching", "trap",
    "trapped", "kill", "killed", "bite", "biting", "attack", "attacking",
    "attacked", "spear", "speared", "food", "edible", "eat", "eating",
    "ate", "meat", "cook", "cooked", "skin", "fur", "tail", "claw",
    "body-part", "bone", "fat", "habitat", "ecology", "tree-climbing",
    "climb", "branch", "hollow", "cave", "story", "story-site",
    "place-name", "totem", "moiety", "ceremony", "water", "river", "sea",
    "ocean", "iron", "clothing", "source material", "loan", "introduced",
    "pig", "horse", "dog", "domestic cat", "cat loan", "cat-loan",
    "skinny", "weak", "full", "door", "front", "colour", "color", "case",
    "compound", "reduplication", "support inflection", "plural", "many",
)


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, 3, js(words), js([]), evidence, "0.86")


EVIDENCE = {
    "bala": "Dictionary lines 720-728 give bala as noun 'sugar glider', semantic domain fauna-mammal; lines 729-738 give the skinny/weak/boney adjective homograph, which Rule 253 keeps closed. Patz grammar lines 2553-2603 source bare nominative pronouns, lines 2838-2845 source yaluy/yinyay, and lines 3043-3049 source nyaji-l 'see'.",
    "darrba": "Dictionary lines 5306-5315 give darrba as noun 'wallaby', definition/translations 'grass wallaby', semantic domain fauna-mammal. Rule 253 selects grass wallaby only. Patz grammar lines 2553-2603, 2838-2845, and 3043-3049 source the frame.",
    "jarrabina": "Dictionary lines 8248-8259 give jarrabina as noun 'tree kangaroo', definition 'tree-climbing kangaroo', semantic domain fauna-mammal; Rule 253 selects the lexical label only and leaves tree-climbing and murral cross-reference drift closed. Patz grammar lines 2553-2603, 2838-2845, and 3043-3049 source support.",
    "jayju": "Dictionary lines 8602-8610 give jayju as noun 'kangaroo rat', semantic domain fauna-mammal. Rule 253 selects kangaroo rat only. Patz grammar lines 2553-2603, 2838-2845, and 3043-3049 source support.",
    "jungarr": "Dictionary lines 10882-10892 give jungarr as noun 'marsupial native cat', semantic domain fauna-mammal, with quoll commentary; Rule 253 selects marsupial native cat only and leaves domestic/introduced cat drift closed. Patz grammar lines 2553-2603, 2838-2845, and 3043-3049 source support.",
    "kukur": "Dictionary lines 15002-15010 give kukur as noun 'rat', semantic domain fauna-mammal. Rule 253 selects rat only. Patz grammar lines 2553-2603, 2838-2845, and 3043-3049 source support.",
    "mali": "Dictionary lines 17566-17577 give mali as noun 'bat', definition 'species of small bat', translations bat/small bat, semantic domain fauna-mammal; Rule 253 selects small bat as a lexical label only. Patz grammar lines 2553-2603, 2838-2845, and 3043-3049 source support.",
    "murramu": "Dictionary lines 21010-21020 give murramu as noun 'dingo', semantic domain fauna-mammal, with synonym ngamu-murramu; Rule 253 selects murramu/dingo only and leaves synonym, dog/loan, attack, and event drift closed. Patz grammar lines 2553-2603, 2838-2845, and 3043-3049 source support.",
    "ngumbi": "Dictionary lines 23562-23572 give ngumbi as noun 'bandicoot', definition 'little spotted bandicoot', semantic domain fauna-mammal; Rule 253 selects bandicoot only and leaves little/spotted as source-prose modifiers. Patz grammar lines 2553-2603, 2838-2845, and 3043-3049 source support.",
    "yawa": "Dictionary lines 29634-29642 give yawa as noun 'possum', semantic domain fauna-mammal. Rule 253 selects possum only. Patz grammar lines 2553-2603, 2838-2845, and 3043-3049 source support.",
}


ROWS = [
    row(1, "I see the sugar glider here.", "Ngayu bala yaluy nyajil.", "ngayu bala yaluy nyajil | 1sg.NOM sugar.glider here see.NPST", "r253_1sg_target_here_see_bala", ["ngayu", "bala", "yaluy", "nyajil"], EVIDENCE["bala"]),
    row(2, "I see the grass wallaby here.", "Ngayu darrba yaluy nyajil.", "ngayu darrba yaluy nyajil | 1sg.NOM grass.wallaby here see.NPST", "r253_1sg_target_here_see_darrba", ["ngayu", "darrba", "yaluy", "nyajil"], EVIDENCE["darrba"]),
    row(3, "I see the tree kangaroo here.", "Ngayu jarrabina yaluy nyajil.", "ngayu jarrabina yaluy nyajil | 1sg.NOM tree.kangaroo here see.NPST", "r253_1sg_target_here_see_jarrabina", ["ngayu", "jarrabina", "yaluy", "nyajil"], EVIDENCE["jarrabina"]),
    row(4, "I see the kangaroo rat here.", "Ngayu jayju yaluy nyajil.", "ngayu jayju yaluy nyajil | 1sg.NOM kangaroo.rat here see.NPST", "r253_1sg_target_here_see_jayju", ["ngayu", "jayju", "yaluy", "nyajil"], EVIDENCE["jayju"]),
    row(5, "I see the marsupial native cat here.", "Ngayu jungarr yaluy nyajil.", "ngayu jungarr yaluy nyajil | 1sg.NOM marsupial.native.cat here see.NPST", "r253_1sg_target_here_see_jungarr", ["ngayu", "jungarr", "yaluy", "nyajil"], EVIDENCE["jungarr"]),
    row(6, "I see the rat here.", "Ngayu kukur yaluy nyajil.", "ngayu kukur yaluy nyajil | 1sg.NOM rat here see.NPST", "r253_1sg_target_here_see_kukur", ["ngayu", "kukur", "yaluy", "nyajil"], EVIDENCE["kukur"]),
    row(7, "I see the small bat here.", "Ngayu mali yaluy nyajil.", "ngayu mali yaluy nyajil | 1sg.NOM small.bat here see.NPST", "r253_1sg_target_here_see_mali", ["ngayu", "mali", "yaluy", "nyajil"], EVIDENCE["mali"]),
    row(8, "I see the dingo here.", "Ngayu murramu yaluy nyajil.", "ngayu murramu yaluy nyajil | 1sg.NOM dingo here see.NPST", "r253_1sg_target_here_see_murramu", ["ngayu", "murramu", "yaluy", "nyajil"], EVIDENCE["murramu"]),
    row(9, "I see the bandicoot here.", "Ngayu ngumbi yaluy nyajil.", "ngayu ngumbi yaluy nyajil | 1sg.NOM bandicoot here see.NPST", "r253_1sg_target_here_see_ngumbi", ["ngayu", "ngumbi", "yaluy", "nyajil"], EVIDENCE["ngumbi"]),
    row(10, "I see the possum here.", "Ngayu yawa yaluy nyajil.", "ngayu yawa yaluy nyajil | 1sg.NOM possum here see.NPST", "r253_1sg_target_here_see_yawa", ["ngayu", "yawa", "yaluy", "nyajil"], EVIDENCE["yawa"]),
    row(11, "He sees the sugar glider there.", "Nyulu bala yinyay nyajil.", "nyulu bala yinyay nyajil | 3sg.NOM sugar.glider there see.NPST", "r253_3sg_target_there_see_bala", ["nyulu", "bala", "yinyay", "nyajil"], EVIDENCE["bala"]),
    row(12, "He sees the grass wallaby there.", "Nyulu darrba yinyay nyajil.", "nyulu darrba yinyay nyajil | 3sg.NOM grass.wallaby there see.NPST", "r253_3sg_target_there_see_darrba", ["nyulu", "darrba", "yinyay", "nyajil"], EVIDENCE["darrba"]),
    row(13, "He sees the tree kangaroo there.", "Nyulu jarrabina yinyay nyajil.", "nyulu jarrabina yinyay nyajil | 3sg.NOM tree.kangaroo there see.NPST", "r253_3sg_target_there_see_jarrabina", ["nyulu", "jarrabina", "yinyay", "nyajil"], EVIDENCE["jarrabina"]),
    row(14, "He sees the kangaroo rat there.", "Nyulu jayju yinyay nyajil.", "nyulu jayju yinyay nyajil | 3sg.NOM kangaroo.rat there see.NPST", "r253_3sg_target_there_see_jayju", ["nyulu", "jayju", "yinyay", "nyajil"], EVIDENCE["jayju"]),
    row(15, "He sees the marsupial native cat there.", "Nyulu jungarr yinyay nyajil.", "nyulu jungarr yinyay nyajil | 3sg.NOM marsupial.native.cat there see.NPST", "r253_3sg_target_there_see_jungarr", ["nyulu", "jungarr", "yinyay", "nyajil"], EVIDENCE["jungarr"]),
    row(16, "He sees the rat there.", "Nyulu kukur yinyay nyajil.", "nyulu kukur yinyay nyajil | 3sg.NOM rat there see.NPST", "r253_3sg_target_there_see_kukur", ["nyulu", "kukur", "yinyay", "nyajil"], EVIDENCE["kukur"]),
    row(17, "He sees the small bat there.", "Nyulu mali yinyay nyajil.", "nyulu mali yinyay nyajil | 3sg.NOM small.bat there see.NPST", "r253_3sg_target_there_see_mali", ["nyulu", "mali", "yinyay", "nyajil"], EVIDENCE["mali"]),
    row(18, "He sees the dingo there.", "Nyulu murramu yinyay nyajil.", "nyulu murramu yinyay nyajil | 3sg.NOM dingo there see.NPST", "r253_3sg_target_there_see_murramu", ["nyulu", "murramu", "yinyay", "nyajil"], EVIDENCE["murramu"]),
    row(19, "He sees the bandicoot there.", "Nyulu ngumbi yinyay nyajil.", "nyulu ngumbi yinyay nyajil | 3sg.NOM bandicoot there see.NPST", "r253_3sg_target_there_see_ngumbi", ["nyulu", "ngumbi", "yinyay", "nyajil"], EVIDENCE["ngumbi"]),
    row(20, "He sees the possum there.", "Nyulu yawa yinyay nyajil.", "nyulu yawa yinyay nyajil | 3sg.NOM possum there see.NPST", "r253_3sg_target_there_see_yawa", ["nyulu", "yawa", "yinyay", "nyajil"], EVIDENCE["yawa"]),
    row(21, "You all see the sugar glider here.", "Yurra bala yaluy nyajil.", "yurra bala yaluy nyajil | 2pl.NOM sugar.glider here see.NPST", "r253_2pl_target_here_see_bala", ["yurra", "bala", "yaluy", "nyajil"], EVIDENCE["bala"]),
    row(22, "You all see the grass wallaby here.", "Yurra darrba yaluy nyajil.", "yurra darrba yaluy nyajil | 2pl.NOM grass.wallaby here see.NPST", "r253_2pl_target_here_see_darrba", ["yurra", "darrba", "yaluy", "nyajil"], EVIDENCE["darrba"]),
    row(23, "You all see the tree kangaroo here.", "Yurra jarrabina yaluy nyajil.", "yurra jarrabina yaluy nyajil | 2pl.NOM tree.kangaroo here see.NPST", "r253_2pl_target_here_see_jarrabina", ["yurra", "jarrabina", "yaluy", "nyajil"], EVIDENCE["jarrabina"]),
    row(24, "You all see the kangaroo rat here.", "Yurra jayju yaluy nyajil.", "yurra jayju yaluy nyajil | 2pl.NOM kangaroo.rat here see.NPST", "r253_2pl_target_here_see_jayju", ["yurra", "jayju", "yaluy", "nyajil"], EVIDENCE["jayju"]),
    row(25, "You all see the marsupial native cat here.", "Yurra jungarr yaluy nyajil.", "yurra jungarr yaluy nyajil | 2pl.NOM marsupial.native.cat here see.NPST", "r253_2pl_target_here_see_jungarr", ["yurra", "jungarr", "yaluy", "nyajil"], EVIDENCE["jungarr"]),
    row(26, "You all see the rat here.", "Yurra kukur yaluy nyajil.", "yurra kukur yaluy nyajil | 2pl.NOM rat here see.NPST", "r253_2pl_target_here_see_kukur", ["yurra", "kukur", "yaluy", "nyajil"], EVIDENCE["kukur"]),
    row(27, "You all see the small bat here.", "Yurra mali yaluy nyajil.", "yurra mali yaluy nyajil | 2pl.NOM small.bat here see.NPST", "r253_2pl_target_here_see_mali", ["yurra", "mali", "yaluy", "nyajil"], EVIDENCE["mali"]),
    row(28, "You all see the dingo here.", "Yurra murramu yaluy nyajil.", "yurra murramu yaluy nyajil | 2pl.NOM dingo here see.NPST", "r253_2pl_target_here_see_murramu", ["yurra", "murramu", "yaluy", "nyajil"], EVIDENCE["murramu"]),
    row(29, "You all see the bandicoot here.", "Yurra ngumbi yaluy nyajil.", "yurra ngumbi yaluy nyajil | 2pl.NOM bandicoot here see.NPST", "r253_2pl_target_here_see_ngumbi", ["yurra", "ngumbi", "yaluy", "nyajil"], EVIDENCE["ngumbi"]),
    row(30, "You all see the possum here.", "Yurra yawa yaluy nyajil.", "yurra yawa yaluy nyajil | 2pl.NOM possum here see.NPST", "r253_2pl_target_here_see_yawa", ["yurra", "yawa", "yaluy", "nyajil"], EVIDENCE["yawa"]),
    row(31, "The two of them see the sugar glider there.", "Bula bala yinyay nyajil.", "bula bala yinyay nyajil | 3du.NOM sugar.glider there see.NPST", "r253_3du_target_there_see_bala", ["bula", "bala", "yinyay", "nyajil"], EVIDENCE["bala"]),
    row(32, "The two of them see the grass wallaby there.", "Bula darrba yinyay nyajil.", "bula darrba yinyay nyajil | 3du.NOM grass.wallaby there see.NPST", "r253_3du_target_there_see_darrba", ["bula", "darrba", "yinyay", "nyajil"], EVIDENCE["darrba"]),
    row(33, "The two of them see the tree kangaroo there.", "Bula jarrabina yinyay nyajil.", "bula jarrabina yinyay nyajil | 3du.NOM tree.kangaroo there see.NPST", "r253_3du_target_there_see_jarrabina", ["bula", "jarrabina", "yinyay", "nyajil"], EVIDENCE["jarrabina"]),
    row(34, "The two of them see the kangaroo rat there.", "Bula jayju yinyay nyajil.", "bula jayju yinyay nyajil | 3du.NOM kangaroo.rat there see.NPST", "r253_3du_target_there_see_jayju", ["bula", "jayju", "yinyay", "nyajil"], EVIDENCE["jayju"]),
    row(35, "The two of them see the marsupial native cat there.", "Bula jungarr yinyay nyajil.", "bula jungarr yinyay nyajil | 3du.NOM marsupial.native.cat there see.NPST", "r253_3du_target_there_see_jungarr", ["bula", "jungarr", "yinyay", "nyajil"], EVIDENCE["jungarr"]),
    row(36, "The two of them see the rat there.", "Bula kukur yinyay nyajil.", "bula kukur yinyay nyajil | 3du.NOM rat there see.NPST", "r253_3du_target_there_see_kukur", ["bula", "kukur", "yinyay", "nyajil"], EVIDENCE["kukur"]),
    row(37, "The two of them see the small bat there.", "Bula mali yinyay nyajil.", "bula mali yinyay nyajil | 3du.NOM small.bat there see.NPST", "r253_3du_target_there_see_mali", ["bula", "mali", "yinyay", "nyajil"], EVIDENCE["mali"]),
    row(38, "The two of them see the dingo there.", "Bula murramu yinyay nyajil.", "bula murramu yinyay nyajil | 3du.NOM dingo there see.NPST", "r253_3du_target_there_see_murramu", ["bula", "murramu", "yinyay", "nyajil"], EVIDENCE["murramu"]),
    row(39, "The two of them see the bandicoot there.", "Bula ngumbi yinyay nyajil.", "bula ngumbi yinyay nyajil | 3du.NOM bandicoot there see.NPST", "r253_3du_target_there_see_ngumbi", ["bula", "ngumbi", "yinyay", "nyajil"], EVIDENCE["ngumbi"]),
    row(40, "The two of them see the possum there.", "Bula yawa yinyay nyajil.", "bula yawa yinyay nyajil | 3du.NOM possum there see.NPST", "r253_3du_target_there_see_yawa", ["bula", "yawa", "yinyay", "nyajil"], EVIDENCE["yawa"]),
    row(41, "They see the sugar glider here.", "Jana bala yaluy nyajil.", "jana bala yaluy nyajil | 3pl.NOM sugar.glider here see.NPST", "r253_3pl_target_here_see_bala", ["jana", "bala", "yaluy", "nyajil"], EVIDENCE["bala"]),
    row(42, "They see the grass wallaby here.", "Jana darrba yaluy nyajil.", "jana darrba yaluy nyajil | 3pl.NOM grass.wallaby here see.NPST", "r253_3pl_target_here_see_darrba", ["jana", "darrba", "yaluy", "nyajil"], EVIDENCE["darrba"]),
    row(43, "They see the tree kangaroo here.", "Jana jarrabina yaluy nyajil.", "jana jarrabina yaluy nyajil | 3pl.NOM tree.kangaroo here see.NPST", "r253_3pl_target_here_see_jarrabina", ["jana", "jarrabina", "yaluy", "nyajil"], EVIDENCE["jarrabina"]),
    row(44, "They see the kangaroo rat here.", "Jana jayju yaluy nyajil.", "jana jayju yaluy nyajil | 3pl.NOM kangaroo.rat here see.NPST", "r253_3pl_target_here_see_jayju", ["jana", "jayju", "yaluy", "nyajil"], EVIDENCE["jayju"]),
    row(45, "They see the marsupial native cat here.", "Jana jungarr yaluy nyajil.", "jana jungarr yaluy nyajil | 3pl.NOM marsupial.native.cat here see.NPST", "r253_3pl_target_here_see_jungarr", ["jana", "jungarr", "yaluy", "nyajil"], EVIDENCE["jungarr"]),
    row(46, "They see the rat here.", "Jana kukur yaluy nyajil.", "jana kukur yaluy nyajil | 3pl.NOM rat here see.NPST", "r253_3pl_target_here_see_kukur", ["jana", "kukur", "yaluy", "nyajil"], EVIDENCE["kukur"]),
    row(47, "They see the small bat here.", "Jana mali yaluy nyajil.", "jana mali yaluy nyajil | 3pl.NOM small.bat here see.NPST", "r253_3pl_target_here_see_mali", ["jana", "mali", "yaluy", "nyajil"], EVIDENCE["mali"]),
    row(48, "They see the dingo here.", "Jana murramu yaluy nyajil.", "jana murramu yaluy nyajil | 3pl.NOM dingo here see.NPST", "r253_3pl_target_here_see_murramu", ["jana", "murramu", "yaluy", "nyajil"], EVIDENCE["murramu"]),
    row(49, "They see the bandicoot here.", "Jana ngumbi yaluy nyajil.", "jana ngumbi yaluy nyajil | 3pl.NOM bandicoot here see.NPST", "r253_3pl_target_here_see_ngumbi", ["jana", "ngumbi", "yaluy", "nyajil"], EVIDENCE["ngumbi"]),
    row(50, "They see the possum here.", "Jana yawa yaluy nyajil.", "jana yawa yaluy nyajil | 3pl.NOM possum here see.NPST", "r253_3pl_target_here_see_yawa", ["jana", "yawa", "yaluy", "nyajil"], EVIDENCE["yawa"]),
]


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|karra|manda|bulal"
    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("r253_"):
            issues.append(f"{label}: Rule 253 frame must start with r253_")
        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 253")
        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 253 target mammal 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")
        pronouns = [pronoun for pronoun in PRONOUN_SUPPORT if has_token(low, pronoun)]
        if len(pronouns) != 1:
            issues.append(f"{label}: rows require exactly one bare nominative pronoun, found {pronouns}")
        if 1 <= seq <= 10 and (not low.startswith("ngayu ") or not low.endswith(" yaluy nyajil.") or len(low.split()) != 4):
            issues.append(f"{label}: rows 1-10 require Ngayu TARGET yaluy nyajil")
        if 11 <= seq <= 20 and (not low.startswith("nyulu ") or not low.endswith(" yinyay nyajil.") or len(low.split()) != 4):
            issues.append(f"{label}: rows 11-20 require Nyulu TARGET yinyay nyajil")
        if 21 <= seq <= 30 and (not low.startswith("yurra ") or not low.endswith(" yaluy nyajil.") or len(low.split()) != 4):
            issues.append(f"{label}: rows 21-30 require Yurra TARGET yaluy nyajil")
        if 31 <= seq <= 40 and (not low.startswith("bula ") or not low.endswith(" yinyay nyajil.") or len(low.split()) != 4):
            issues.append(f"{label}: rows 31-40 require Bula TARGET yinyay nyajil")
        if 41 <= seq <= 50 and (not low.startswith("jana ") or not low.endswith(" yaluy nyajil.") or len(low.split()) != 4):
            issues.append(f"{label}: rows 41-50 require Jana TARGET yaluy nyajil")
        if any(english_has_denied(english_low, bad) for bad in DENY_ENGLISH):
            issues.append(f"{label}: denied mammal behavior/use/habitat/story/body-part/source-prose 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 lessons 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:
        db.execute(
            "INSERT INTO batches(label, cheatsheet_version, guide_version, notes, created_at) VALUES(?,?,?,?,?)",
            (LABEL, "Rule 253 draft", "operator-guide-2026-07-09", "draft under review", NOW),
        )
        batch_id = db.execute("SELECT id FROM batches WHERE label=?", (LABEL,)).fetchone()[0]

    collisions: list[str] = []
    for seq, _english, kuku, *_rest in ROWS:
        found = db.execute(
            """
            SELECT b.label, s.seq, s.status
            FROM sentences s JOIN batches b ON b.id=s.batch_id
            WHERE lower(s.kuku)=lower(?) AND s.status IN ('accepted','revised','under_review')
            """,
            (kuku,),
        ).fetchall()
        if found:
            collisions.append(f"{seq}: {kuku} -> {found}")
    if collisions:
        raise SystemExit("collision scan failed:\n" + "\n".join(collisions))

    db.executemany(
        """
        INSERT INTO sentences(
          batch_id, seq, english, kuku, analysis, frame, tier, words_used,
          loans_used, evidence, status, confidence, created_at
        )
        VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)
        """,
        [
            (
                batch_id,
                seq,
                english,
                kuku,
                analysis,
                frame,
                tier,
                words_used,
                loans_used,
                evidence,
                "under_review",
                confidence,
                NOW,
            )
            for seq, english, kuku, analysis, frame, tier, words_used, loans_used, evidence, confidence in ROWS
        ],
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="source",
        event_type="source-readback",
        actor="claude-main",
        detail="Rule 253 source pass checked exact dictionary lines for bala sugar glider, darrba grass wallaby, jarrabina tree kangaroo, jayju kangaroo rat, jungarr marsupial native cat, kukur rat, mali small bat, murramu dingo, ngumbi bandicoot, and yawa possum; Patz grammar lines 2553-2603 for bare nominative pronouns; lines 2838-2845 for yaluy/yinyay; and lines 3043-3049 for nyaji-l.",
        artifact_path=PROCESS_LOG,
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="planning",
        event_type="debt-sweep-scope",
        actor="claude-main",
        detail="Selected Rule 253 mammal-reference perception debt sweep after Rule 252: ten Rule 219 mammal labels in five zero-collision nominative-pronoun perception bands. All hunting, catching, killing, biting, attack, food, habitat, body-part, story, ceremony, source-material, secondary-sense, target-case, pronoun-case, demonstrative-case, and perception-compound semantics remain closed.",
        artifact_path=PROCESS_LOG,
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="preflight",
        event_type="coverage-audit",
        actor="claude-main",
        detail="Pre-batch token-aware target coverage among accepted/revised rows after Rule 252: bala 9, darrba 38, jarrabina 10, jayju 8, jungarr 7, kukur 11, mali 15, murramu 28, ngumbi 8, and yawa 34. Support coverage: ngayu 1243, nyulu 1724, yurra 173, bula 153, jana 1446, yaluy 2173, yinyay 2426, nyajil 2467.",
        command="sqlite3 synthetic.db token-aware coverage audit",
        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 253 Kuku surfaces returned zero accepted, revised, or under-review collisions.",
        command="python3 batch_scripts/bank_295.py internal collision scan",
        output_excerpt="0",
        artifact_path=PROCESS_LOG,
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="preflight",
        event_type="static-guard-pass",
        actor="claude-main",
        detail="Static guards passed: 50 rows, exactly one Rule 253 target mammal noun per row, exactly one bare nominative pronoun per row, no loans, no target suffixes, no excluded mammal candidate, no behavior/use/habitat/story/body-part/source-prose drift, no pronoun case, no demonstrative case, no perception compound, and five planned frame bands only.",
        command="python3 batch_scripts/bank_295.py",
        artifact_path="batch_scripts/bank_295.py",
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="bank",
        event_type="bank-success",
        actor="claude-main",
        detail="Banked 50 explicit hand-authored Rule 253 mammal-reference perception rows as under_review.",
        command="python3 batch_scripts/bank_295.py",
        artifact_path="batch_scripts/bank_295.py",
        created_at=NOW,
    )
    db.commit()
    print(f"banked {LABEL}: 50 under_review rows")
    return 0


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

