#!/usr/bin/env python3
"""Bank batch-364: Rule 322 zero-use anatomy non-singular nonpast perception."""

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-364"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
PROCESS_LOG = "process_logs/batch-364-zero-use-anatomy-nonsingular-nonpast-perception-after-rule321-process.md"

TARGET_EVIDENCE = {
    "dalkari": "Dictionary yaml lines 4857-4865 give dalkari directly as noun 'bladder'. Rule 322 uses visible dalkari-bladder reference only and leaves possession, person/animal attribution, urine, excretion, pain, illness, medicine, surgery, butchery, use, and event propositions closed.",
    "diburr-miyil": "Dictionary yaml lines 5502-5512 give the exact compound head diburr-miyil 'eyeball' and analyze diburr 'seed/egg' plus miyil 'eye'. Rule 322 admits only the whole eyeball head; it does not license decomposition, productive compounding, seed/egg or eye-part claims, possession, injury, vision state, medicine, use, or event propositions.",
    "jadalangka": "Dictionary yaml lines 6975-6985 give jadalangka directly as noun 'leg of a beast'. Rule 322 uses the conservative English label animal leg and leaves species, possession, movement, injury, butchery, food, hunting, cutting, carrying, use, and event propositions closed.",
    "mijan": "Dictionary yaml lines 18891-18899 give mijan directly as noun 'wart'. Rule 322 uses visible mijan-wart reference only and leaves possession, body location, pain, illness, contagion, medicine, removal, treatment, size, number, property, and event propositions closed.",
    "mungka-dirka": "Dictionary yaml lines 20646-20656 give the exact compound head mungka-dirka 'fur' and note mungka 'hair'. Rule 322 admits only the whole fur head; it does not license decomposition, productive compounding, animal/species source, possession, colour, texture, clothing/material use, removal, hunting, or event propositions.",
    "murrka": "Dictionary yaml lines 21045-21057 give murrka 'scar, scab, initiation marks' and explicitly distinguish it from an open wound. Rule 322 selects visible scar reference only and leaves scab, initiation/scarification, ritual, possession, injury cause, open wound, pain, medicine, healing, cultural practice, and event propositions closed.",
    "nyirribulu": "Dictionary yaml lines 24623-24631 give nyirribulu directly as noun 'appendix'. Rule 322 uses visible appendix reference only and leaves possession, person/animal attribution, pain, illness, inflammation, diagnosis, surgery, medicine, butchery, function, and event propositions closed.",
    "waral": "Dictionary yaml lines 26326-26335 give waral directly as noun 'stomach, belly'. Patz grammar line 2173 independently attests the lexeme in derived possessed form waral-ji-mu 'belly-COMIT-POSS'. Rule 322 selects bare visible stomach reference only and leaves belly alternation as a separate translation, possession, pregnancy, hunger, eating, digestion, pain, illness, greed compounds, medicine, butchery, and event propositions closed.",
    "wubun": "Dictionary yaml lines 27509-27517 give wubun directly as noun 'hump', with a Brahman-bull example. Rule 322 uses visible hump reference only and leaves Brahman/bull species attribution, possession, size, shape, back/body location, movement, burden, property, use, and event propositions closed.",
    "yinkan": "Dictionary yaml lines 30271-30280 give yinkan directly as noun 'ribs, side'. Rule 322 selects visible ribs reference only and leaves side alternation, possession, number morphology, body location, pain, injury, breathing, butchery, food, movement, lying-sideways expression, and event propositions closed.",
}

SUPPORT_EVIDENCE = (
    "Patz grammar line 1476 classifies external and internal body parts and bodily excretions as nouns. Examples at "
    "lines 4761-4771 and 5431 show bare body-part nouns jina 'foot', yimbi 'lips', and mara 'hand' without an overt "
    "possessive suffix when the possessor is contextually recoverable; section 4.5.2 at lines 5898-5917 distinguishes "
    "optional possessive/appositional constructions when possession itself is asserted. Rule 322 asserts no possessor. "
    "Patz pronoun lines 2577-2582 and person-number discussion 2674-2684 source bare nominatives ngali, ngaliny, "
    "yubal, yurra, and ngana; lines 2834-2847 source Yalanji yaluy 'here' and yinyay 'there'. Lines 3043-3049 give "
    "nonpast nyaji-l, lines 3149-3151 define present/future nonpast function, and lines 4256-4265 license nominative "
    "pronoun A with bare absolutive O for sensory perception. Dictionary lines 24282-24296 independently attest "
    "running-form nyajil and its visual sense. Exact Patz searches found waral once and the other nine target heads "
    "nowhere; all target lexical identities remain dictionary-anchored."
)

