#!/usr/bin/env python3
"""Bank batch-363: Rule 321 zero/low-use bird singular/third past 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-363"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
PROCESS_LOG = "process_logs/batch-363-zero-low-bird-singular-third-past-perception-after-rule320-process.md"

TARGET_EVIDENCE = {
    "binjurr-binjurr": "Dictionary yaml lines 3049-3062 give the exact hyphenated noun binjurr-binjurr as a species of honey eater. Rule 321 uses visible binjurr-binjurr honeyeater reference only; it does not equate the head with solid binjurrbinjurr, assert robin identity, or import feeding, honey, call, habitat, color, or behavior.",
    "bujarr-bujarr": "Dictionary yaml lines 3615-3628 give the populated fauna-bird entry bujarr-bujarr with gloss and definition 'black bird'; lines 3606-3614 are an empty duplicate record. Rule 321 uses the whole lexicalized head as bujarr-bujarr bird reference only and does not turn the source gloss into a productive black-color predicate or import call, habitat, behavior, or event content.",
    "dakwul-dakwul": "Dictionary yaml lines 4703-4732 give dakwul-dakwul as a brown-and-white scrub bird and include display prose. Rule 321 selects visible dakwul-dakwul scrub-bird reference only and leaves color, sex, head/eye anatomy, clearing, group, circle, singing, dancing, display, habitat, and event propositions closed.",
    "dibirr-dibirr": "Dictionary yaml lines 5452-5466 give the exact hyphenated noun dibirr-dibirr as 'rainbow bird'. Rule 321 uses that lexical common-name reference only and does not equate it with solid dibirrdibirr, assert honeyeater identity, or import color, rainbow appearance, call, iconicity, onomatopoeia, behavior, or event content.",
    "julurr-julurr": "Dictionary yaml lines 10719-10750 give julurr-julurr as 'moomoo bird' and variously identify owl, night owl, or night hawk. Rule 321 preserves the source-local label moomoo bird without resolving species and leaves owl/night-hawk equivalence, nocturnality, call, omen, habitat, behavior, and event propositions closed.",
    "muya": "Dictionary yaml lines 21330-21351 classify muya as a kind of bird while explicitly recording that its English name is unknown. Rule 321 therefore translates only 'muya bird' and makes no species, appearance, sound, habitat, behavior, use, or event claim.",
    "juril-juril": "Dictionary yaml lines 11199-11227 give juril-juril directly as seashore plover. Rule 321 uses visible juril-juril plover reference only and does not import the homophonous verb juril 'eject', beach/water habitat, running, feeding, crab, tide, flock, nest, call, or prior-corpus event propositions.",
    "dawa-dawa": "Dictionary yaml lines 5340-5354 give the exact hyphenated noun dawa-dawa as a species of magpie and distinguish solid dawadawa as a compared form. Rule 321 uses visible dawa-dawa magpie reference only and does not import song, call, dawn/time, weather, message, country, flock, habitat, behavior, or prior-corpus event propositions.",
    "bulnja": "Dictionary yaml lines 3893-3909 contain an empty duplicate and a populated fauna-bird entry identifying bulnja as frogmouth/mopoke. Rule 321 selects visible bulnja frogmouth reference only and leaves mopoke synonymy, nocturnality, branch posture, camouflage, mouth/anatomy, feeding, insects, warning, call, habitat, behavior, and prior-corpus events closed.",
    "jinabiju": "Dictionary yaml lines 9327-9347 identify jinabiju as chicken hawk/goshawk. Rule 321 uses the conservative goshawk label in visible reference only and leaves chicken/chick, hunting, snatching, flight, wind, diving, prey, silence, warning, habitat, body-part, behavior, and prior-corpus event propositions closed.",
}

SUPPORT_EVIDENCE = (
    "Patz grammar lines 2577-2582 source bare nominatives ngayu, yundu, nyulu, bula, and jana/iana; "
    "lines 2834-2847 source Yalanji yaluy 'here' and yinyay 'there'. Patz example 67b at lines 2021-2024 "
    "directly gives Ngayu ... nyaji-ny 'I saw ...', lines 3160-3162 define past -ny, and lines 4256-4265 "
    "license nominative pronoun A with bare absolutive O for sensory perception. Dictionary usage lines "
    "23876-23883 and 23968-23976 independently attest running-form nyajin in complete visual-perception "
    "clauses. Exact searches found none of the ten target heads in Patz; their lexical evidence therefore comes "
    "from the dictionary, while Patz supplies the construction. Rule 321 uses only bare support and past visual perception."
)

TARGET_ORDER = [
    "binjurr-binjurr", "bujarr-bujarr", "dakwul-dakwul", "dibirr-dibirr", "julurr-julurr",
    "muya", "juril-juril", "dawa-dawa", "bulnja", "jinabiju",
]
TARGET_LABELS = {
    "binjurr-binjurr": "binjurr-binjurr honeyeater",
    "bujarr-bujarr": "bujarr-bujarr bird",
    "dakwul-dakwul": "dakwul-dakwul scrub bird",
    "dibirr-dibirr": "dibirr-dibirr rainbow bird",
    "julurr-julurr": "julurr-julurr moomoo bird",
    "muya": "muya bird",
    "juril-juril": "juril-juril seashore plover",
    "dawa-dawa": "dawa-dawa magpie",
    "bulnja": "bulnja frogmouth",
    "jinabiju": "jinabiju goshawk",
}
TARGET_GLOSSES = {
    "binjurr-binjurr": "binjurr.binjurr.honeyeater",
    "bujarr-bujarr": "bujarr.bujarr.bird",
    "dakwul-dakwul": "dakwul.dakwul.scrub.bird",
    "dibirr-dibirr": "dibirr.dibirr.rainbow.bird",
    "julurr-julurr": "julurr.julurr.moomoo.bird",
    "muya": "muya.bird",
    "juril-juril": "juril.juril.seashore.plover",
    "dawa-dawa": "dawa.dawa.magpie",
    "bulnja": "bulnja.frogmouth",
    "jinabiju": "jinabiju.goshawk",
}
TARGET_CONFIDENCE = {
    "binjurr-binjurr": "0.87",
    "bujarr-bujarr": "0.84",
    "dakwul-dakwul": "0.86",
    "dibirr-dibirr": "0.87",
    "julurr-julurr": "0.84",
    "muya": "0.84",
    "juril-juril": "0.88",
    "dawa-dawa": "0.88",
    "bulnja": "0.87",
    "jinabiju": "0.87",
}
EXPECTED_TARGET_COVERAGE = {
    "binjurr-binjurr": 0,
    "bujarr-bujarr": 0,
    "dakwul-dakwul": 0,
    "dibirr-dibirr": 0,
    "julurr-julurr": 0,
    "muya": 0,
    "juril-juril": 2,
    "dawa-dawa": 3,
    "bulnja": 4,
    "jinabiju": 4,
}
FRAME_SPECS = [
    ("ngayu", "yinyay", "I saw", "there", "1sg"),
    ("yundu", "yaluy", "You saw", "here", "2sg"),
    ("nyulu", "yinyay", "He saw", "there", "3sg"),
    ("bula", "yaluy", "The two of them saw", "here", "3du"),
    ("jana", "yinyay", "They saw", "there", "3pl"),
]

DENY_KUKU = {
    "nganya", "yununy", "nyunguny", "yununiny", "nyunguniny", "ngaykunku", "yununku", "nyungunku",
    "ngaykundu", "yunundu", "nyungundu", "ngaykundumuny", "yunundumuny", "nyungundumuny",
    "ngaykunji", "yununji", "nyungunji", "ngayku", "yunu", "nyunju", "yulu", "iana",
    "ngali", "ngaliny", "yubal", "yurra", "ngana", "nganjin",
    "bidubidu", "binjurrbinjurr", "dibirrdibirr", "jukujuku", "dakwurr-dakwun", "walu-dalbaji",
    "yalay", "yala", "yanyu", "yinya", "yalungku", "yaluyngku", "yinyangka", "yinyayngka",
    "yalamuny", "yinyamuny", "nyajil", "nyaji-l", "nyaji-nka", "nyaji-l-nyaji", "milka", "baykal", "jalngkay",
}
DENY_ENGLISH = (
    "black", "brown", "white", "colour", "color", "male", "head", "eye", "strip", "clear", "circle",
    "sing", "song", "dance", "display", "totem", "moiety", "call", "appearance", "iconic", "onomatopoeia",
    "owl", "night", "hawk", "stranger", "death", "died", "omen", "warning", "morning", "thompson", "creek",
    "place", "story", "flock", "fly", "flight", "nest", "egg", "feather", "food", "eat", "feeding", "hunt",
    "catch", "storm", "spirit", "sacred", "habitat", "behavior", "honey", "robin", "species", "eject", "run",
    "crab", "tide", "mopoke", "branch", "camouflage", "mouth", "trap", "beetle", "insect", "chicken", "chick",
    "snatch", "wind", "stone", "prey", "silence", "body", "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, "I saw the binjurr-binjurr honeyeater there.", "Ngayu binjurr-binjurr yinyay nyajin.", "ngayu binjurr-binjurr yinyay nyajin | 1sg.NOM binjurr.binjurr.honeyeater there see.PST", "r321_1sg_there_zero_low_bird_saw_binjurr_binjurr", ["ngayu", "binjurr-binjurr", "yinyay", "nyajin"]),
    row(2, "I saw the bujarr-bujarr bird there.", "Ngayu bujarr-bujarr yinyay nyajin.", "ngayu bujarr-bujarr yinyay nyajin | 1sg.NOM bujarr.bujarr.bird there see.PST", "r321_1sg_there_zero_low_bird_saw_bujarr_bujarr", ["ngayu", "bujarr-bujarr", "yinyay", "nyajin"]),
    row(3, "I saw the dakwul-dakwul scrub bird there.", "Ngayu dakwul-dakwul yinyay nyajin.", "ngayu dakwul-dakwul yinyay nyajin | 1sg.NOM dakwul.dakwul.scrub.bird there see.PST", "r321_1sg_there_zero_low_bird_saw_dakwul_dakwul", ["ngayu", "dakwul-dakwul", "yinyay", "nyajin"]),
    row(4, "I saw the dibirr-dibirr rainbow bird there.", "Ngayu dibirr-dibirr yinyay nyajin.", "ngayu dibirr-dibirr yinyay nyajin | 1sg.NOM dibirr.dibirr.rainbow.bird there see.PST", "r321_1sg_there_zero_low_bird_saw_dibirr_dibirr", ["ngayu", "dibirr-dibirr", "yinyay", "nyajin"]),
    row(5, "I saw the julurr-julurr moomoo bird there.", "Ngayu julurr-julurr yinyay nyajin.", "ngayu julurr-julurr yinyay nyajin | 1sg.NOM julurr.julurr.moomoo.bird there see.PST", "r321_1sg_there_zero_low_bird_saw_julurr_julurr", ["ngayu", "julurr-julurr", "yinyay", "nyajin"]),
    row(6, "I saw the muya bird there.", "Ngayu muya yinyay nyajin.", "ngayu muya yinyay nyajin | 1sg.NOM muya.bird there see.PST", "r321_1sg_there_zero_low_bird_saw_muya", ["ngayu", "muya", "yinyay", "nyajin"]),
    row(7, "I saw the juril-juril seashore plover there.", "Ngayu juril-juril yinyay nyajin.", "ngayu juril-juril yinyay nyajin | 1sg.NOM juril.juril.seashore.plover there see.PST", "r321_1sg_there_zero_low_bird_saw_juril_juril", ["ngayu", "juril-juril", "yinyay", "nyajin"]),
    row(8, "I saw the dawa-dawa magpie there.", "Ngayu dawa-dawa yinyay nyajin.", "ngayu dawa-dawa yinyay nyajin | 1sg.NOM dawa.dawa.magpie there see.PST", "r321_1sg_there_zero_low_bird_saw_dawa_dawa", ["ngayu", "dawa-dawa", "yinyay", "nyajin"]),
    row(9, "I saw the bulnja frogmouth there.", "Ngayu bulnja yinyay nyajin.", "ngayu bulnja yinyay nyajin | 1sg.NOM bulnja.frogmouth there see.PST", "r321_1sg_there_zero_low_bird_saw_bulnja", ["ngayu", "bulnja", "yinyay", "nyajin"]),
    row(10, "I saw the jinabiju goshawk there.", "Ngayu jinabiju yinyay nyajin.", "ngayu jinabiju yinyay nyajin | 1sg.NOM jinabiju.goshawk there see.PST", "r321_1sg_there_zero_low_bird_saw_jinabiju", ["ngayu", "jinabiju", "yinyay", "nyajin"]),
    row(11, "You saw the binjurr-binjurr honeyeater here.", "Yundu binjurr-binjurr yaluy nyajin.", "yundu binjurr-binjurr yaluy nyajin | 2sg.NOM binjurr.binjurr.honeyeater here see.PST", "r321_2sg_here_zero_low_bird_saw_binjurr_binjurr", ["yundu", "binjurr-binjurr", "yaluy", "nyajin"]),
    row(12, "You saw the bujarr-bujarr bird here.", "Yundu bujarr-bujarr yaluy nyajin.", "yundu bujarr-bujarr yaluy nyajin | 2sg.NOM bujarr.bujarr.bird here see.PST", "r321_2sg_here_zero_low_bird_saw_bujarr_bujarr", ["yundu", "bujarr-bujarr", "yaluy", "nyajin"]),
    row(13, "You saw the dakwul-dakwul scrub bird here.", "Yundu dakwul-dakwul yaluy nyajin.", "yundu dakwul-dakwul yaluy nyajin | 2sg.NOM dakwul.dakwul.scrub.bird here see.PST", "r321_2sg_here_zero_low_bird_saw_dakwul_dakwul", ["yundu", "dakwul-dakwul", "yaluy", "nyajin"]),
    row(14, "You saw the dibirr-dibirr rainbow bird here.", "Yundu dibirr-dibirr yaluy nyajin.", "yundu dibirr-dibirr yaluy nyajin | 2sg.NOM dibirr.dibirr.rainbow.bird here see.PST", "r321_2sg_here_zero_low_bird_saw_dibirr_dibirr", ["yundu", "dibirr-dibirr", "yaluy", "nyajin"]),
    row(15, "You saw the julurr-julurr moomoo bird here.", "Yundu julurr-julurr yaluy nyajin.", "yundu julurr-julurr yaluy nyajin | 2sg.NOM julurr.julurr.moomoo.bird here see.PST", "r321_2sg_here_zero_low_bird_saw_julurr_julurr", ["yundu", "julurr-julurr", "yaluy", "nyajin"]),
    row(16, "You saw the muya bird here.", "Yundu muya yaluy nyajin.", "yundu muya yaluy nyajin | 2sg.NOM muya.bird here see.PST", "r321_2sg_here_zero_low_bird_saw_muya", ["yundu", "muya", "yaluy", "nyajin"]),
    row(17, "You saw the juril-juril seashore plover here.", "Yundu juril-juril yaluy nyajin.", "yundu juril-juril yaluy nyajin | 2sg.NOM juril.juril.seashore.plover here see.PST", "r321_2sg_here_zero_low_bird_saw_juril_juril", ["yundu", "juril-juril", "yaluy", "nyajin"]),
    row(18, "You saw the dawa-dawa magpie here.", "Yundu dawa-dawa yaluy nyajin.", "yundu dawa-dawa yaluy nyajin | 2sg.NOM dawa.dawa.magpie here see.PST", "r321_2sg_here_zero_low_bird_saw_dawa_dawa", ["yundu", "dawa-dawa", "yaluy", "nyajin"]),
    row(19, "You saw the bulnja frogmouth here.", "Yundu bulnja yaluy nyajin.", "yundu bulnja yaluy nyajin | 2sg.NOM bulnja.frogmouth here see.PST", "r321_2sg_here_zero_low_bird_saw_bulnja", ["yundu", "bulnja", "yaluy", "nyajin"]),
    row(20, "You saw the jinabiju goshawk here.", "Yundu jinabiju yaluy nyajin.", "yundu jinabiju yaluy nyajin | 2sg.NOM jinabiju.goshawk here see.PST", "r321_2sg_here_zero_low_bird_saw_jinabiju", ["yundu", "jinabiju", "yaluy", "nyajin"]),
    row(21, "He saw the binjurr-binjurr honeyeater there.", "Nyulu binjurr-binjurr yinyay nyajin.", "nyulu binjurr-binjurr yinyay nyajin | 3sg.NOM binjurr.binjurr.honeyeater there see.PST", "r321_3sg_there_zero_low_bird_saw_binjurr_binjurr", ["nyulu", "binjurr-binjurr", "yinyay", "nyajin"]),
    row(22, "He saw the bujarr-bujarr bird there.", "Nyulu bujarr-bujarr yinyay nyajin.", "nyulu bujarr-bujarr yinyay nyajin | 3sg.NOM bujarr.bujarr.bird there see.PST", "r321_3sg_there_zero_low_bird_saw_bujarr_bujarr", ["nyulu", "bujarr-bujarr", "yinyay", "nyajin"]),
    row(23, "He saw the dakwul-dakwul scrub bird there.", "Nyulu dakwul-dakwul yinyay nyajin.", "nyulu dakwul-dakwul yinyay nyajin | 3sg.NOM dakwul.dakwul.scrub.bird there see.PST", "r321_3sg_there_zero_low_bird_saw_dakwul_dakwul", ["nyulu", "dakwul-dakwul", "yinyay", "nyajin"]),
    row(24, "He saw the dibirr-dibirr rainbow bird there.", "Nyulu dibirr-dibirr yinyay nyajin.", "nyulu dibirr-dibirr yinyay nyajin | 3sg.NOM dibirr.dibirr.rainbow.bird there see.PST", "r321_3sg_there_zero_low_bird_saw_dibirr_dibirr", ["nyulu", "dibirr-dibirr", "yinyay", "nyajin"]),
    row(25, "He saw the julurr-julurr moomoo bird there.", "Nyulu julurr-julurr yinyay nyajin.", "nyulu julurr-julurr yinyay nyajin | 3sg.NOM julurr.julurr.moomoo.bird there see.PST", "r321_3sg_there_zero_low_bird_saw_julurr_julurr", ["nyulu", "julurr-julurr", "yinyay", "nyajin"]),
    row(26, "He saw the muya bird there.", "Nyulu muya yinyay nyajin.", "nyulu muya yinyay nyajin | 3sg.NOM muya.bird there see.PST", "r321_3sg_there_zero_low_bird_saw_muya", ["nyulu", "muya", "yinyay", "nyajin"]),
    row(27, "He saw the juril-juril seashore plover there.", "Nyulu juril-juril yinyay nyajin.", "nyulu juril-juril yinyay nyajin | 3sg.NOM juril.juril.seashore.plover there see.PST", "r321_3sg_there_zero_low_bird_saw_juril_juril", ["nyulu", "juril-juril", "yinyay", "nyajin"]),
    row(28, "He saw the dawa-dawa magpie there.", "Nyulu dawa-dawa yinyay nyajin.", "nyulu dawa-dawa yinyay nyajin | 3sg.NOM dawa.dawa.magpie there see.PST", "r321_3sg_there_zero_low_bird_saw_dawa_dawa", ["nyulu", "dawa-dawa", "yinyay", "nyajin"]),
    row(29, "He saw the bulnja frogmouth there.", "Nyulu bulnja yinyay nyajin.", "nyulu bulnja yinyay nyajin | 3sg.NOM bulnja.frogmouth there see.PST", "r321_3sg_there_zero_low_bird_saw_bulnja", ["nyulu", "bulnja", "yinyay", "nyajin"]),
    row(30, "He saw the jinabiju goshawk there.", "Nyulu jinabiju yinyay nyajin.", "nyulu jinabiju yinyay nyajin | 3sg.NOM jinabiju.goshawk there see.PST", "r321_3sg_there_zero_low_bird_saw_jinabiju", ["nyulu", "jinabiju", "yinyay", "nyajin"]),
    row(31, "The two of them saw the binjurr-binjurr honeyeater here.", "Bula binjurr-binjurr yaluy nyajin.", "bula binjurr-binjurr yaluy nyajin | 3du.NOM binjurr.binjurr.honeyeater here see.PST", "r321_3du_here_zero_low_bird_saw_binjurr_binjurr", ["bula", "binjurr-binjurr", "yaluy", "nyajin"]),
    row(32, "The two of them saw the bujarr-bujarr bird here.", "Bula bujarr-bujarr yaluy nyajin.", "bula bujarr-bujarr yaluy nyajin | 3du.NOM bujarr.bujarr.bird here see.PST", "r321_3du_here_zero_low_bird_saw_bujarr_bujarr", ["bula", "bujarr-bujarr", "yaluy", "nyajin"]),
    row(33, "The two of them saw the dakwul-dakwul scrub bird here.", "Bula dakwul-dakwul yaluy nyajin.", "bula dakwul-dakwul yaluy nyajin | 3du.NOM dakwul.dakwul.scrub.bird here see.PST", "r321_3du_here_zero_low_bird_saw_dakwul_dakwul", ["bula", "dakwul-dakwul", "yaluy", "nyajin"]),
    row(34, "The two of them saw the dibirr-dibirr rainbow bird here.", "Bula dibirr-dibirr yaluy nyajin.", "bula dibirr-dibirr yaluy nyajin | 3du.NOM dibirr.dibirr.rainbow.bird here see.PST", "r321_3du_here_zero_low_bird_saw_dibirr_dibirr", ["bula", "dibirr-dibirr", "yaluy", "nyajin"]),
    row(35, "The two of them saw the julurr-julurr moomoo bird here.", "Bula julurr-julurr yaluy nyajin.", "bula julurr-julurr yaluy nyajin | 3du.NOM julurr.julurr.moomoo.bird here see.PST", "r321_3du_here_zero_low_bird_saw_julurr_julurr", ["bula", "julurr-julurr", "yaluy", "nyajin"]),
    row(36, "The two of them saw the muya bird here.", "Bula muya yaluy nyajin.", "bula muya yaluy nyajin | 3du.NOM muya.bird here see.PST", "r321_3du_here_zero_low_bird_saw_muya", ["bula", "muya", "yaluy", "nyajin"]),
    row(37, "The two of them saw the juril-juril seashore plover here.", "Bula juril-juril yaluy nyajin.", "bula juril-juril yaluy nyajin | 3du.NOM juril.juril.seashore.plover here see.PST", "r321_3du_here_zero_low_bird_saw_juril_juril", ["bula", "juril-juril", "yaluy", "nyajin"]),
    row(38, "The two of them saw the dawa-dawa magpie here.", "Bula dawa-dawa yaluy nyajin.", "bula dawa-dawa yaluy nyajin | 3du.NOM dawa.dawa.magpie here see.PST", "r321_3du_here_zero_low_bird_saw_dawa_dawa", ["bula", "dawa-dawa", "yaluy", "nyajin"]),
    row(39, "The two of them saw the bulnja frogmouth here.", "Bula bulnja yaluy nyajin.", "bula bulnja yaluy nyajin | 3du.NOM bulnja.frogmouth here see.PST", "r321_3du_here_zero_low_bird_saw_bulnja", ["bula", "bulnja", "yaluy", "nyajin"]),
    row(40, "The two of them saw the jinabiju goshawk here.", "Bula jinabiju yaluy nyajin.", "bula jinabiju yaluy nyajin | 3du.NOM jinabiju.goshawk here see.PST", "r321_3du_here_zero_low_bird_saw_jinabiju", ["bula", "jinabiju", "yaluy", "nyajin"]),
    row(41, "They saw the binjurr-binjurr honeyeater there.", "Jana binjurr-binjurr yinyay nyajin.", "jana binjurr-binjurr yinyay nyajin | 3pl.NOM binjurr.binjurr.honeyeater there see.PST", "r321_3pl_there_zero_low_bird_saw_binjurr_binjurr", ["jana", "binjurr-binjurr", "yinyay", "nyajin"]),
    row(42, "They saw the bujarr-bujarr bird there.", "Jana bujarr-bujarr yinyay nyajin.", "jana bujarr-bujarr yinyay nyajin | 3pl.NOM bujarr.bujarr.bird there see.PST", "r321_3pl_there_zero_low_bird_saw_bujarr_bujarr", ["jana", "bujarr-bujarr", "yinyay", "nyajin"]),
    row(43, "They saw the dakwul-dakwul scrub bird there.", "Jana dakwul-dakwul yinyay nyajin.", "jana dakwul-dakwul yinyay nyajin | 3pl.NOM dakwul.dakwul.scrub.bird there see.PST", "r321_3pl_there_zero_low_bird_saw_dakwul_dakwul", ["jana", "dakwul-dakwul", "yinyay", "nyajin"]),
    row(44, "They saw the dibirr-dibirr rainbow bird there.", "Jana dibirr-dibirr yinyay nyajin.", "jana dibirr-dibirr yinyay nyajin | 3pl.NOM dibirr.dibirr.rainbow.bird there see.PST", "r321_3pl_there_zero_low_bird_saw_dibirr_dibirr", ["jana", "dibirr-dibirr", "yinyay", "nyajin"]),
    row(45, "They saw the julurr-julurr moomoo bird there.", "Jana julurr-julurr yinyay nyajin.", "jana julurr-julurr yinyay nyajin | 3pl.NOM julurr.julurr.moomoo.bird there see.PST", "r321_3pl_there_zero_low_bird_saw_julurr_julurr", ["jana", "julurr-julurr", "yinyay", "nyajin"]),
    row(46, "They saw the muya bird there.", "Jana muya yinyay nyajin.", "jana muya yinyay nyajin | 3pl.NOM muya.bird there see.PST", "r321_3pl_there_zero_low_bird_saw_muya", ["jana", "muya", "yinyay", "nyajin"]),
    row(47, "They saw the juril-juril seashore plover there.", "Jana juril-juril yinyay nyajin.", "jana juril-juril yinyay nyajin | 3pl.NOM juril.juril.seashore.plover there see.PST", "r321_3pl_there_zero_low_bird_saw_juril_juril", ["jana", "juril-juril", "yinyay", "nyajin"]),
    row(48, "They saw the dawa-dawa magpie there.", "Jana dawa-dawa yinyay nyajin.", "jana dawa-dawa yinyay nyajin | 3pl.NOM dawa.dawa.magpie there see.PST", "r321_3pl_there_zero_low_bird_saw_dawa_dawa", ["jana", "dawa-dawa", "yinyay", "nyajin"]),
    row(49, "They saw the bulnja frogmouth there.", "Jana bulnja yinyay nyajin.", "jana bulnja yinyay nyajin | 3pl.NOM bulnja.frogmouth there see.PST", "r321_3pl_there_zero_low_bird_saw_bulnja", ["jana", "bulnja", "yinyay", "nyajin"]),
    row(50, "They saw the jinabiju goshawk there.", "Jana jinabiju yinyay nyajin.", "jana jinabiju yinyay nyajin | 3pl.NOM jinabiju.goshawk there see.PST", "r321_3pl_there_zero_low_bird_saw_jinabiju", ["jana", "jinabiju", "yinyay", "nyajin"]),
]


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} nyajin."
        expected_english = f"{prefix} the {TARGET_LABELS[target]} {location}."
        expected_analysis = f"{pronoun} {target} {demo} nyajin | {person_gloss}.NOM {TARGET_GLOSSES[target]} {location} see.PST"
        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, "nyajin"]:
            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("r321_"):
            issues.append(f"{seq}: frame not r321 {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, ["ngayu", "yundu", "nyulu", "bula", "jana", "yaluy", "yinyay", "nyajin"])
    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/LOW-USE BIRD SINGULAR/THIRD-PERSON PAST PERCEPTION SWEEP AFTER RULE 320 (Rule 321). 50 under-review "
        "rows over six zero-use heads (binjurr-binjurr, bujarr-bujarr, dakwul-dakwul, dibirr-dibirr, "
        "julurr-julurr, muya) and four two-to-four-use heads (juril-juril, dawa-dawa, bulnja, jinabiju). "
        "SUPPORT: bare nominative ngayu, yundu, nyulu, bula, jana, Yalanji yaluy/yinyay, and dictionary-attested "
        "past nyajin. Exact dictionary head orthography is preserved; solid variants, productive reduplication, "
        "species overresolution, color/anatomy, song/call/display, omen/totem/story/place, habitat/ecology, food/"
        "hunting, case, nonpast/purposive/reduplicated perception, support inflection, and carried traps remain closed."
    )
    cur = db.execute(
        "INSERT INTO batches(label,cheatsheet_version,guide_version,notes,created_at) VALUES(?,?,?,?,?)",
        (LABEL, "Rule 321 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 bird entries; exact-searched every selected head in Patz (none occurs lexically); reread Patz nominative pronouns, Yalanji local demonstratives, past -ny, sensory-perception A/O syntax, and dictionary running-form nyajin evidence before authoring Rule 321.", 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 12 zero-use bird-domain heads. Rejected solid bidubidu, binjurrbinjurr, dibirrdibirr, and jukujuku rather than weakening the global reduplication guard; rejected dakwurr-dakwun and walu-dalbaji because totem/moiety and place/story pressure remained avoidable; selected six clean zero-use heads plus four direct low-use controls.", artifact_path=PROCESS_LOG, created_at=NOW)
    record_event(db, batch_label=LABEL, phase="planning", event_type="zero-low-bird-singular-third-past-scope", actor="codex", detail="Locked ten exact dictionary bird heads to bare visible reference in five sourced singular/third-person past-perception frames. Duplicate-entry heads use only their populated record; muya remains taxonomically unresolved; julurr-julurr remains the source-local moomoo bird; no source-prose, variant-equivalence, case, event, or support-inflection 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 321 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 bird head each, bare singular/third-person pronouns and Yalanji demonstratives, final nyajin, no loans, no denied variants, and no source-prose or prior-row drift.", command="python3 -m py_compile batch_scripts/bank_363.py batch_scripts/close_363.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_363.py", created_at=NOW)
    record_event(db, batch_label=LABEL, phase="bank", event_type="bank-success", actor="codex", detail=f"Banked 50 Rule 321 rows as under_review. Verified remains {verified_before}; Kuku words remain {words_before}.", command="python3 batch_scripts/bank_363.py", output_excerpt=f"banked batch-363: 50 under_review; verified_before={verified_before}; kuku_words_before={words_before}", artifact_path=PROCESS_LOG, created_at=NOW)
    db.commit()
    print("banked batch-363: 50 rows under_review")
    return 0


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