#!/usr/bin/env python3
"""Bank batch-362: Rule 320 zero-use flora 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-362"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
PROCESS_LOG = "process_logs/batch-362-zero-use-flora-nonsingular-nonpast-perception-after-rule319-process.md"

TARGET_EVIDENCE = {
    "bikarrakal": "Dictionary yaml lines 2369-2380 give bikarrakal a flora sense 'bikarrakal fruit' / species of tree and its fruit, alongside a grub-used-for-bait definition and cooking requirement. Rule 320 selects visible bikarrakal-fruit reference only and leaves grub, bait, tree, cooking, edibility, preparation, use, and event propositions closed.",
    "dikirr": "Dictionary yaml lines 5674-5685 give dikirr 'waterlily' / water flower and note edibility. Rule 320 selects visible dikirr-waterlily reference only and leaves edibility, food, collection, preparation, aquatic habitat, flower-part analysis, and event propositions closed.",
    "dukul-dukul": "Dictionary yaml lines 6332-6346 give full-reduplicated dukul-dukul 'broad-leafed bush' used to cover a dirt oven. Rule 320 admits the whole dictionary head as visible bush reference only and leaves productive reduplication, leaf properties, oven/kurrma, covering, cooking, material use, and event propositions closed.",
    "kakarr": "Dictionary yaml lines 12122-12136 give kakarr a primary noun sense 'grass' plus extended blanket and year/counting-unit senses. Rule 320 selects visible kakarr-grass reference only and leaves blanket, lying/use, year, counting, number, time, and event propositions closed.",
    "kalkurr": "Dictionary yaml lines 12741-12752 give kalkurr as a species of wild yam / yam and identify it as a food plant. Rule 320 selects visible kalkurr-yam reference only and leaves wildness, species taxonomy, food, edibility, tuber, gathering, preparation, and event propositions closed.",
    "marrku": "Dictionary yaml lines 18676-18687 give marrku 'native cherry' / edible wild cherry, with prose about seeds, low beach growth, and a shiny leaf. Rule 320 selects visible marrku-fruit reference only and leaves edibility, food, wild/native property, cherry comparison, seed number, beach habitat, growth, leaf, shine, and event propositions closed.",
    "milmarr": "Dictionary yaml lines 19536-19547 give milmarr 'cane' / edible lawyer cane. Rule 320 selects visible milmarr-cane reference only and leaves lawyer-cane subtype, edibility, food, gathering, weaving/material use, preparation, and event propositions closed.",
    "warrabuka": "Dictionary yaml lines 26560-26570 give warrabuka as a species of wild yam / food plant. Rule 320 selects visible warrabuka-yam reference only and leaves wildness, taxonomy, food, edibility, tuber, gathering, preparation, and event propositions closed.",
    "wubali": "Dictionary yaml lines 27436-27446 give wubali as a species of yam / edible tuber. Rule 320 selects visible wubali-yam reference only and leaves taxonomy, edibility, food, tuber, gathering, preparation, and event propositions closed.",
    "wulku": "Dictionary yaml lines 27854-27862 give wulku directly as noun 'fig'. Rule 320 selects visible wulku-fig reference only and adds no fruit-part, tree, edibility, food, colour, ripeness, collection, preparation, or event proposition.",
}

SUPPORT_EVIDENCE = (
    "Patz pronoun table lines 2577-2582 sources bare nominatives ngali, ngaliny, yubal, yurra, and ngana; "
    "lines 2674-2684 support their dual/plural, inclusive/exclusive, and person values. Demonstrative lines "
    "2834-2847 source Yalanji yaluy 'here' and yinyay 'there'. Lines 3043-3049 give nyaji-l as nonpast 'see', "
    "lines 3149-3151 define nonpast present/future 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 as a general l-conjugation perception verb including visual 'see'. Rule 320 uses bare support and the "
    "visual, present/nonpast reading only."
)

TARGET_ORDER = [
    "bikarrakal", "dikirr", "dukul-dukul", "kakarr", "kalkurr",
    "marrku", "milmarr", "warrabuka", "wubali", "wulku",
]
TARGET_LABELS = {
    "bikarrakal": "bikarrakal fruit",
    "dikirr": "dikirr waterlily",
    "dukul-dukul": "dukul-dukul bush",
    "kakarr": "kakarr grass",
    "kalkurr": "kalkurr yam",
    "marrku": "marrku fruit",
    "milmarr": "milmarr cane",
    "warrabuka": "warrabuka yam",
    "wubali": "wubali yam",
    "wulku": "wulku fig",
}
FRAME_SPECS = [
    ("ngali", "yaluy", "We two, not you, see", "here"),
    ("ngaliny", "yinyay", "You and I see", "there"),
    ("yubal", "yaluy", "You two see", "here"),
    ("yurra", "yinyay", "You all see", "there"),
    ("ngana", "yaluy", "We see", "here"),
]

DENY_KUKU = {
    "ngayu", "yundu", "nyulu", "yulu", "bula", "jana", "nganjin", "iana",
    "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",
    "bikarrakul", "kurrma", "dukul", "kararr", "jambul", "yalay",
    "yalungku", "yaluyngku", "yinyangka", "yinyayngka", "yalamuny", "yinyamuny",
    "nyajin", "nyajiny", "nyaji-ny", "nyaji-nka", "nyaji-l-nyaji", "milka", "baykal", "jalngkay",
}
DENY_ENGLISH = (
    "grub", "bait", "tree", "cook", "cooked", "cooking", "edible", "edibility", "food", "collect",
    "collection", "gather", "gathering", "prepare", "preparation", "water", "flower", "aquatic", "broad",
    "leaf", "leafed", "leaves", "cover", "covering", "dirt", "oven", "kurrma", "material", "use", "used",
    "blanket", "lie", "lying", "year", "count", "counting", "number", "time", "wild", "native", "cherry",
    "species", "taxonomy", "tuber", "seed", "seeds", "beach", "growth", "grow", "grows", "shiny", "shine",
    "lawyer", "weave", "weaving", "part", "colour", "color", "ripe", "ripeness", "habitat", "behavior",
    "event",
)


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}", "0.86",
    )


ROWS = [
    row(1, "We two, not you, see the bikarrakal fruit here.", "Ngali bikarrakal yaluy nyajil.", "ngali bikarrakal yaluy nyajil | 1du.excl.NOM bikarrakal.fruit here see.NPST", "r320_1du_excl_here_zero_flora_see_bikarrakal", ["ngali", "bikarrakal", "yaluy", "nyajil"]),
    row(2, "We two, not you, see the dikirr waterlily here.", "Ngali dikirr yaluy nyajil.", "ngali dikirr yaluy nyajil | 1du.excl.NOM dikirr.waterlily here see.NPST", "r320_1du_excl_here_zero_flora_see_dikirr", ["ngali", "dikirr", "yaluy", "nyajil"]),
    row(3, "We two, not you, see the dukul-dukul bush here.", "Ngali dukul-dukul yaluy nyajil.", "ngali dukul-dukul yaluy nyajil | 1du.excl.NOM dukul-dukul.bush here see.NPST", "r320_1du_excl_here_zero_flora_see_dukul_dukul", ["ngali", "dukul-dukul", "yaluy", "nyajil"]),
    row(4, "We two, not you, see the kakarr grass here.", "Ngali kakarr yaluy nyajil.", "ngali kakarr yaluy nyajil | 1du.excl.NOM kakarr.grass here see.NPST", "r320_1du_excl_here_zero_flora_see_kakarr", ["ngali", "kakarr", "yaluy", "nyajil"]),
    row(5, "We two, not you, see the kalkurr yam here.", "Ngali kalkurr yaluy nyajil.", "ngali kalkurr yaluy nyajil | 1du.excl.NOM kalkurr.yam here see.NPST", "r320_1du_excl_here_zero_flora_see_kalkurr", ["ngali", "kalkurr", "yaluy", "nyajil"]),
    row(6, "We two, not you, see the marrku fruit here.", "Ngali marrku yaluy nyajil.", "ngali marrku yaluy nyajil | 1du.excl.NOM marrku.fruit here see.NPST", "r320_1du_excl_here_zero_flora_see_marrku", ["ngali", "marrku", "yaluy", "nyajil"]),
    row(7, "We two, not you, see the milmarr cane here.", "Ngali milmarr yaluy nyajil.", "ngali milmarr yaluy nyajil | 1du.excl.NOM milmarr.cane here see.NPST", "r320_1du_excl_here_zero_flora_see_milmarr", ["ngali", "milmarr", "yaluy", "nyajil"]),
    row(8, "We two, not you, see the warrabuka yam here.", "Ngali warrabuka yaluy nyajil.", "ngali warrabuka yaluy nyajil | 1du.excl.NOM warrabuka.yam here see.NPST", "r320_1du_excl_here_zero_flora_see_warrabuka", ["ngali", "warrabuka", "yaluy", "nyajil"]),
    row(9, "We two, not you, see the wubali yam here.", "Ngali wubali yaluy nyajil.", "ngali wubali yaluy nyajil | 1du.excl.NOM wubali.yam here see.NPST", "r320_1du_excl_here_zero_flora_see_wubali", ["ngali", "wubali", "yaluy", "nyajil"]),
    row(10, "We two, not you, see the wulku fig here.", "Ngali wulku yaluy nyajil.", "ngali wulku yaluy nyajil | 1du.excl.NOM wulku.fig here see.NPST", "r320_1du_excl_here_zero_flora_see_wulku", ["ngali", "wulku", "yaluy", "nyajil"]),
    row(11, "You and I see the bikarrakal fruit there.", "Ngaliny bikarrakal yinyay nyajil.", "ngaliny bikarrakal yinyay nyajil | 1du.incl.NOM bikarrakal.fruit there see.NPST", "r320_1du_incl_there_zero_flora_see_bikarrakal", ["ngaliny", "bikarrakal", "yinyay", "nyajil"]),
    row(12, "You and I see the dikirr waterlily there.", "Ngaliny dikirr yinyay nyajil.", "ngaliny dikirr yinyay nyajil | 1du.incl.NOM dikirr.waterlily there see.NPST", "r320_1du_incl_there_zero_flora_see_dikirr", ["ngaliny", "dikirr", "yinyay", "nyajil"]),
    row(13, "You and I see the dukul-dukul bush there.", "Ngaliny dukul-dukul yinyay nyajil.", "ngaliny dukul-dukul yinyay nyajil | 1du.incl.NOM dukul-dukul.bush there see.NPST", "r320_1du_incl_there_zero_flora_see_dukul_dukul", ["ngaliny", "dukul-dukul", "yinyay", "nyajil"]),
    row(14, "You and I see the kakarr grass there.", "Ngaliny kakarr yinyay nyajil.", "ngaliny kakarr yinyay nyajil | 1du.incl.NOM kakarr.grass there see.NPST", "r320_1du_incl_there_zero_flora_see_kakarr", ["ngaliny", "kakarr", "yinyay", "nyajil"]),
    row(15, "You and I see the kalkurr yam there.", "Ngaliny kalkurr yinyay nyajil.", "ngaliny kalkurr yinyay nyajil | 1du.incl.NOM kalkurr.yam there see.NPST", "r320_1du_incl_there_zero_flora_see_kalkurr", ["ngaliny", "kalkurr", "yinyay", "nyajil"]),
    row(16, "You and I see the marrku fruit there.", "Ngaliny marrku yinyay nyajil.", "ngaliny marrku yinyay nyajil | 1du.incl.NOM marrku.fruit there see.NPST", "r320_1du_incl_there_zero_flora_see_marrku", ["ngaliny", "marrku", "yinyay", "nyajil"]),
    row(17, "You and I see the milmarr cane there.", "Ngaliny milmarr yinyay nyajil.", "ngaliny milmarr yinyay nyajil | 1du.incl.NOM milmarr.cane there see.NPST", "r320_1du_incl_there_zero_flora_see_milmarr", ["ngaliny", "milmarr", "yinyay", "nyajil"]),
    row(18, "You and I see the warrabuka yam there.", "Ngaliny warrabuka yinyay nyajil.", "ngaliny warrabuka yinyay nyajil | 1du.incl.NOM warrabuka.yam there see.NPST", "r320_1du_incl_there_zero_flora_see_warrabuka", ["ngaliny", "warrabuka", "yinyay", "nyajil"]),
    row(19, "You and I see the wubali yam there.", "Ngaliny wubali yinyay nyajil.", "ngaliny wubali yinyay nyajil | 1du.incl.NOM wubali.yam there see.NPST", "r320_1du_incl_there_zero_flora_see_wubali", ["ngaliny", "wubali", "yinyay", "nyajil"]),
    row(20, "You and I see the wulku fig there.", "Ngaliny wulku yinyay nyajil.", "ngaliny wulku yinyay nyajil | 1du.incl.NOM wulku.fig there see.NPST", "r320_1du_incl_there_zero_flora_see_wulku", ["ngaliny", "wulku", "yinyay", "nyajil"]),
    row(21, "You two see the bikarrakal fruit here.", "Yubal bikarrakal yaluy nyajil.", "yubal bikarrakal yaluy nyajil | 2du.NOM bikarrakal.fruit here see.NPST", "r320_2du_here_zero_flora_see_bikarrakal", ["yubal", "bikarrakal", "yaluy", "nyajil"]),
    row(22, "You two see the dikirr waterlily here.", "Yubal dikirr yaluy nyajil.", "yubal dikirr yaluy nyajil | 2du.NOM dikirr.waterlily here see.NPST", "r320_2du_here_zero_flora_see_dikirr", ["yubal", "dikirr", "yaluy", "nyajil"]),
    row(23, "You two see the dukul-dukul bush here.", "Yubal dukul-dukul yaluy nyajil.", "yubal dukul-dukul yaluy nyajil | 2du.NOM dukul-dukul.bush here see.NPST", "r320_2du_here_zero_flora_see_dukul_dukul", ["yubal", "dukul-dukul", "yaluy", "nyajil"]),
    row(24, "You two see the kakarr grass here.", "Yubal kakarr yaluy nyajil.", "yubal kakarr yaluy nyajil | 2du.NOM kakarr.grass here see.NPST", "r320_2du_here_zero_flora_see_kakarr", ["yubal", "kakarr", "yaluy", "nyajil"]),
    row(25, "You two see the kalkurr yam here.", "Yubal kalkurr yaluy nyajil.", "yubal kalkurr yaluy nyajil | 2du.NOM kalkurr.yam here see.NPST", "r320_2du_here_zero_flora_see_kalkurr", ["yubal", "kalkurr", "yaluy", "nyajil"]),
    row(26, "You two see the marrku fruit here.", "Yubal marrku yaluy nyajil.", "yubal marrku yaluy nyajil | 2du.NOM marrku.fruit here see.NPST", "r320_2du_here_zero_flora_see_marrku", ["yubal", "marrku", "yaluy", "nyajil"]),
    row(27, "You two see the milmarr cane here.", "Yubal milmarr yaluy nyajil.", "yubal milmarr yaluy nyajil | 2du.NOM milmarr.cane here see.NPST", "r320_2du_here_zero_flora_see_milmarr", ["yubal", "milmarr", "yaluy", "nyajil"]),
    row(28, "You two see the warrabuka yam here.", "Yubal warrabuka yaluy nyajil.", "yubal warrabuka yaluy nyajil | 2du.NOM warrabuka.yam here see.NPST", "r320_2du_here_zero_flora_see_warrabuka", ["yubal", "warrabuka", "yaluy", "nyajil"]),
    row(29, "You two see the wubali yam here.", "Yubal wubali yaluy nyajil.", "yubal wubali yaluy nyajil | 2du.NOM wubali.yam here see.NPST", "r320_2du_here_zero_flora_see_wubali", ["yubal", "wubali", "yaluy", "nyajil"]),
    row(30, "You two see the wulku fig here.", "Yubal wulku yaluy nyajil.", "yubal wulku yaluy nyajil | 2du.NOM wulku.fig here see.NPST", "r320_2du_here_zero_flora_see_wulku", ["yubal", "wulku", "yaluy", "nyajil"]),
    row(31, "You all see the bikarrakal fruit there.", "Yurra bikarrakal yinyay nyajil.", "yurra bikarrakal yinyay nyajil | 2pl.NOM bikarrakal.fruit there see.NPST", "r320_2pl_there_zero_flora_see_bikarrakal", ["yurra", "bikarrakal", "yinyay", "nyajil"]),
    row(32, "You all see the dikirr waterlily there.", "Yurra dikirr yinyay nyajil.", "yurra dikirr yinyay nyajil | 2pl.NOM dikirr.waterlily there see.NPST", "r320_2pl_there_zero_flora_see_dikirr", ["yurra", "dikirr", "yinyay", "nyajil"]),
    row(33, "You all see the dukul-dukul bush there.", "Yurra dukul-dukul yinyay nyajil.", "yurra dukul-dukul yinyay nyajil | 2pl.NOM dukul-dukul.bush there see.NPST", "r320_2pl_there_zero_flora_see_dukul_dukul", ["yurra", "dukul-dukul", "yinyay", "nyajil"]),
    row(34, "You all see the kakarr grass there.", "Yurra kakarr yinyay nyajil.", "yurra kakarr yinyay nyajil | 2pl.NOM kakarr.grass there see.NPST", "r320_2pl_there_zero_flora_see_kakarr", ["yurra", "kakarr", "yinyay", "nyajil"]),
    row(35, "You all see the kalkurr yam there.", "Yurra kalkurr yinyay nyajil.", "yurra kalkurr yinyay nyajil | 2pl.NOM kalkurr.yam there see.NPST", "r320_2pl_there_zero_flora_see_kalkurr", ["yurra", "kalkurr", "yinyay", "nyajil"]),
    row(36, "You all see the marrku fruit there.", "Yurra marrku yinyay nyajil.", "yurra marrku yinyay nyajil | 2pl.NOM marrku.fruit there see.NPST", "r320_2pl_there_zero_flora_see_marrku", ["yurra", "marrku", "yinyay", "nyajil"]),
    row(37, "You all see the milmarr cane there.", "Yurra milmarr yinyay nyajil.", "yurra milmarr yinyay nyajil | 2pl.NOM milmarr.cane there see.NPST", "r320_2pl_there_zero_flora_see_milmarr", ["yurra", "milmarr", "yinyay", "nyajil"]),
    row(38, "You all see the warrabuka yam there.", "Yurra warrabuka yinyay nyajil.", "yurra warrabuka yinyay nyajil | 2pl.NOM warrabuka.yam there see.NPST", "r320_2pl_there_zero_flora_see_warrabuka", ["yurra", "warrabuka", "yinyay", "nyajil"]),
    row(39, "You all see the wubali yam there.", "Yurra wubali yinyay nyajil.", "yurra wubali yinyay nyajil | 2pl.NOM wubali.yam there see.NPST", "r320_2pl_there_zero_flora_see_wubali", ["yurra", "wubali", "yinyay", "nyajil"]),
    row(40, "You all see the wulku fig there.", "Yurra wulku yinyay nyajil.", "yurra wulku yinyay nyajil | 2pl.NOM wulku.fig there see.NPST", "r320_2pl_there_zero_flora_see_wulku", ["yurra", "wulku", "yinyay", "nyajil"]),
    row(41, "We see the bikarrakal fruit here.", "Ngana bikarrakal yaluy nyajil.", "ngana bikarrakal yaluy nyajil | 1pl.incl.NOM bikarrakal.fruit here see.NPST", "r320_1pl_incl_here_zero_flora_see_bikarrakal", ["ngana", "bikarrakal", "yaluy", "nyajil"]),
    row(42, "We see the dikirr waterlily here.", "Ngana dikirr yaluy nyajil.", "ngana dikirr yaluy nyajil | 1pl.incl.NOM dikirr.waterlily here see.NPST", "r320_1pl_incl_here_zero_flora_see_dikirr", ["ngana", "dikirr", "yaluy", "nyajil"]),
    row(43, "We see the dukul-dukul bush here.", "Ngana dukul-dukul yaluy nyajil.", "ngana dukul-dukul yaluy nyajil | 1pl.incl.NOM dukul-dukul.bush here see.NPST", "r320_1pl_incl_here_zero_flora_see_dukul_dukul", ["ngana", "dukul-dukul", "yaluy", "nyajil"]),
    row(44, "We see the kakarr grass here.", "Ngana kakarr yaluy nyajil.", "ngana kakarr yaluy nyajil | 1pl.incl.NOM kakarr.grass here see.NPST", "r320_1pl_incl_here_zero_flora_see_kakarr", ["ngana", "kakarr", "yaluy", "nyajil"]),
    row(45, "We see the kalkurr yam here.", "Ngana kalkurr yaluy nyajil.", "ngana kalkurr yaluy nyajil | 1pl.incl.NOM kalkurr.yam here see.NPST", "r320_1pl_incl_here_zero_flora_see_kalkurr", ["ngana", "kalkurr", "yaluy", "nyajil"]),
    row(46, "We see the marrku fruit here.", "Ngana marrku yaluy nyajil.", "ngana marrku yaluy nyajil | 1pl.incl.NOM marrku.fruit here see.NPST", "r320_1pl_incl_here_zero_flora_see_marrku", ["ngana", "marrku", "yaluy", "nyajil"]),
    row(47, "We see the milmarr cane here.", "Ngana milmarr yaluy nyajil.", "ngana milmarr yaluy nyajil | 1pl.incl.NOM milmarr.cane here see.NPST", "r320_1pl_incl_here_zero_flora_see_milmarr", ["ngana", "milmarr", "yaluy", "nyajil"]),
    row(48, "We see the warrabuka yam here.", "Ngana warrabuka yaluy nyajil.", "ngana warrabuka yaluy nyajil | 1pl.incl.NOM warrabuka.yam here see.NPST", "r320_1pl_incl_here_zero_flora_see_warrabuka", ["ngana", "warrabuka", "yaluy", "nyajil"]),
    row(49, "We see the wubali yam here.", "Ngana wubali yaluy nyajil.", "ngana wubali yaluy nyajil | 1pl.incl.NOM wubali.yam here see.NPST", "r320_1pl_incl_here_zero_flora_see_wubali", ["ngana", "wubali", "yaluy", "nyajil"]),
    row(50, "We see the wulku fig here.", "Ngana wulku yaluy nyajil.", "ngana wulku yaluy nyajil | 1pl.incl.NOM wulku.fig here see.NPST", "r320_1pl_incl_here_zero_flora_see_wulku", ["ngana", "wulku", "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 = FRAME_SPECS[band]
        expected_kuku = f"{pronoun.capitalize()} {target} {demo} nyajil."
        expected_english = f"{prefix} the {TARGET_LABELS[target]} {location}."
        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 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("r320_"):
            issues.append(f"{seq}: frame not r320 {frame}")
    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")
    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}")
    target_counts = count_words(db, TARGET_ORDER)
    support_counts = count_words(db, ["ngali", "ngaliny", "yubal", "yurra", "ngana", "yaluy", "yinyay", "nyajil"])
    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 FLORA NON-SINGULAR NONPAST PERCEPTION SWEEP AFTER RULE 319 (Rule 320). 50 under-review rows "
        "over ten zero-use direct-dictionary flora heads: bikarrakal, dikirr, dukul-dukul, kakarr, kalkurr, marrku, "
        "milmarr, warrabuka, wubali, and wulku. SUPPORT: bare nominative ngali, ngaliny, yubal, yurra, ngana, "
        "Yalanji yaluy/yinyay, and dictionary-attested nonpast nyajil. Conservative visible-flora labels lock "
        "bikarrakal to fruit and kakarr to grass; dukul-dukul remains an indivisible dictionary reduplication. No "
        "grub/bait or blanket/year homograph, edibility/food/preparation, habitat, plant use, properties, taxonomy, "
        "case, new word formation, past/purposive/reduplicated perception, or support inflection is opened."
    )
    cur = db.execute(
        "INSERT INTO batches(label,cheatsheet_version,guide_version,notes,created_at) VALUES(?,?,?,?,?)",
        (LABEL, "Rule 320 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 direct dictionary flora entries, checked every target against Patz (none occurs as a lexical target), and reread Patz non-singular pronoun, demonstrative, nonpast, sensory-perception A/O, plus dictionary running-form nyajil evidence before authoring Rule 320.", artifact_path=PROCESS_LOG, created_at=NOW)
    record_event(db, batch_label=LABEL, phase="planning", event_type="zero-use-flora-nonsingular-nonpast-scope", actor="codex", detail="Selected ten zero-use lint-safe flora nouns for bare non-singular nonpast visual perception. Locked bikarrakal to fruit and kakarr to grass; treated dukul-dukul as an indivisible dictionary head; closed grub/bait, blanket/year, edibility/food/preparation, habitat, use, property, taxonomy, case, new word formation, tense, and support-inflection semantics.", 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="Final 50 Rule 320 flora non-singular nonpast surfaces returned no accepted, revised, or under-review 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 contracts, one selected flora head each, bare non-singular pronouns and Yalanji demonstratives, final nyajil, no loans, no denied forms, and no source-prose drift.", command="python3 -m py_compile batch_scripts/bank_362.py && python3 -c \"import sys;sys.path.insert(0,'batch_scripts');import bank_362;print(bank_362.scan_static())\"", output_excerpt="issues 0", artifact_path="batch_scripts/bank_362.py", created_at=NOW)
    record_event(db, batch_label=LABEL, phase="bank", event_type="bank-success", actor="codex", detail=f"Banked 50 Rule 320 rows as under_review. Verified remains {verified_before}; Kuku words remain {words_before}.", command="python3 batch_scripts/bank_362.py", output_excerpt=f"banked batch-362: 50 under_review; verified_before={verified_before}; kuku_words_before={words_before}", artifact_path=PROCESS_LOG, created_at=NOW)
    db.commit()
    print("banked batch-362: 50 rows under_review")
    return 0


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