TARGET_ORDER = [
    "dalkari", "diburr-miyil", "jadalangka", "mijan", "mungka-dirka",
    "murrka", "nyirribulu", "waral", "wubun", "yinkan",
]
TARGET_LABELS = {
    "dalkari": "dalkari bladder",
    "diburr-miyil": "diburr-miyil eyeball",
    "jadalangka": "jadalangka animal leg",
    "mijan": "mijan wart",
    "mungka-dirka": "mungka-dirka fur",
    "murrka": "murrka scar",
    "nyirribulu": "nyirribulu appendix",
    "waral": "waral stomach",
    "wubun": "wubun hump",
    "yinkan": "yinkan ribs",
}
TARGET_GLOSSES = {
    "dalkari": "dalkari.bladder",
    "diburr-miyil": "diburr.miyil.eyeball",
    "jadalangka": "jadalangka.animal.leg",
    "mijan": "mijan.wart",
    "mungka-dirka": "mungka.dirka.fur",
    "murrka": "murrka.scar",
    "nyirribulu": "nyirribulu.appendix",
    "waral": "waral.stomach",
    "wubun": "wubun.hump",
    "yinkan": "yinkan.ribs",
}
TARGET_CONFIDENCE = {
    "dalkari": "0.86",
    "diburr-miyil": "0.87",
    "jadalangka": "0.86",
    "mijan": "0.87",
    "mungka-dirka": "0.87",
    "murrka": "0.85",
    "nyirribulu": "0.86",
    "waral": "0.89",
    "wubun": "0.86",
    "yinkan": "0.87",
}
EXPECTED_TARGET_COVERAGE = {target: 0 for target in TARGET_ORDER}
FRAME_SPECS = [
    ("ngali", "yaluy", "We two, not you, see", "here", "1du.excl"),
    ("ngaliny", "yinyay", "You and I see", "there", "1du.incl"),
    ("yubal", "yaluy", "You two see", "here", "2du"),
    ("yurra", "yinyay", "You all see", "there", "2pl"),
    ("ngana", "yaluy", "We see", "here", "1pl.incl"),
]

DENY_KUKU = {
    "ngayu", "yundu", "nyulu", "yulu", "bula", "jana", "iana", "nganjin",
    "ngalingan", "ngalinyan", "yubalan", "ngalininy", "ngalinyiny", "yubaliny",
    "ngalinka", "ngalinyanka", "yubalanka", "ngalinda", "ngalinyanda", "yubalanda",
    "ngalindamuny", "ngalinyandamuny", "yubalandamuny", "ngalinji", "ngalinyanji", "yubalanji",
    "ngalinga", "ngalinyanga", "yubalanga", "yurrangan", "yurraniny", "yurranka", "yurranda",
    "yurrandamuny", "yurranji", "yurranga", "nganangan", "ngananiny", "ngananka", "ngananda",
    "nganandamuny", "ngananji", "ngananga",
    "diburr", "miyil", "mungka", "dirka", "kurrburrbun", "ngarran", "wulbar", "yiman", "juwul",
    "yalay", "yala", "yanyu", "yinya", "yalungku", "yaluyngku", "yinyangka", "yinyayngka",
    "yalamuny", "yinyamuny", "nyajin", "nyaji-ny", "nyaji-nka", "nyaji-l-nyaji", "milka", "baykal", "jalngkay",
}
DENY_ENGLISH = (
    "my", "your", "his", "her", "our", "their", "possess", "owner", "urine", "excretion", "pain", "sick",
    "illness", "medicine", "surgery", "diagnosis", "inflammation", "treatment", "remove", "removal", "heal",
    "healing", "butcher", "butchery", "food", "eat", "eating", "cook", "hunger", "digestion", "pregnant",
    "pregnancy", "seed", "egg", "eye", "vision", "injury", "wound", "open", "scab", "initiation",
    "scarification", "ritual", "witchcraft", "cultural", "species", "hunt", "hunting", "cut", "carry",
    "clothing", "material", "colour", "color", "texture", "brahman", "bull", "shape", "back", "burden",
    "belly", "greed", "greedy", "side", "breath", "breathing", "sideways", "movement", "function", "number",
    "compound", "event", "use", "used", "using",
)


def count_words(db: sqlite3.Connection, words: list[str]) -> dict[str, int]:
    return {
        word: db.execute(
            """SELECT COUNT(*) FROM sentences s
               WHERE s.status IN ('accepted','revised')
                 AND EXISTS (SELECT 1 FROM json_each(s.words_used) WHERE lower(value)=?)""",
            (word,),
        ).fetchone()[0]
        for word in words
    }


