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

TARGET_EVIDENCE = {
    "duburan": "Dictionary yaml lines 6196-6209 give duburan as noun for a placed directional sign made from stones or twisted grass and separately a soft carrying ring/wreath. Rule 327 admits directional-sign reference only and leaves ring/wreath, carrying, women, body placement, direction-giving, route use, stone/grass composition, making, positioning, and event propositions closed.",
    "jila": "Dictionary yaml lines 9038-9063 give jila as beeswax, smell, and sweat, with smell/sweat derivatives. Patz lines 7088 and 7091 attest only the smell sense. Rule 327 admits beeswax reference only and leaves smell, sweat/perspiration, crocodile source, body state, bad-smell and sweat derivatives, sensory event, source/use, and equivalence to other wax heads closed.",
    "makarra": "Dictionary yaml lines 17184-17193 give makarra as noun 'streaky yellow ochre'; nearby makirr at 17194-17202 is plain yellow ochre. Rule 327 admits the streaky-yellow-ochre label only and leaves equivalence to makirr, colour/property predication, streak pattern inference, source/place, mining/digging, grinding, painting, body/ceremony use, and events closed.",
    "makirr": "Dictionary yaml lines 17194-17202 give makirr as noun 'yellow ochre', distinct from preceding makarra 'streaky yellow ochre'. Rule 327 admits yellow-ochre reference only and leaves synonym/equivalence collapse, streakiness, colour/property predication, source/place, mining/digging, grinding, painting, body/ceremony use, and events closed.",
    "ngurran": "Dictionary yaml lines 23861-23872 give ngurran as noun 'rope' and also a dilly bag made from rope, with synonym karra. Rule 327 admits rope reference only and leaves bag/container sense, material-source relation, synonym substitution, tying, carrying, making, weaving, possession, and event propositions closed.",
    "nyumbirr": "Dictionary yaml lines 24750-24760 give nyumbirr as noun 'wax made by bees'. Rule 327 admits beeswax reference only and leaves bee/source event, collecting, heating, hardening, softening, attaching, medicine, food/honey, manufacture/use, and equivalence to jila or yikari closed.",
    "warkal": "Dictionary yaml lines 26443-26453 give warkal as noun 'bailer shell' and note its traditional use as a billy/water container. Rule 327 admits bailer-shell reference only and leaves billy/container function, water, carrying, bailing, cooking, food, old-time practice, shell source, possession, and event propositions closed.",
    "wuba": "Dictionary yaml lines 27407-27417 give wuba as noun 'red ochre' and note pigment use. Rule 327 admits red-ochre reference only and leaves colour/property predication, pigment function, source/place, digging, grinding, painting, body/ceremony use, comparison with yellow ochres, and event propositions closed.",
    "wuju": "Dictionary yaml lines 27620-27630 give wuju as a grass sponge/sop used for eating honey or soup. Patz lines 5171-5172 independently attest wuju as grass obtained for eating soup. Rule 327 admits grass-sponge reference only and leaves grass/material decomposition, honey/soup/food, soaking, eating, obtaining, making, carrying, possession, and event propositions closed.",
    "yikari": "Dictionary yaml lines 29896-29906 give yikari as hardened beeswax made with ironwood-root juice extracted by heating and used for spears. Rule 327 admits hardened-beeswax reference only and leaves ironwood/root/juice source, extraction, heating, hardening process, spear/weapon manufacture, attaching, material use, and equivalence to jila or nyumbirr closed.",
}

