#!/usr/bin/env python3
"""Bank batch-297: Rule 255 insect-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-297"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
PROCESS_LOG = "process_logs/batch-297-insect-perception-debt-sweep-after-rule254-process.md"

TARGET_HEADS = {
    "balarr": "flea",
    "dijaraban": "mayfly",
    "kalburiji": "kalburiji bee",
    "mawal": "mawal bee",
    "munudumbun": "scorpion",
    "munyurri": "sandfly",
    "nakawarra": "nakawarra bee",
    "ngalmnbu": "jumper ant",
    "yarrka": "yarrka bee",
    "yiljun": "grasshopper",
}
SUPPORT = {"ngayu", "nyulu", "yurra", "bula", "jana", "yaluy", "yinyay", "nyajil"}
PRONOUN_SUPPORT = {"ngayu", "nyulu", "yurra", "bula", "jana"}
DENY_KUKU = {
    # Rule 169-170 and Rule 222 insect/arthropod exclusions and alternate target sets.
    "biray", "kamay", "manukurru", "mindil", "murrmun", "murrumun",
    "muyu-muyu", "wurrarr-wurrarr", "yijil-yijin", "yinja-yinja",
    "kira-kira", "kandal", "kinga", "mulma", "biringal", "birinjil",
    "kurrmbal", "nganjamu", "kurran", "ngirran", "dabadaba", "daba-daba",
    "dujandujan", "dujan-dujan", "kalkamal", "karrkil", "kuran",
    "kurrmaja", "murma", "wurrbu", "nyumbil", "jawurraji", "jiljay",
    "jingka-jingka", "wurarr-wurarr", "munukurru", "diri-diri",
    # Behavior/use/ecology/body/source-prose drift.
    "bayka-l", "baykal", "jindal", "wunba", "bayan", "mayi", "bama",
    "juku", "bubu", "bana", "wukay", "badida", "kalbal", "dukunjaka",
    # 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.
    "bala", "darrba", "jarrabina", "jayju", "jungarr", "kukur", "mali",
    "murramu", "ngumbi", "yawa", "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 = (
    "body", "human", "bite", "biting", "bitten", "sting", "stinging",
    "sick", "sickness", "vomit", "vomiting", "larva", "larvae", "egg",
    "eggs", "honey", "nest", "nests", "edible", "food", "eat", "eating",
    "medicine", "season", "seasonal", "collect", "collecting", "antbed",
    "ant bed", "anthill", "ant hill", "grub", "tree", "wood", "green wood",
    "mountain", "habitat", "pest", "control", "totem", "life-force",
    "dragonfly", "smallest", "bush", "ecology", "movement", "danger",
    "dangerous", "event", "yam", "singing", "song", "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 = {
    "balarr": "Dictionary lines 833-841 give balarr as noun 'flea', semantic domain fauna-insect; the human-body wording is source prose only. Patz grammar lines 2553-2603 source bare nominative pronouns, lines 2838-2845 source yaluy/yinyay, and lines 3043-3049 source nyaji-l 'see'.",
    "dijaraban": "Dictionary lines 5542-5551 give dijaraban as noun 'mayfly', definition/translations mayfly/dragonfly, semantic domain fauna-insect; Rule 255 selects mayfly only. Patz grammar lines 2553-2603, 2838-2845, and 3043-3049 source support.",
    "kalburiji": "Dictionary lines 12474-12484 give kalburiji as noun 'bee', definition 'species of bee', semantic domain fauna-insect; Rule 255 selects kalburiji bee only and leaves honey/nest/egg/larvae readings closed. Patz grammar lines 2553-2603, 2838-2845, and 3043-3049 source support.",
    "mawal": "Dictionary lines 18743-18753 give mawal as noun 'bee', definition 'species of bee', semantic domain fauna-insect; Rule 255 selects mawal bee only and leaves honey/nest/egg/larvae readings closed. Patz grammar lines 2553-2603, 2838-2845, and 3043-3049 source support.",
    "munudumbun": "Dictionary lines 20816-20826 give munudumbun as noun 'scorpion', semantic domain fauna-insect, synonym munukurru; Rule 255 selects munudumbun only and leaves synonym/sting/sickness/fear/danger rows closed. Patz grammar lines 2553-2603, 2838-2845, and 3043-3049 source support.",
    "munyurri": "Dictionary lines 20868-20889 give duplicate munyurri noun entries as 'sandfly', semantic domain fauna-insect, synonym diri-diri; Rule 255 selects munyurri only and leaves synonym/biting/sickness rows closed. Patz grammar lines 2553-2603, 2838-2845, and 3043-3049 source support.",
    "nakawarra": "Dictionary lines 21461-21470 give nakawarra as noun 'species of bee', translations species of bee/bee, semantic domain fauna-insect; Rule 255 selects nakawarra bee only and leaves honey/nest/egg/larvae readings closed. Patz grammar lines 2553-2603, 2838-2845, and 3043-3049 source support.",
    "ngalmnbu": "Dictionary lines 21972-21980 give ngalmnbu as noun 'jumper ant', semantic domain fauna-insect; Rule 255 selects jumper ant only and leaves jumping, biting, sting, antbed, and event readings closed. Patz grammar lines 2553-2603, 2838-2845, and 3043-3049 source support.",
    "yarrka": "Dictionary lines 29551-29559 give yarrka as noun 'bee', definition 'bee, the smallest bee in the bush', semantic domain fauna-insect; Rule 255 selects yarrka bee only and leaves smallest/bush/ecology readings closed. Patz grammar lines 2553-2603, 2838-2845, and 3043-3049 source support.",
    "yiljun": "Dictionary lines 30019-30029 give yiljun as noun 'grasshopper', definition 'type of grasshopper', with a singing/yam-readiness source usage; Rule 255 selects grasshopper only. Patz grammar lines 2553-2603, 2838-2845, and 3043-3049 source support.",
}


ROWS = [
    row(1, "I see the flea there.", "Ngayu balarr yinyay nyajil.", "ngayu balarr yinyay nyajil | 1sg.NOM flea there see.NPST", "r255_1sg_target_there_see_balarr", ["ngayu", "balarr", "yinyay", "nyajil"], EVIDENCE["balarr"]),
    row(2, "I see the mayfly there.", "Ngayu dijaraban yinyay nyajil.", "ngayu dijaraban yinyay nyajil | 1sg.NOM mayfly there see.NPST", "r255_1sg_target_there_see_dijaraban", ["ngayu", "dijaraban", "yinyay", "nyajil"], EVIDENCE["dijaraban"]),
    row(3, "I see the kalburiji bee there.", "Ngayu kalburiji yinyay nyajil.", "ngayu kalburiji yinyay nyajil | 1sg.NOM kalburiji.bee there see.NPST", "r255_1sg_target_there_see_kalburiji", ["ngayu", "kalburiji", "yinyay", "nyajil"], EVIDENCE["kalburiji"]),
    row(4, "I see the mawal bee there.", "Ngayu mawal yinyay nyajil.", "ngayu mawal yinyay nyajil | 1sg.NOM mawal.bee there see.NPST", "r255_1sg_target_there_see_mawal", ["ngayu", "mawal", "yinyay", "nyajil"], EVIDENCE["mawal"]),
    row(5, "I see the scorpion there.", "Ngayu munudumbun yinyay nyajil.", "ngayu munudumbun yinyay nyajil | 1sg.NOM scorpion there see.NPST", "r255_1sg_target_there_see_munudumbun", ["ngayu", "munudumbun", "yinyay", "nyajil"], EVIDENCE["munudumbun"]),
    row(6, "I see the sandfly there.", "Ngayu munyurri yinyay nyajil.", "ngayu munyurri yinyay nyajil | 1sg.NOM sandfly there see.NPST", "r255_1sg_target_there_see_munyurri", ["ngayu", "munyurri", "yinyay", "nyajil"], EVIDENCE["munyurri"]),
    row(7, "I see the nakawarra bee there.", "Ngayu nakawarra yinyay nyajil.", "ngayu nakawarra yinyay nyajil | 1sg.NOM nakawarra.bee there see.NPST", "r255_1sg_target_there_see_nakawarra", ["ngayu", "nakawarra", "yinyay", "nyajil"], EVIDENCE["nakawarra"]),
    row(8, "I see the jumper ant there.", "Ngayu ngalmnbu yinyay nyajil.", "ngayu ngalmnbu yinyay nyajil | 1sg.NOM jumper.ant there see.NPST", "r255_1sg_target_there_see_ngalmnbu", ["ngayu", "ngalmnbu", "yinyay", "nyajil"], EVIDENCE["ngalmnbu"]),
    row(9, "I see the yarrka bee there.", "Ngayu yarrka yinyay nyajil.", "ngayu yarrka yinyay nyajil | 1sg.NOM yarrka.bee there see.NPST", "r255_1sg_target_there_see_yarrka", ["ngayu", "yarrka", "yinyay", "nyajil"], EVIDENCE["yarrka"]),
    row(10, "I see the grasshopper there.", "Ngayu yiljun yinyay nyajil.", "ngayu yiljun yinyay nyajil | 1sg.NOM grasshopper there see.NPST", "r255_1sg_target_there_see_yiljun", ["ngayu", "yiljun", "yinyay", "nyajil"], EVIDENCE["yiljun"]),
    row(11, "He sees the flea here.", "Nyulu balarr yaluy nyajil.", "nyulu balarr yaluy nyajil | 3sg.NOM flea here see.NPST", "r255_3sg_target_here_see_balarr", ["nyulu", "balarr", "yaluy", "nyajil"], EVIDENCE["balarr"]),
    row(12, "He sees the mayfly here.", "Nyulu dijaraban yaluy nyajil.", "nyulu dijaraban yaluy nyajil | 3sg.NOM mayfly here see.NPST", "r255_3sg_target_here_see_dijaraban", ["nyulu", "dijaraban", "yaluy", "nyajil"], EVIDENCE["dijaraban"]),
    row(13, "He sees the kalburiji bee here.", "Nyulu kalburiji yaluy nyajil.", "nyulu kalburiji yaluy nyajil | 3sg.NOM kalburiji.bee here see.NPST", "r255_3sg_target_here_see_kalburiji", ["nyulu", "kalburiji", "yaluy", "nyajil"], EVIDENCE["kalburiji"]),
    row(14, "He sees the mawal bee here.", "Nyulu mawal yaluy nyajil.", "nyulu mawal yaluy nyajil | 3sg.NOM mawal.bee here see.NPST", "r255_3sg_target_here_see_mawal", ["nyulu", "mawal", "yaluy", "nyajil"], EVIDENCE["mawal"]),
    row(15, "He sees the scorpion here.", "Nyulu munudumbun yaluy nyajil.", "nyulu munudumbun yaluy nyajil | 3sg.NOM scorpion here see.NPST", "r255_3sg_target_here_see_munudumbun", ["nyulu", "munudumbun", "yaluy", "nyajil"], EVIDENCE["munudumbun"]),
    row(16, "He sees the sandfly here.", "Nyulu munyurri yaluy nyajil.", "nyulu munyurri yaluy nyajil | 3sg.NOM sandfly here see.NPST", "r255_3sg_target_here_see_munyurri", ["nyulu", "munyurri", "yaluy", "nyajil"], EVIDENCE["munyurri"]),
    row(17, "He sees the nakawarra bee here.", "Nyulu nakawarra yaluy nyajil.", "nyulu nakawarra yaluy nyajil | 3sg.NOM nakawarra.bee here see.NPST", "r255_3sg_target_here_see_nakawarra", ["nyulu", "nakawarra", "yaluy", "nyajil"], EVIDENCE["nakawarra"]),
    row(18, "He sees the jumper ant here.", "Nyulu ngalmnbu yaluy nyajil.", "nyulu ngalmnbu yaluy nyajil | 3sg.NOM jumper.ant here see.NPST", "r255_3sg_target_here_see_ngalmnbu", ["nyulu", "ngalmnbu", "yaluy", "nyajil"], EVIDENCE["ngalmnbu"]),
    row(19, "He sees the yarrka bee here.", "Nyulu yarrka yaluy nyajil.", "nyulu yarrka yaluy nyajil | 3sg.NOM yarrka.bee here see.NPST", "r255_3sg_target_here_see_yarrka", ["nyulu", "yarrka", "yaluy", "nyajil"], EVIDENCE["yarrka"]),
    row(20, "He sees the grasshopper here.", "Nyulu yiljun yaluy nyajil.", "nyulu yiljun yaluy nyajil | 3sg.NOM grasshopper here see.NPST", "r255_3sg_target_here_see_yiljun", ["nyulu", "yiljun", "yaluy", "nyajil"], EVIDENCE["yiljun"]),
    row(21, "You all see the flea there.", "Yurra balarr yinyay nyajil.", "yurra balarr yinyay nyajil | 2pl.NOM flea there see.NPST", "r255_2pl_target_there_see_balarr", ["yurra", "balarr", "yinyay", "nyajil"], EVIDENCE["balarr"]),
    row(22, "You all see the mayfly there.", "Yurra dijaraban yinyay nyajil.", "yurra dijaraban yinyay nyajil | 2pl.NOM mayfly there see.NPST", "r255_2pl_target_there_see_dijaraban", ["yurra", "dijaraban", "yinyay", "nyajil"], EVIDENCE["dijaraban"]),
    row(23, "You all see the kalburiji bee there.", "Yurra kalburiji yinyay nyajil.", "yurra kalburiji yinyay nyajil | 2pl.NOM kalburiji.bee there see.NPST", "r255_2pl_target_there_see_kalburiji", ["yurra", "kalburiji", "yinyay", "nyajil"], EVIDENCE["kalburiji"]),
    row(24, "You all see the mawal bee there.", "Yurra mawal yinyay nyajil.", "yurra mawal yinyay nyajil | 2pl.NOM mawal.bee there see.NPST", "r255_2pl_target_there_see_mawal", ["yurra", "mawal", "yinyay", "nyajil"], EVIDENCE["mawal"]),
    row(25, "You all see the scorpion there.", "Yurra munudumbun yinyay nyajil.", "yurra munudumbun yinyay nyajil | 2pl.NOM scorpion there see.NPST", "r255_2pl_target_there_see_munudumbun", ["yurra", "munudumbun", "yinyay", "nyajil"], EVIDENCE["munudumbun"]),
    row(26, "You all see the sandfly there.", "Yurra munyurri yinyay nyajil.", "yurra munyurri yinyay nyajil | 2pl.NOM sandfly there see.NPST", "r255_2pl_target_there_see_munyurri", ["yurra", "munyurri", "yinyay", "nyajil"], EVIDENCE["munyurri"]),
    row(27, "You all see the nakawarra bee there.", "Yurra nakawarra yinyay nyajil.", "yurra nakawarra yinyay nyajil | 2pl.NOM nakawarra.bee there see.NPST", "r255_2pl_target_there_see_nakawarra", ["yurra", "nakawarra", "yinyay", "nyajil"], EVIDENCE["nakawarra"]),
    row(28, "You all see the jumper ant there.", "Yurra ngalmnbu yinyay nyajil.", "yurra ngalmnbu yinyay nyajil | 2pl.NOM jumper.ant there see.NPST", "r255_2pl_target_there_see_ngalmnbu", ["yurra", "ngalmnbu", "yinyay", "nyajil"], EVIDENCE["ngalmnbu"]),
    row(29, "You all see the yarrka bee there.", "Yurra yarrka yinyay nyajil.", "yurra yarrka yinyay nyajil | 2pl.NOM yarrka.bee there see.NPST", "r255_2pl_target_there_see_yarrka", ["yurra", "yarrka", "yinyay", "nyajil"], EVIDENCE["yarrka"]),
    row(30, "You all see the grasshopper there.", "Yurra yiljun yinyay nyajil.", "yurra yiljun yinyay nyajil | 2pl.NOM grasshopper there see.NPST", "r255_2pl_target_there_see_yiljun", ["yurra", "yiljun", "yinyay", "nyajil"], EVIDENCE["yiljun"]),
    row(31, "The two of them see the flea here.", "Bula balarr yaluy nyajil.", "bula balarr yaluy nyajil | 3du.NOM flea here see.NPST", "r255_3du_target_here_see_balarr", ["bula", "balarr", "yaluy", "nyajil"], EVIDENCE["balarr"]),
    row(32, "The two of them see the mayfly here.", "Bula dijaraban yaluy nyajil.", "bula dijaraban yaluy nyajil | 3du.NOM mayfly here see.NPST", "r255_3du_target_here_see_dijaraban", ["bula", "dijaraban", "yaluy", "nyajil"], EVIDENCE["dijaraban"]),
    row(33, "The two of them see the kalburiji bee here.", "Bula kalburiji yaluy nyajil.", "bula kalburiji yaluy nyajil | 3du.NOM kalburiji.bee here see.NPST", "r255_3du_target_here_see_kalburiji", ["bula", "kalburiji", "yaluy", "nyajil"], EVIDENCE["kalburiji"]),
    row(34, "The two of them see the mawal bee here.", "Bula mawal yaluy nyajil.", "bula mawal yaluy nyajil | 3du.NOM mawal.bee here see.NPST", "r255_3du_target_here_see_mawal", ["bula", "mawal", "yaluy", "nyajil"], EVIDENCE["mawal"]),
    row(35, "The two of them see the scorpion here.", "Bula munudumbun yaluy nyajil.", "bula munudumbun yaluy nyajil | 3du.NOM scorpion here see.NPST", "r255_3du_target_here_see_munudumbun", ["bula", "munudumbun", "yaluy", "nyajil"], EVIDENCE["munudumbun"]),
    row(36, "The two of them see the sandfly here.", "Bula munyurri yaluy nyajil.", "bula munyurri yaluy nyajil | 3du.NOM sandfly here see.NPST", "r255_3du_target_here_see_munyurri", ["bula", "munyurri", "yaluy", "nyajil"], EVIDENCE["munyurri"]),
    row(37, "The two of them see the nakawarra bee here.", "Bula nakawarra yaluy nyajil.", "bula nakawarra yaluy nyajil | 3du.NOM nakawarra.bee here see.NPST", "r255_3du_target_here_see_nakawarra", ["bula", "nakawarra", "yaluy", "nyajil"], EVIDENCE["nakawarra"]),
    row(38, "The two of them see the jumper ant here.", "Bula ngalmnbu yaluy nyajil.", "bula ngalmnbu yaluy nyajil | 3du.NOM jumper.ant here see.NPST", "r255_3du_target_here_see_ngalmnbu", ["bula", "ngalmnbu", "yaluy", "nyajil"], EVIDENCE["ngalmnbu"]),
    row(39, "The two of them see the yarrka bee here.", "Bula yarrka yaluy nyajil.", "bula yarrka yaluy nyajil | 3du.NOM yarrka.bee here see.NPST", "r255_3du_target_here_see_yarrka", ["bula", "yarrka", "yaluy", "nyajil"], EVIDENCE["yarrka"]),
    row(40, "The two of them see the grasshopper here.", "Bula yiljun yaluy nyajil.", "bula yiljun yaluy nyajil | 3du.NOM grasshopper here see.NPST", "r255_3du_target_here_see_yiljun", ["bula", "yiljun", "yaluy", "nyajil"], EVIDENCE["yiljun"]),
    row(41, "They see the flea there.", "Jana balarr yinyay nyajil.", "jana balarr yinyay nyajil | 3pl.NOM flea there see.NPST", "r255_3pl_target_there_see_balarr", ["jana", "balarr", "yinyay", "nyajil"], EVIDENCE["balarr"]),
    row(42, "They see the mayfly there.", "Jana dijaraban yinyay nyajil.", "jana dijaraban yinyay nyajil | 3pl.NOM mayfly there see.NPST", "r255_3pl_target_there_see_dijaraban", ["jana", "dijaraban", "yinyay", "nyajil"], EVIDENCE["dijaraban"]),
    row(43, "They see the kalburiji bee there.", "Jana kalburiji yinyay nyajil.", "jana kalburiji yinyay nyajil | 3pl.NOM kalburiji.bee there see.NPST", "r255_3pl_target_there_see_kalburiji", ["jana", "kalburiji", "yinyay", "nyajil"], EVIDENCE["kalburiji"]),
    row(44, "They see the mawal bee there.", "Jana mawal yinyay nyajil.", "jana mawal yinyay nyajil | 3pl.NOM mawal.bee there see.NPST", "r255_3pl_target_there_see_mawal", ["jana", "mawal", "yinyay", "nyajil"], EVIDENCE["mawal"]),
    row(45, "They see the scorpion there.", "Jana munudumbun yinyay nyajil.", "jana munudumbun yinyay nyajil | 3pl.NOM scorpion there see.NPST", "r255_3pl_target_there_see_munudumbun", ["jana", "munudumbun", "yinyay", "nyajil"], EVIDENCE["munudumbun"]),
    row(46, "They see the sandfly there.", "Jana munyurri yinyay nyajil.", "jana munyurri yinyay nyajil | 3pl.NOM sandfly there see.NPST", "r255_3pl_target_there_see_munyurri", ["jana", "munyurri", "yinyay", "nyajil"], EVIDENCE["munyurri"]),
    row(47, "They see the nakawarra bee there.", "Jana nakawarra yinyay nyajil.", "jana nakawarra yinyay nyajil | 3pl.NOM nakawarra.bee there see.NPST", "r255_3pl_target_there_see_nakawarra", ["jana", "nakawarra", "yinyay", "nyajil"], EVIDENCE["nakawarra"]),
    row(48, "They see the jumper ant there.", "Jana ngalmnbu yinyay nyajil.", "jana ngalmnbu yinyay nyajil | 3pl.NOM jumper.ant there see.NPST", "r255_3pl_target_there_see_ngalmnbu", ["jana", "ngalmnbu", "yinyay", "nyajil"], EVIDENCE["ngalmnbu"]),
    row(49, "They see the yarrka bee there.", "Jana yarrka yinyay nyajil.", "jana yarrka yinyay nyajil | 3pl.NOM yarrka.bee there see.NPST", "r255_3pl_target_there_see_yarrka", ["jana", "yarrka", "yinyay", "nyajil"], EVIDENCE["yarrka"]),
    row(50, "They see the grasshopper there.", "Jana yiljun yinyay nyajil.", "jana yiljun yinyay nyajil | 3pl.NOM grasshopper there see.NPST", "r255_3pl_target_there_see_yiljun", ["jana", "yiljun", "yinyay", "nyajil"], EVIDENCE["yiljun"]),
]


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("r255_"):
            issues.append(f"{label}: Rule 255 frame must start with r255_")
        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 255")
        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 255 target insect 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(" yinyay nyajil.") or len(low.split()) != 4):
            issues.append(f"{label}: rows 1-10 require Ngayu TARGET yinyay nyajil")
        if 11 <= seq <= 20 and (not low.startswith("nyulu ") or not low.endswith(" yaluy nyajil.") or len(low.split()) != 4):
            issues.append(f"{label}: rows 11-20 require Nyulu TARGET yaluy nyajil")
        if 21 <= seq <= 30 and (not low.startswith("yurra ") or not low.endswith(" yinyay nyajil.") or len(low.split()) != 4):
            issues.append(f"{label}: rows 21-30 require Yurra TARGET yinyay nyajil")
        if 31 <= seq <= 40 and (not low.startswith("bula ") or not low.endswith(" yaluy nyajil.") or len(low.split()) != 4):
            issues.append(f"{label}: rows 31-40 require Bula TARGET yaluy nyajil")
        if 41 <= seq <= 50 and (not low.startswith("jana ") or not low.endswith(" yinyay nyajil.") or len(low.split()) != 4):
            issues.append(f"{label}: rows 41-50 require Jana TARGET yinyay nyajil")
        if any(english_has_denied(english_low, bad) for bad in DENY_ENGLISH):
            issues.append(f"{label}: denied insect behavior/use/body/ecology/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 255 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 255 source pass checked exact dictionary lines for balarr flea, dijaraban mayfly, kalburiji bee, mawal bee, munudumbun scorpion, munyurri sandfly, nakawarra bee, ngalmnbu jumper ant, yarrka bee, and yiljun grasshopper; 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 255 insect-reference perception debt sweep after Rule 254: ten Rule 212 insect labels in five zero-collision nominative-pronoun perception bands. All biting, stinging, sickness, honey, nest, egg, larvae, edible, food, medicine, seasonal-signal, ecology, body-part, source-prose, 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 254: balarr 5, dijaraban 5, kalburiji 5, mawal 5, munudumbun 5, munyurri 5, nakawarra 5, ngalmnbu 5, yarrka 5, and yiljun 5. Support coverage: ngayu 1263, nyulu 1744, yurra 193, bula 173, jana 1466, yaluy 2223, yinyay 2476, nyajil 2567.",
        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 255 Kuku surfaces returned zero accepted, revised, or under-review collisions.",
        command="python3 batch_scripts/bank_297.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 255 target insect noun per row, exactly one bare nominative pronoun per row, no loans, no target suffixes, no excluded insect candidate, no behavior/use/ecology/body/source-prose drift, no pronoun case, no demonstrative case, no perception compound, and five planned frame bands only.",
        command="python3 batch_scripts/bank_297.py",
        artifact_path="batch_scripts/bank_297.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 255 insect-reference perception rows as under_review.",
        command="python3 batch_scripts/bank_297.py",
        artifact_path="batch_scripts/bank_297.py",
        created_at=NOW,
    )
    db.commit()
    print(f"banked {LABEL}: 50 under_review rows")
    return 0


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