def row(seq: int, english: str, kuku: str, analysis: str, frame: str, words: list[str]) -> tuple:
    target = words[1]
    return (
        seq, english, kuku, analysis, frame, 3,
        json.dumps(words, ensure_ascii=False), json.dumps([], ensure_ascii=False),
        f"{TARGET_EVIDENCE[target]} {SUPPORT_EVIDENCE}", TARGET_CONFIDENCE[target],
    )


ROWS = [
    row(1, "We two, not you, see the dalkari bladder here.", "Ngali dalkari yaluy nyajil.", "ngali dalkari yaluy nyajil | 1du.excl.NOM dalkari.bladder here see.NPST", "r322_1du_excl_here_zero_anatomy_see_dalkari", ["ngali", "dalkari", "yaluy", "nyajil"]),
    row(2, "We two, not you, see the diburr-miyil eyeball here.", "Ngali diburr-miyil yaluy nyajil.", "ngali diburr-miyil yaluy nyajil | 1du.excl.NOM diburr.miyil.eyeball here see.NPST", "r322_1du_excl_here_zero_anatomy_see_diburr_miyil", ["ngali", "diburr-miyil", "yaluy", "nyajil"]),
    row(3, "We two, not you, see the jadalangka animal leg here.", "Ngali jadalangka yaluy nyajil.", "ngali jadalangka yaluy nyajil | 1du.excl.NOM jadalangka.animal.leg here see.NPST", "r322_1du_excl_here_zero_anatomy_see_jadalangka", ["ngali", "jadalangka", "yaluy", "nyajil"]),
    row(4, "We two, not you, see the mijan wart here.", "Ngali mijan yaluy nyajil.", "ngali mijan yaluy nyajil | 1du.excl.NOM mijan.wart here see.NPST", "r322_1du_excl_here_zero_anatomy_see_mijan", ["ngali", "mijan", "yaluy", "nyajil"]),
    row(5, "We two, not you, see the mungka-dirka fur here.", "Ngali mungka-dirka yaluy nyajil.", "ngali mungka-dirka yaluy nyajil | 1du.excl.NOM mungka.dirka.fur here see.NPST", "r322_1du_excl_here_zero_anatomy_see_mungka_dirka", ["ngali", "mungka-dirka", "yaluy", "nyajil"]),
    row(6, "We two, not you, see the murrka scar here.", "Ngali murrka yaluy nyajil.", "ngali murrka yaluy nyajil | 1du.excl.NOM murrka.scar here see.NPST", "r322_1du_excl_here_zero_anatomy_see_murrka", ["ngali", "murrka", "yaluy", "nyajil"]),
    row(7, "We two, not you, see the nyirribulu appendix here.", "Ngali nyirribulu yaluy nyajil.", "ngali nyirribulu yaluy nyajil | 1du.excl.NOM nyirribulu.appendix here see.NPST", "r322_1du_excl_here_zero_anatomy_see_nyirribulu", ["ngali", "nyirribulu", "yaluy", "nyajil"]),
    row(8, "We two, not you, see the waral stomach here.", "Ngali waral yaluy nyajil.", "ngali waral yaluy nyajil | 1du.excl.NOM waral.stomach here see.NPST", "r322_1du_excl_here_zero_anatomy_see_waral", ["ngali", "waral", "yaluy", "nyajil"]),
    row(9, "We two, not you, see the wubun hump here.", "Ngali wubun yaluy nyajil.", "ngali wubun yaluy nyajil | 1du.excl.NOM wubun.hump here see.NPST", "r322_1du_excl_here_zero_anatomy_see_wubun", ["ngali", "wubun", "yaluy", "nyajil"]),
    row(10, "We two, not you, see the yinkan ribs here.", "Ngali yinkan yaluy nyajil.", "ngali yinkan yaluy nyajil | 1du.excl.NOM yinkan.ribs here see.NPST", "r322_1du_excl_here_zero_anatomy_see_yinkan", ["ngali", "yinkan", "yaluy", "nyajil"]),
    row(11, "You and I see the dalkari bladder there.", "Ngaliny dalkari yinyay nyajil.", "ngaliny dalkari yinyay nyajil | 1du.incl.NOM dalkari.bladder there see.NPST", "r322_1du_incl_there_zero_anatomy_see_dalkari", ["ngaliny", "dalkari", "yinyay", "nyajil"]),
    row(12, "You and I see the diburr-miyil eyeball there.", "Ngaliny diburr-miyil yinyay nyajil.", "ngaliny diburr-miyil yinyay nyajil | 1du.incl.NOM diburr.miyil.eyeball there see.NPST", "r322_1du_incl_there_zero_anatomy_see_diburr_miyil", ["ngaliny", "diburr-miyil", "yinyay", "nyajil"]),
    row(13, "You and I see the jadalangka animal leg there.", "Ngaliny jadalangka yinyay nyajil.", "ngaliny jadalangka yinyay nyajil | 1du.incl.NOM jadalangka.animal.leg there see.NPST", "r322_1du_incl_there_zero_anatomy_see_jadalangka", ["ngaliny", "jadalangka", "yinyay", "nyajil"]),
    row(14, "You and I see the mijan wart there.", "Ngaliny mijan yinyay nyajil.", "ngaliny mijan yinyay nyajil | 1du.incl.NOM mijan.wart there see.NPST", "r322_1du_incl_there_zero_anatomy_see_mijan", ["ngaliny", "mijan", "yinyay", "nyajil"]),
    row(15, "You and I see the mungka-dirka fur there.", "Ngaliny mungka-dirka yinyay nyajil.", "ngaliny mungka-dirka yinyay nyajil | 1du.incl.NOM mungka.dirka.fur there see.NPST", "r322_1du_incl_there_zero_anatomy_see_mungka_dirka", ["ngaliny", "mungka-dirka", "yinyay", "nyajil"]),
    row(16, "You and I see the murrka scar there.", "Ngaliny murrka yinyay nyajil.", "ngaliny murrka yinyay nyajil | 1du.incl.NOM murrka.scar there see.NPST", "r322_1du_incl_there_zero_anatomy_see_murrka", ["ngaliny", "murrka", "yinyay", "nyajil"]),
    row(17, "You and I see the nyirribulu appendix there.", "Ngaliny nyirribulu yinyay nyajil.", "ngaliny nyirribulu yinyay nyajil | 1du.incl.NOM nyirribulu.appendix there see.NPST", "r322_1du_incl_there_zero_anatomy_see_nyirribulu", ["ngaliny", "nyirribulu", "yinyay", "nyajil"]),
    row(18, "You and I see the waral stomach there.", "Ngaliny waral yinyay nyajil.", "ngaliny waral yinyay nyajil | 1du.incl.NOM waral.stomach there see.NPST", "r322_1du_incl_there_zero_anatomy_see_waral", ["ngaliny", "waral", "yinyay", "nyajil"]),
    row(19, "You and I see the wubun hump there.", "Ngaliny wubun yinyay nyajil.", "ngaliny wubun yinyay nyajil | 1du.incl.NOM wubun.hump there see.NPST", "r322_1du_incl_there_zero_anatomy_see_wubun", ["ngaliny", "wubun", "yinyay", "nyajil"]),
    row(20, "You and I see the yinkan ribs there.", "Ngaliny yinkan yinyay nyajil.", "ngaliny yinkan yinyay nyajil | 1du.incl.NOM yinkan.ribs there see.NPST", "r322_1du_incl_there_zero_anatomy_see_yinkan", ["ngaliny", "yinkan", "yinyay", "nyajil"]),
    row(21, "You two see the dalkari bladder here.", "Yubal dalkari yaluy nyajil.", "yubal dalkari yaluy nyajil | 2du.NOM dalkari.bladder here see.NPST", "r322_2du_here_zero_anatomy_see_dalkari", ["yubal", "dalkari", "yaluy", "nyajil"]),
    row(22, "You two see the diburr-miyil eyeball here.", "Yubal diburr-miyil yaluy nyajil.", "yubal diburr-miyil yaluy nyajil | 2du.NOM diburr.miyil.eyeball here see.NPST", "r322_2du_here_zero_anatomy_see_diburr_miyil", ["yubal", "diburr-miyil", "yaluy", "nyajil"]),
    row(23, "You two see the jadalangka animal leg here.", "Yubal jadalangka yaluy nyajil.", "yubal jadalangka yaluy nyajil | 2du.NOM jadalangka.animal.leg here see.NPST", "r322_2du_here_zero_anatomy_see_jadalangka", ["yubal", "jadalangka", "yaluy", "nyajil"]),
    row(24, "You two see the mijan wart here.", "Yubal mijan yaluy nyajil.", "yubal mijan yaluy nyajil | 2du.NOM mijan.wart here see.NPST", "r322_2du_here_zero_anatomy_see_mijan", ["yubal", "mijan", "yaluy", "nyajil"]),
    row(25, "You two see the mungka-dirka fur here.", "Yubal mungka-dirka yaluy nyajil.", "yubal mungka-dirka yaluy nyajil | 2du.NOM mungka.dirka.fur here see.NPST", "r322_2du_here_zero_anatomy_see_mungka_dirka", ["yubal", "mungka-dirka", "yaluy", "nyajil"]),
    row(26, "You two see the murrka scar here.", "Yubal murrka yaluy nyajil.", "yubal murrka yaluy nyajil | 2du.NOM murrka.scar here see.NPST", "r322_2du_here_zero_anatomy_see_murrka", ["yubal", "murrka", "yaluy", "nyajil"]),
    row(27, "You two see the nyirribulu appendix here.", "Yubal nyirribulu yaluy nyajil.", "yubal nyirribulu yaluy nyajil | 2du.NOM nyirribulu.appendix here see.NPST", "r322_2du_here_zero_anatomy_see_nyirribulu", ["yubal", "nyirribulu", "yaluy", "nyajil"]),
    row(28, "You two see the waral stomach here.", "Yubal waral yaluy nyajil.", "yubal waral yaluy nyajil | 2du.NOM waral.stomach here see.NPST", "r322_2du_here_zero_anatomy_see_waral", ["yubal", "waral", "yaluy", "nyajil"]),
    row(29, "You two see the wubun hump here.", "Yubal wubun yaluy nyajil.", "yubal wubun yaluy nyajil | 2du.NOM wubun.hump here see.NPST", "r322_2du_here_zero_anatomy_see_wubun", ["yubal", "wubun", "yaluy", "nyajil"]),
    row(30, "You two see the yinkan ribs here.", "Yubal yinkan yaluy nyajil.", "yubal yinkan yaluy nyajil | 2du.NOM yinkan.ribs here see.NPST", "r322_2du_here_zero_anatomy_see_yinkan", ["yubal", "yinkan", "yaluy", "nyajil"]),
    row(31, "You all see the dalkari bladder there.", "Yurra dalkari yinyay nyajil.", "yurra dalkari yinyay nyajil | 2pl.NOM dalkari.bladder there see.NPST", "r322_2pl_there_zero_anatomy_see_dalkari", ["yurra", "dalkari", "yinyay", "nyajil"]),
    row(32, "You all see the diburr-miyil eyeball there.", "Yurra diburr-miyil yinyay nyajil.", "yurra diburr-miyil yinyay nyajil | 2pl.NOM diburr.miyil.eyeball there see.NPST", "r322_2pl_there_zero_anatomy_see_diburr_miyil", ["yurra", "diburr-miyil", "yinyay", "nyajil"]),
    row(33, "You all see the jadalangka animal leg there.", "Yurra jadalangka yinyay nyajil.", "yurra jadalangka yinyay nyajil | 2pl.NOM jadalangka.animal.leg there see.NPST", "r322_2pl_there_zero_anatomy_see_jadalangka", ["yurra", "jadalangka", "yinyay", "nyajil"]),
    row(34, "You all see the mijan wart there.", "Yurra mijan yinyay nyajil.", "yurra mijan yinyay nyajil | 2pl.NOM mijan.wart there see.NPST", "r322_2pl_there_zero_anatomy_see_mijan", ["yurra", "mijan", "yinyay", "nyajil"]),
    row(35, "You all see the mungka-dirka fur there.", "Yurra mungka-dirka yinyay nyajil.", "yurra mungka-dirka yinyay nyajil | 2pl.NOM mungka.dirka.fur there see.NPST", "r322_2pl_there_zero_anatomy_see_mungka_dirka", ["yurra", "mungka-dirka", "yinyay", "nyajil"]),
    row(36, "You all see the murrka scar there.", "Yurra murrka yinyay nyajil.", "yurra murrka yinyay nyajil | 2pl.NOM murrka.scar there see.NPST", "r322_2pl_there_zero_anatomy_see_murrka", ["yurra", "murrka", "yinyay", "nyajil"]),
    row(37, "You all see the nyirribulu appendix there.", "Yurra nyirribulu yinyay nyajil.", "yurra nyirribulu yinyay nyajil | 2pl.NOM nyirribulu.appendix there see.NPST", "r322_2pl_there_zero_anatomy_see_nyirribulu", ["yurra", "nyirribulu", "yinyay", "nyajil"]),
    row(38, "You all see the waral stomach there.", "Yurra waral yinyay nyajil.", "yurra waral yinyay nyajil | 2pl.NOM waral.stomach there see.NPST", "r322_2pl_there_zero_anatomy_see_waral", ["yurra", "waral", "yinyay", "nyajil"]),
    row(39, "You all see the wubun hump there.", "Yurra wubun yinyay nyajil.", "yurra wubun yinyay nyajil | 2pl.NOM wubun.hump there see.NPST", "r322_2pl_there_zero_anatomy_see_wubun", ["yurra", "wubun", "yinyay", "nyajil"]),
    row(40, "You all see the yinkan ribs there.", "Yurra yinkan yinyay nyajil.", "yurra yinkan yinyay nyajil | 2pl.NOM yinkan.ribs there see.NPST", "r322_2pl_there_zero_anatomy_see_yinkan", ["yurra", "yinkan", "yinyay", "nyajil"]),
    row(41, "We see the dalkari bladder here.", "Ngana dalkari yaluy nyajil.", "ngana dalkari yaluy nyajil | 1pl.incl.NOM dalkari.bladder here see.NPST", "r322_1pl_incl_here_zero_anatomy_see_dalkari", ["ngana", "dalkari", "yaluy", "nyajil"]),
    row(42, "We see the diburr-miyil eyeball here.", "Ngana diburr-miyil yaluy nyajil.", "ngana diburr-miyil yaluy nyajil | 1pl.incl.NOM diburr.miyil.eyeball here see.NPST", "r322_1pl_incl_here_zero_anatomy_see_diburr_miyil", ["ngana", "diburr-miyil", "yaluy", "nyajil"]),
    row(43, "We see the jadalangka animal leg here.", "Ngana jadalangka yaluy nyajil.", "ngana jadalangka yaluy nyajil | 1pl.incl.NOM jadalangka.animal.leg here see.NPST", "r322_1pl_incl_here_zero_anatomy_see_jadalangka", ["ngana", "jadalangka", "yaluy", "nyajil"]),
    row(44, "We see the mijan wart here.", "Ngana mijan yaluy nyajil.", "ngana mijan yaluy nyajil | 1pl.incl.NOM mijan.wart here see.NPST", "r322_1pl_incl_here_zero_anatomy_see_mijan", ["ngana", "mijan", "yaluy", "nyajil"]),
    row(45, "We see the mungka-dirka fur here.", "Ngana mungka-dirka yaluy nyajil.", "ngana mungka-dirka yaluy nyajil | 1pl.incl.NOM mungka.dirka.fur here see.NPST", "r322_1pl_incl_here_zero_anatomy_see_mungka_dirka", ["ngana", "mungka-dirka", "yaluy", "nyajil"]),
    row(46, "We see the murrka scar here.", "Ngana murrka yaluy nyajil.", "ngana murrka yaluy nyajil | 1pl.incl.NOM murrka.scar here see.NPST", "r322_1pl_incl_here_zero_anatomy_see_murrka", ["ngana", "murrka", "yaluy", "nyajil"]),
    row(47, "We see the nyirribulu appendix here.", "Ngana nyirribulu yaluy nyajil.", "ngana nyirribulu yaluy nyajil | 1pl.incl.NOM nyirribulu.appendix here see.NPST", "r322_1pl_incl_here_zero_anatomy_see_nyirribulu", ["ngana", "nyirribulu", "yaluy", "nyajil"]),
    row(48, "We see the waral stomach here.", "Ngana waral yaluy nyajil.", "ngana waral yaluy nyajil | 1pl.incl.NOM waral.stomach here see.NPST", "r322_1pl_incl_here_zero_anatomy_see_waral", ["ngana", "waral", "yaluy", "nyajil"]),
    row(49, "We see the wubun hump here.", "Ngana wubun yaluy nyajil.", "ngana wubun yaluy nyajil | 1pl.incl.NOM wubun.hump here see.NPST", "r322_1pl_incl_here_zero_anatomy_see_wubun", ["ngana", "wubun", "yaluy", "nyajil"]),
    row(50, "We see the yinkan ribs here.", "Ngana yinkan yaluy nyajil.", "ngana yinkan yaluy nyajil | 1pl.incl.NOM yinkan.ribs here see.NPST", "r322_1pl_incl_here_zero_anatomy_see_yinkan", ["ngana", "yinkan", "yaluy", "nyajil"]),
]