SUPPORT_EVIDENCE = (
    "Patz grammar line 1476 explicitly includes artifacts and other objects of human habitat among noun referents. "
    "Patz lines 2577-2586 source bare nominative ngayu, yundu, nyulu, bula, and jana/iana; lines 2834-2847 "
    "source Yalanji yaluy 'here' and yinyay 'there'. Examples at lines 2021-2024 and 2568-2571 attest nyaji-ny "
    "'see-PAST', lines 3160-3162 define past -ny, and lines 4256-4265 license nominative pronoun A with bare "
    "absolutive O in perception. Dictionary lines 23876-23883 and 23968-23976 independently attest running-form "
    "nyajin. Exact Patz target search finds wuju at lines 5171-5172 in its grass-sop use and jila at 7088/7091 "
    "only in the smell sense; the other eight targets are absent. Rule 327 takes every selected object sense from "
    "the dictionary and uses only bare support and past visual perception."
)

TARGET_ORDER = ["duburan", "jila", "makarra", "makirr", "ngurran", "nyumbirr", "warkal", "wuba", "wuju", "yikari"]
TARGET_LABELS = {
    "duburan": "duburan directional sign",
    "jila": "jila beeswax",
    "makarra": "makarra streaky yellow ochre",
    "makirr": "makirr yellow ochre",
    "ngurran": "ngurran rope",
    "nyumbirr": "nyumbirr beeswax",
    "warkal": "warkal bailer shell",
    "wuba": "wuba red ochre",
    "wuju": "wuju grass sponge",
    "yikari": "yikari hardened beeswax",
}
TARGET_GLOSSES = {
    "duburan": "duburan.directional.sign",
    "jila": "jila.beeswax",
    "makarra": "makarra.streaky.yellow.ochre",
    "makirr": "makirr.yellow.ochre",
    "ngurran": "ngurran.rope",
    "nyumbirr": "nyumbirr.beeswax",
    "warkal": "warkal.bailer.shell",
    "wuba": "wuba.red.ochre",
    "wuju": "wuju.grass.sponge",
    "yikari": "yikari.hardened.beeswax",
}
TARGET_CONFIDENCE = {"duburan": "0.86", "jila": "0.84", "makarra": "0.91", "makirr": "0.91", "ngurran": "0.87", "nyumbirr": "0.91", "warkal": "0.88", "wuba": "0.91", "wuju": "0.90", "yikari": "0.89"}
EXPECTED_TARGET_COVERAGE = {"duburan": 4, "jila": 9, "makarra": 0, "makirr": 6, "ngurran": 0, "nyumbirr": 0, "warkal": 6, "wuba": 5, "wuju": 6, "yikari": 1}
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 = {
    "ngali", "ngaliny", "yubal", "yurra", "ngana", "nganjin", "yulu", "iana",
    "nganya", "yununy", "nyunguny", "yununiny", "nyunguniny", "ngaykunku", "yununku", "nyungunku",
    "ngaykundu", "yunundu", "nyungundu", "ngaykundumuny", "yunundumuny", "nyungundumuny",
    "ngaykunji", "yununji", "nyungunji", "ngayku", "yunu", "nyunju",
    "jila-burra", "jila-warri", "makarr", "karra", "yinkar", "yalay", "yala", "yanyu", "yinya",
    "yalungku", "yaluyngku", "yinyangka", "yinyayngka", "yalamuny", "yinyamuny", "nyajil", "nyaji-l",
    "nyaji-nka", "nyaji-l-nyaji", "milka", "baykal", "jalngkay",
}
DENY_ENGLISH = (
    "ring", "wreath", "carry", "women", "body", "direction giving", "route", "stone", "position", "smell",
    "sweat", "perspire", "crocodile", "sensory", "equivalent", "pattern", "source", "mine", "dig", "grind",
    "paint", "ceremony", "bag", "container", "tie", "make", "weave", "possess", "bee source", "collect",
    "heat", "soften", "attach", "medicine", "honey", "manufacture", "billy", "water", "bail", "cook",
    "food", "old time", "pigment", "compare", "soup", "soak", "eat", "obtain", "ironwood", "root", "juice",
    "extract", "spear", "weapon", "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 duburan directional sign there.", "Ngayu duburan yinyay nyajin.", "ngayu duburan yinyay nyajin | 1sg.NOM duburan.directional.sign there see.PST", "r327_1sg_there_low_craft_saw_duburan", ["ngayu", "duburan", "yinyay", "nyajin"]),
    row(2, "I saw the jila beeswax there.", "Ngayu jila yinyay nyajin.", "ngayu jila yinyay nyajin | 1sg.NOM jila.beeswax there see.PST", "r327_1sg_there_low_craft_saw_jila", ["ngayu", "jila", "yinyay", "nyajin"]),
    row(3, "I saw the makarra streaky yellow ochre there.", "Ngayu makarra yinyay nyajin.", "ngayu makarra yinyay nyajin | 1sg.NOM makarra.streaky.yellow.ochre there see.PST", "r327_1sg_there_low_craft_saw_makarra", ["ngayu", "makarra", "yinyay", "nyajin"]),
    row(4, "I saw the makirr yellow ochre there.", "Ngayu makirr yinyay nyajin.", "ngayu makirr yinyay nyajin | 1sg.NOM makirr.yellow.ochre there see.PST", "r327_1sg_there_low_craft_saw_makirr", ["ngayu", "makirr", "yinyay", "nyajin"]),
    row(5, "I saw the ngurran rope there.", "Ngayu ngurran yinyay nyajin.", "ngayu ngurran yinyay nyajin | 1sg.NOM ngurran.rope there see.PST", "r327_1sg_there_low_craft_saw_ngurran", ["ngayu", "ngurran", "yinyay", "nyajin"]),
    row(6, "I saw the nyumbirr beeswax there.", "Ngayu nyumbirr yinyay nyajin.", "ngayu nyumbirr yinyay nyajin | 1sg.NOM nyumbirr.beeswax there see.PST", "r327_1sg_there_low_craft_saw_nyumbirr", ["ngayu", "nyumbirr", "yinyay", "nyajin"]),
    row(7, "I saw the warkal bailer shell there.", "Ngayu warkal yinyay nyajin.", "ngayu warkal yinyay nyajin | 1sg.NOM warkal.bailer.shell there see.PST", "r327_1sg_there_low_craft_saw_warkal", ["ngayu", "warkal", "yinyay", "nyajin"]),
    row(8, "I saw the wuba red ochre there.", "Ngayu wuba yinyay nyajin.", "ngayu wuba yinyay nyajin | 1sg.NOM wuba.red.ochre there see.PST", "r327_1sg_there_low_craft_saw_wuba", ["ngayu", "wuba", "yinyay", "nyajin"]),
    row(9, "I saw the wuju grass sponge there.", "Ngayu wuju yinyay nyajin.", "ngayu wuju yinyay nyajin | 1sg.NOM wuju.grass.sponge there see.PST", "r327_1sg_there_low_craft_saw_wuju", ["ngayu", "wuju", "yinyay", "nyajin"]),
    row(10, "I saw the yikari hardened beeswax there.", "Ngayu yikari yinyay nyajin.", "ngayu yikari yinyay nyajin | 1sg.NOM yikari.hardened.beeswax there see.PST", "r327_1sg_there_low_craft_saw_yikari", ["ngayu", "yikari", "yinyay", "nyajin"]),
    row(11, "You saw the duburan directional sign here.", "Yundu duburan yaluy nyajin.", "yundu duburan yaluy nyajin | 2sg.NOM duburan.directional.sign here see.PST", "r327_2sg_here_low_craft_saw_duburan", ["yundu", "duburan", "yaluy", "nyajin"]),
    row(12, "You saw the jila beeswax here.", "Yundu jila yaluy nyajin.", "yundu jila yaluy nyajin | 2sg.NOM jila.beeswax here see.PST", "r327_2sg_here_low_craft_saw_jila", ["yundu", "jila", "yaluy", "nyajin"]),
    row(13, "You saw the makarra streaky yellow ochre here.", "Yundu makarra yaluy nyajin.", "yundu makarra yaluy nyajin | 2sg.NOM makarra.streaky.yellow.ochre here see.PST", "r327_2sg_here_low_craft_saw_makarra", ["yundu", "makarra", "yaluy", "nyajin"]),
    row(14, "You saw the makirr yellow ochre here.", "Yundu makirr yaluy nyajin.", "yundu makirr yaluy nyajin | 2sg.NOM makirr.yellow.ochre here see.PST", "r327_2sg_here_low_craft_saw_makirr", ["yundu", "makirr", "yaluy", "nyajin"]),
    row(15, "You saw the ngurran rope here.", "Yundu ngurran yaluy nyajin.", "yundu ngurran yaluy nyajin | 2sg.NOM ngurran.rope here see.PST", "r327_2sg_here_low_craft_saw_ngurran", ["yundu", "ngurran", "yaluy", "nyajin"]),
    row(16, "You saw the nyumbirr beeswax here.", "Yundu nyumbirr yaluy nyajin.", "yundu nyumbirr yaluy nyajin | 2sg.NOM nyumbirr.beeswax here see.PST", "r327_2sg_here_low_craft_saw_nyumbirr", ["yundu", "nyumbirr", "yaluy", "nyajin"]),
    row(17, "You saw the warkal bailer shell here.", "Yundu warkal yaluy nyajin.", "yundu warkal yaluy nyajin | 2sg.NOM warkal.bailer.shell here see.PST", "r327_2sg_here_low_craft_saw_warkal", ["yundu", "warkal", "yaluy", "nyajin"]),
    row(18, "You saw the wuba red ochre here.", "Yundu wuba yaluy nyajin.", "yundu wuba yaluy nyajin | 2sg.NOM wuba.red.ochre here see.PST", "r327_2sg_here_low_craft_saw_wuba", ["yundu", "wuba", "yaluy", "nyajin"]),
    row(19, "You saw the wuju grass sponge here.", "Yundu wuju yaluy nyajin.", "yundu wuju yaluy nyajin | 2sg.NOM wuju.grass.sponge here see.PST", "r327_2sg_here_low_craft_saw_wuju", ["yundu", "wuju", "yaluy", "nyajin"]),
    row(20, "You saw the yikari hardened beeswax here.", "Yundu yikari yaluy nyajin.", "yundu yikari yaluy nyajin | 2sg.NOM yikari.hardened.beeswax here see.PST", "r327_2sg_here_low_craft_saw_yikari", ["yundu", "yikari", "yaluy", "nyajin"]),
    row(21, "He saw the duburan directional sign there.", "Nyulu duburan yinyay nyajin.", "nyulu duburan yinyay nyajin | 3sg.NOM duburan.directional.sign there see.PST", "r327_3sg_there_low_craft_saw_duburan", ["nyulu", "duburan", "yinyay", "nyajin"]),
    row(22, "He saw the jila beeswax there.", "Nyulu jila yinyay nyajin.", "nyulu jila yinyay nyajin | 3sg.NOM jila.beeswax there see.PST", "r327_3sg_there_low_craft_saw_jila", ["nyulu", "jila", "yinyay", "nyajin"]),
    row(23, "He saw the makarra streaky yellow ochre there.", "Nyulu makarra yinyay nyajin.", "nyulu makarra yinyay nyajin | 3sg.NOM makarra.streaky.yellow.ochre there see.PST", "r327_3sg_there_low_craft_saw_makarra", ["nyulu", "makarra", "yinyay", "nyajin"]),
    row(24, "He saw the makirr yellow ochre there.", "Nyulu makirr yinyay nyajin.", "nyulu makirr yinyay nyajin | 3sg.NOM makirr.yellow.ochre there see.PST", "r327_3sg_there_low_craft_saw_makirr", ["nyulu", "makirr", "yinyay", "nyajin"]),
    row(25, "He saw the ngurran rope there.", "Nyulu ngurran yinyay nyajin.", "nyulu ngurran yinyay nyajin | 3sg.NOM ngurran.rope there see.PST", "r327_3sg_there_low_craft_saw_ngurran", ["nyulu", "ngurran", "yinyay", "nyajin"]),
    row(26, "He saw the nyumbirr beeswax there.", "Nyulu nyumbirr yinyay nyajin.", "nyulu nyumbirr yinyay nyajin | 3sg.NOM nyumbirr.beeswax there see.PST", "r327_3sg_there_low_craft_saw_nyumbirr", ["nyulu", "nyumbirr", "yinyay", "nyajin"]),
    row(27, "He saw the warkal bailer shell there.", "Nyulu warkal yinyay nyajin.", "nyulu warkal yinyay nyajin | 3sg.NOM warkal.bailer.shell there see.PST", "r327_3sg_there_low_craft_saw_warkal", ["nyulu", "warkal", "yinyay", "nyajin"]),
    row(28, "He saw the wuba red ochre there.", "Nyulu wuba yinyay nyajin.", "nyulu wuba yinyay nyajin | 3sg.NOM wuba.red.ochre there see.PST", "r327_3sg_there_low_craft_saw_wuba", ["nyulu", "wuba", "yinyay", "nyajin"]),
    row(29, "He saw the wuju grass sponge there.", "Nyulu wuju yinyay nyajin.", "nyulu wuju yinyay nyajin | 3sg.NOM wuju.grass.sponge there see.PST", "r327_3sg_there_low_craft_saw_wuju", ["nyulu", "wuju", "yinyay", "nyajin"]),
    row(30, "He saw the yikari hardened beeswax there.", "Nyulu yikari yinyay nyajin.", "nyulu yikari yinyay nyajin | 3sg.NOM yikari.hardened.beeswax there see.PST", "r327_3sg_there_low_craft_saw_yikari", ["nyulu", "yikari", "yinyay", "nyajin"]),
    row(31, "The two of them saw the duburan directional sign here.", "Bula duburan yaluy nyajin.", "bula duburan yaluy nyajin | 3du.NOM duburan.directional.sign here see.PST", "r327_3du_here_low_craft_saw_duburan", ["bula", "duburan", "yaluy", "nyajin"]),
    row(32, "The two of them saw the jila beeswax here.", "Bula jila yaluy nyajin.", "bula jila yaluy nyajin | 3du.NOM jila.beeswax here see.PST", "r327_3du_here_low_craft_saw_jila", ["bula", "jila", "yaluy", "nyajin"]),
    row(33, "The two of them saw the makarra streaky yellow ochre here.", "Bula makarra yaluy nyajin.", "bula makarra yaluy nyajin | 3du.NOM makarra.streaky.yellow.ochre here see.PST", "r327_3du_here_low_craft_saw_makarra", ["bula", "makarra", "yaluy", "nyajin"]),
    row(34, "The two of them saw the makirr yellow ochre here.", "Bula makirr yaluy nyajin.", "bula makirr yaluy nyajin | 3du.NOM makirr.yellow.ochre here see.PST", "r327_3du_here_low_craft_saw_makirr", ["bula", "makirr", "yaluy", "nyajin"]),
    row(35, "The two of them saw the ngurran rope here.", "Bula ngurran yaluy nyajin.", "bula ngurran yaluy nyajin | 3du.NOM ngurran.rope here see.PST", "r327_3du_here_low_craft_saw_ngurran", ["bula", "ngurran", "yaluy", "nyajin"]),
    row(36, "The two of them saw the nyumbirr beeswax here.", "Bula nyumbirr yaluy nyajin.", "bula nyumbirr yaluy nyajin | 3du.NOM nyumbirr.beeswax here see.PST", "r327_3du_here_low_craft_saw_nyumbirr", ["bula", "nyumbirr", "yaluy", "nyajin"]),
    row(37, "The two of them saw the warkal bailer shell here.", "Bula warkal yaluy nyajin.", "bula warkal yaluy nyajin | 3du.NOM warkal.bailer.shell here see.PST", "r327_3du_here_low_craft_saw_warkal", ["bula", "warkal", "yaluy", "nyajin"]),
    row(38, "The two of them saw the wuba red ochre here.", "Bula wuba yaluy nyajin.", "bula wuba yaluy nyajin | 3du.NOM wuba.red.ochre here see.PST", "r327_3du_here_low_craft_saw_wuba", ["bula", "wuba", "yaluy", "nyajin"]),
    row(39, "The two of them saw the wuju grass sponge here.", "Bula wuju yaluy nyajin.", "bula wuju yaluy nyajin | 3du.NOM wuju.grass.sponge here see.PST", "r327_3du_here_low_craft_saw_wuju", ["bula", "wuju", "yaluy", "nyajin"]),
    row(40, "The two of them saw the yikari hardened beeswax here.", "Bula yikari yaluy nyajin.", "bula yikari yaluy nyajin | 3du.NOM yikari.hardened.beeswax here see.PST", "r327_3du_here_low_craft_saw_yikari", ["bula", "yikari", "yaluy", "nyajin"]),
    row(41, "They saw the duburan directional sign there.", "Jana duburan yinyay nyajin.", "jana duburan yinyay nyajin | 3pl.NOM duburan.directional.sign there see.PST", "r327_3pl_there_low_craft_saw_duburan", ["jana", "duburan", "yinyay", "nyajin"]),
    row(42, "They saw the jila beeswax there.", "Jana jila yinyay nyajin.", "jana jila yinyay nyajin | 3pl.NOM jila.beeswax there see.PST", "r327_3pl_there_low_craft_saw_jila", ["jana", "jila", "yinyay", "nyajin"]),
    row(43, "They saw the makarra streaky yellow ochre there.", "Jana makarra yinyay nyajin.", "jana makarra yinyay nyajin | 3pl.NOM makarra.streaky.yellow.ochre there see.PST", "r327_3pl_there_low_craft_saw_makarra", ["jana", "makarra", "yinyay", "nyajin"]),
    row(44, "They saw the makirr yellow ochre there.", "Jana makirr yinyay nyajin.", "jana makirr yinyay nyajin | 3pl.NOM makirr.yellow.ochre there see.PST", "r327_3pl_there_low_craft_saw_makirr", ["jana", "makirr", "yinyay", "nyajin"]),
    row(45, "They saw the ngurran rope there.", "Jana ngurran yinyay nyajin.", "jana ngurran yinyay nyajin | 3pl.NOM ngurran.rope there see.PST", "r327_3pl_there_low_craft_saw_ngurran", ["jana", "ngurran", "yinyay", "nyajin"]),
    row(46, "They saw the nyumbirr beeswax there.", "Jana nyumbirr yinyay nyajin.", "jana nyumbirr yinyay nyajin | 3pl.NOM nyumbirr.beeswax there see.PST", "r327_3pl_there_low_craft_saw_nyumbirr", ["jana", "nyumbirr", "yinyay", "nyajin"]),
    row(47, "They saw the warkal bailer shell there.", "Jana warkal yinyay nyajin.", "jana warkal yinyay nyajin | 3pl.NOM warkal.bailer.shell there see.PST", "r327_3pl_there_low_craft_saw_warkal", ["jana", "warkal", "yinyay", "nyajin"]),
    row(48, "They saw the wuba red ochre there.", "Jana wuba yinyay nyajin.", "jana wuba yinyay nyajin | 3pl.NOM wuba.red.ochre there see.PST", "r327_3pl_there_low_craft_saw_wuba", ["jana", "wuba", "yinyay", "nyajin"]),
    row(49, "They saw the wuju grass sponge there.", "Jana wuju yinyay nyajin.", "jana wuju yinyay nyajin | 3pl.NOM wuju.grass.sponge there see.PST", "r327_3pl_there_low_craft_saw_wuju", ["jana", "wuju", "yinyay", "nyajin"]),
    row(50, "They saw the yikari hardened beeswax there.", "Jana yikari yinyay nyajin.", "jana yikari yinyay nyajin | 3pl.NOM yikari.hardened.beeswax there see.PST", "r327_3pl_there_low_craft_saw_yikari", ["jana", "yikari", "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")
        if english!=expected_english: issues.append(f"{seq}: English mismatch")
        if analysis!=expected_analysis: issues.append(f"{seq}: analysis mismatch")
        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("r327_"): issues.append(f"{seq}: frame not r327")
        if TARGET_EVIDENCE[target] not in evidence or SUPPORT_EVIDENCE not in evidence: issues.append(f"{seq}: evidence mismatch")
        if confidence!=TARGET_CONFIDENCE[target]: issues.append(f"{seq}: confidence mismatch")
    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: {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=("LOW-COVERAGE CRAFT MATERIALS/OBJECTS SINGULAR/THIRD-PERSON PAST PERCEPTION AFTER RULE 326 (Rule 327). 50 under-review rows over ten 0-9-use noun heads: duburan, jila, makarra, makirr, ngurran, nyumbirr, warkal, wuba, wuju, yikari. Exact referential senses only; no ring/wreath, smell/sweat, ochre equivalence/use, bag sense, wax equivalence/process, container/food, pigment, spear manufacture, source relation, case, nonpast/purposive/reduplicated perception, or support drift.")
    cur=db.execute("INSERT INTO batches(label,cheatsheet_version,guide_version,notes,created_at) VALUES(?,?,?,?,?)",(LABEL,"Rule 327 under review","operator-guide-2026-07-10",notes,NOW)); bid=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(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",[(bid,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 dictionary craft-object entries; exact Patz search found wuju only in grass-sop use and jila only in smell sense, with the other eight absent; reread Patz artifact noun status, singular/third pronouns, Yalanji demonstratives, past, perception A/O, and running nyajin.",artifact_path=PROCESS_LOG,created_at=NOW)
    record_event(db,batch_label=LABEL,phase="planning",event_type="candidate-audit",actor="codex",detail="Structured object audit excluded loans, weapons, coercive implements, place/euphemism homonyms, mortuary yinkar, and unresolved cultural restrictions. Selected ten direct non-loan craft materials/objects with stable narrow readings and coverage 0-9; three wax and three ochre heads remain distinct rather than normalized.",artifact_path=PROCESS_LOG,created_at=NOW)
    record_event(db,batch_label=LABEL,phase="planning",event_type="low-craft-singular-third-past-scope",actor="codex",detail="Locked ten low-coverage craft heads to bare reference in five sourced singular/third-person past-perception frames. Polysemous senses and material-use prose are closed; wax/ochre heads remain non-equivalent; no source, manufacture, use, case, or productive morphology 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 327 exact Kuku surfaces are internally unique and returned no 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 contracts, one selected craft head each, bare singular/third pronouns, Yalanji demonstratives, final nyajin, no loans, denied forms, polysemy/use, equivalence, source, manufacture, case, or support drift.",command="python3 -m py_compile batch_scripts/bank_369.py batch_scripts/close_369.py && AST/static/lint probes",output_excerpt="50 explicit rows; scan_static 0; 50 linter probes 0; collisions 0",artifact_path="batch_scripts/bank_369.py",created_at=NOW)
    record_event(db,batch_label=LABEL,phase="bank",event_type="bank-success",actor="codex",detail=f"Banked 50 Rule 327 rows as under_review. Verified remains {verified_before}; Kuku words remain {words_before}.",command="python3 batch_scripts/bank_369.py",output_excerpt=f"banked batch-369: 50 under_review; verified_before={verified_before}; words_before={words_before}",artifact_path=PROCESS_LOG,created_at=NOW)
    db.commit(); print("banked batch-369: 50 rows under_review"); return 0


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