def scan_static() -> list[str]:
    issues: list[str] = []
    if len(ROWS) != 50:
        issues.append(f"row count {len(ROWS)} != 50")
    if [r[0] for r in ROWS] != list(range(1, 51)):
        issues.append("sequence is not 1..50")
    if len({r[1] for r in ROWS}) != 50:
        issues.append("duplicate English surface inside batch")
    if len({r[2] for r in ROWS}) != 50:
        issues.append("duplicate Kuku surface inside batch")
    for seq, english, kuku, analysis, frame, _tier, words_json, loans_json, evidence, confidence in ROWS:
        words = json.loads(words_json)
        loans = json.loads(loans_json)
        band = (seq - 1) // 10
        target = TARGET_ORDER[(seq - 1) % 10]
        pronoun, demo, prefix, location, person_gloss = FRAME_SPECS[band]
        expected_kuku = f"{pronoun.capitalize()} {target} {demo} nyajil."
        expected_english = f"{prefix} the {TARGET_LABELS[target]} {location}."
        expected_analysis = f"{pronoun} {target} {demo} nyajil | {person_gloss}.NOM {TARGET_GLOSSES[target]} {location} see.NPST"
        low_kuku = kuku.lower()
        low_english = english.lower()
        if loans:
            issues.append(f"{seq}: loans used {loans}")
        denied = sorted({w for w in DENY_KUKU if re.search(rf"(^|\s){re.escape(w)}([\s\.]|$)", low_kuku)})
        if denied:
            issues.append(f"{seq}: denied Kuku forms {denied}")
        denied_english = [term for term in DENY_ENGLISH if re.search(rf"\b{re.escape(term)}\b", low_english)]
        if denied_english:
            issues.append(f"{seq}: denied English drift {denied_english}")
        if kuku != expected_kuku:
            issues.append(f"{seq}: Kuku mismatch expected {expected_kuku!r}, got {kuku!r}")
        if english != expected_english:
            issues.append(f"{seq}: English mismatch expected {expected_english!r}, got {english!r}")
        if analysis != expected_analysis:
            issues.append(f"{seq}: analysis mismatch expected {expected_analysis!r}, got {analysis!r}")
        if words != [pronoun, target, demo, "nyajil"]:
            issues.append(f"{seq}: words mismatch {words}")
        if low_kuku.rstrip(".") != " ".join(words):
            issues.append(f"{seq}: Kuku does not match words_used")
        if not frame.startswith("r322_"):
            issues.append(f"{seq}: frame not r322 {frame}")
        if TARGET_EVIDENCE[target] not in evidence or SUPPORT_EVIDENCE not in evidence:
            issues.append(f"{seq}: evidence contract mismatch")
        if confidence != TARGET_CONFIDENCE[target]:
            issues.append(f"{seq}: confidence mismatch {confidence}")
    return issues


def main() -> int:
    issues = scan_static()
    if issues:
        print("\n".join(issues))
        raise SystemExit(1)
    db = sqlite3.connect(DB)
    db.execute("PRAGMA foreign_keys=ON")
    db.execute("BEGIN")
    ensure_schema(db)
    if db.execute("SELECT 1 FROM batches WHERE label=?", (LABEL,)).fetchone():
        raise SystemExit(f"{LABEL} already exists")
    target_counts = count_words(db, TARGET_ORDER)
    if target_counts != EXPECTED_TARGET_COVERAGE:
        raise SystemExit(f"target coverage changed; rerun source/scope audit: {target_counts}")
    support_counts = count_words(db, ["ngali", "ngaliny", "yubal", "yurra", "ngana", "yaluy", "yinyay", "nyajil"])
    collisions = []
    for _seq, _english, kuku, *_rest in ROWS:
        hit = 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!='rejected'",
            (kuku,),
        ).fetchall()
        if hit:
            collisions.append((kuku, hit))
    if collisions:
        raise SystemExit(f"duplicate preflight failed: {collisions}")
    verified_before, words_before = db.execute(
        "SELECT COUNT(*),SUM(LENGTH(kuku)-LENGTH(REPLACE(kuku,' ',''))+1) "
        "FROM sentences WHERE status IN ('accepted','revised')"
    ).fetchone()
    notes = (
        "ZERO-USE ANATOMY/BODY-SURFACE NON-SINGULAR NONPAST PERCEPTION SWEEP AFTER RULE 321 (Rule 322). 50 "
        "under-review rows over ten zero-use noun-typed heads: dalkari, diburr-miyil, jadalangka, mijan, "
        "mungka-dirka, murrka, nyirribulu, waral, wubun, yinkan. SUPPORT: bare nominative ngali, ngaliny, yubal, "
        "yurra, ngana; Yalanji yaluy/yinyay; dictionary-attested nonpast nyajil. Bare targets assert no possessor. "
        "No compound decomposition, possession, person/animal attribution beyond lexical labels, pain/illness/medicine/"
        "surgery, injury/ritual/initiation, butchery/food/hunting, material use, property, target case, past/purposive/"
        "reduplicated perception, support inflection, or carried trap is opened."
    )
    cur = db.execute(
        "INSERT INTO batches(label,cheatsheet_version,guide_version,notes,created_at) VALUES(?,?,?,?,?)",
        (LABEL, "Rule 322 under review", "operator-guide-2026-07-10", notes, NOW),
    )
    batch_id = cur.lastrowid
    db.executemany(
        "INSERT INTO sentences(batch_id,seq,english,kuku,analysis,frame,tier,words_used,loans_used,evidence,status,confidence,rights_status,author,created_at,updated_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
        [
            (batch_id, seq, en, ku, an, fr, ti, wo, lo, ev, "under_review", co,
             "project_approved_synthetic_pending_elder_verification", "codex-main", NOW, NOW)
            for seq, en, ku, an, fr, ti, wo, lo, ev, co in ROWS
        ],
    )
    record_event(db, batch_label=LABEL, phase="source", event_type="source-readback", actor="codex", detail="Reread all ten selected dictionary anatomy/body-surface entries; exact-searched every target in Patz (waral occurs once in derived possessed form, the other nine do not occur); reread Patz noun semantics, bare/contextually possessed body-part examples, inalienable possession, non-singular nominatives, Yalanji local demonstratives, nonpast, sensory-perception A/O, and dictionary running-form nyajil before authoring Rule 322.", artifact_path=PROCESS_LOG, created_at=NOW)
    record_event(db, batch_label=LABEL, phase="planning", event_type="candidate-audit", actor="codex", detail="Structured dictionary-to-corpus audit found 31 zero-use body-part-domain heads. Selected ten exact noun-typed, lint-safe, visually referable heads. Excluded type-mislabeled ngarran and wulbar, dialect-only and homograph-heavy heads, unresolved kurrburrbun/kuburrubun near-variants, and witchcraft/place-heavy candidates. Previously deferred medical, animal-source, compound, and scar heads are admitted only for narrow entity reference with all source-prose semantics closed.", artifact_path=PROCESS_LOG, created_at=NOW)
    record_event(db, batch_label=LABEL, phase="planning", event_type="zero-anatomy-nonsingular-nonpast-scope", actor="codex", detail="Locked ten zero-use dictionary anatomy/body-surface nouns to bare visible reference in five sourced non-singular nonpast-perception frames. Bare O does not assert a possessor; diburr-miyil and mungka-dirka remain indivisible dictionary compounds; murrka is scar only; waral is stomach only; no medical, ritual, use, property, event, case, or support claim is opened.", artifact_path=PROCESS_LOG, created_at=NOW)
    record_event(db, batch_label=LABEL, phase="preflight", event_type="coverage-audit", actor="codex", detail=f"Token-aware accepted/revised coverage before banking: targets={target_counts}; support={support_counts}.", artifact_path=PROCESS_LOG, created_at=NOW)
    record_event(db, batch_label=LABEL, phase="preflight", event_type="duplicate-preflight", actor="codex", detail="All 50 Rule 322 exact Kuku surfaces are internally unique and returned no accepted, revised, or under-review corpus collisions.", artifact_path=PROCESS_LOG, created_at=NOW)
    record_event(db, batch_label=LABEL, phase="preflight", event_type="static-guard-pass", actor="codex", detail="Static guard passed: 50 explicit rows, exact Kuku/English/analysis/evidence/confidence contracts, one selected anatomy head each, bare non-singular pronouns and Yalanji demonstratives, final nyajil, no loans, no denied forms, and no possession, medical, ritual, use, property, event, compound-decomposition, or prior-row drift.", command="python3 -m py_compile batch_scripts/bank_364.py batch_scripts/close_364.py && explicit-row/lesson/lexeme AST inventory && scan_static/lint probes", output_excerpt="50 explicit rows; scan_static issues 0; 50 linter probes issues 0; collisions 0", artifact_path="batch_scripts/bank_364.py", created_at=NOW)
    record_event(db, batch_label=LABEL, phase="bank", event_type="bank-success", actor="codex", detail=f"Banked 50 Rule 322 rows as under_review. Verified remains {verified_before}; Kuku words remain {words_before}.", command="python3 batch_scripts/bank_364.py", output_excerpt=f"banked batch-364: 50 under_review; verified_before={verified_before}; kuku_words_before={words_before}", artifact_path=PROCESS_LOG, created_at=NOW)
    db.commit()
    print("banked batch-364: 50 rows under_review")
    return 0


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