#!/usr/bin/env python3
"""Bank batch-157: event nouns, sound/action nouns, and temporal-reference lexicon."""

from __future__ import annotations

import datetime as dt
import json
import re
import sqlite3
import sys

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-157"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
PROCESS_LOG = "process_logs/batch-157-event-temporal-nouns-process.md"

DENY = {"yah", "ngawuya", "walnga", "yala-coordination"}
DENY_STANDALONE = {"ba", "ma"}
SOURCE_WAWU_VERB_FORMS = {
    "wawu-janji-nya-muny",
    "wawu-wala-nya-muny",
}


def js(values: list[str]) -> str:
    return json.dumps(values, ensure_ascii=False)


ROWS = [
    (1, "After the sleep, they went on again.",
     "Wawu-warngku-muny, jana dungan-baja.",
     "wawu-warngku-muny, jana dunga-ny-baja | TEMP4-sleep-ABL they go-PAST-again",
     "prior_event_nominal_sleep", 5, js(["wawu-warngku-muny", "jana", "dungay"]), js([]),
     "Patz ex.635 gives wawu-warngku-muny plus dunga-ny-baja; row retains the source shape.", "0.88"),
    (2, "After the meal, mother washes her hands.",
     "Wawu-mayi-muny, ngamu mara julurri-ji.",
     "wawu-mayi-muny, ngamu mara julurri-ji-y | TEMP4-food-ABL mother hand wash-REF-NONPAST",
     "prior_event_nominal_meal", 5, js(["wawu-mayi-muny", "ngamu", "mara", "julurril"]), js([]),
     "Patz 3.10.1 sources wawu-mayi-muny; julurri-ji elder surface follows Rule 114 correction.", "0.84"),
    (3, "After the walk, the children drink water.",
     "Wawu-jilba-muny, karrkay-karrkay bana nukal.",
     "wawu-jilba-muny, karrkay-karrkay bana nuka-l | TEMP4-walk-ABL children water drink-NONPAST",
     "prior_event_nominal_walk", 5, js(["wawu-jilba-muny", "karrkay", "bana", "nukal"]), js([]),
     "Patz ex.497 prefers nominal wawu-jilba-muny for after the walk.", "0.86"),
    (4, "After the barking, father closes the house.",
     "Wawu-ngangkurr-muny, nganjan-angka bayan nandal.",
     "wawu-ngangkurr-muny, nganjan-angka bayan nanda-l | TEMP4-barking.noise-ABL father-ERG house close-NONPAST",
     "prior_event_nominal_barking", 5, js(["wawu-ngangkurr-muny", "nganjan", "bayan", "nandal"]), js([]),
     "Patz ex.496 requires the barking noun ngangkurr in ablative rather than a forced bark-verb form.", "0.86"),
    (5, "Mother went to camp after washing clothes.",
     "Ngamu bayan-ka dungan, wawu-kambi-muny julurrin.",
     "ngamu bayan-ka dunga-ny, wawu-kambi-muny julurri-ny | mother camp-DAT go-PAST TEMP4-clothes-ABL wash-PAST",
     "prior_event_object_ablative_clothes", 5, js(["ngamu", "bayan", "dungay", "wawu-kambi-muny", "julurril"]), js([]),
     "Patz ex.494 object-ablative prior-event pattern with kambi-muny and wash predicate.", "0.86"),
    (6, "They stayed at the house after feeding chickens.",
     "Jana bayan-ba bundan, wawu-jukijuki-muny mayi dajin.",
     "jana bayan-ba bunda-ny, wawu-jukijuki-muny mayi daji-ny | they house-LOC stay-PAST TEMP4-chicken-ABL food give-PAST",
     "prior_event_object_ablative_feeding", 5, js(["jana", "bayan", "bundanday", "wawu-jukijuki-muny", "mayi", "dajil"]), js([]),
     "Patz ex.495 sources wawu-jukijuki-muny mayi daji-ny as the prior feeding event.", "0.86"),
    (7, "After bathing, grandmother cooked food.",
     "Wawu-janji-nya-muny, babi-ngka mayi wajun.",
     "wawu-janji-nya-muny, babi-ngka mayi waju-ny | TEMP4-bathe-SUB-ABL grandmother-ERG food cook-PAST",
     "prior_event_attested_verb_bathe", 5, js(["wawu-janji-nya-muny", "babi", "mayi", "wajul"]), js([]),
     "Patz ex.491 supplies the restricted verb prior-event form wawu-janji-nya-muny.", "0.86"),
    (8, "After entering, the man sat down.",
     "Wawu-wala-nya-muny, dingkar bundan.",
     "wawu-wala-nya-muny, dingkar bunda-ny | TEMP4-enter-SUB-ABL man sit-PAST",
     "prior_event_attested_verb_enter", 5, js(["wawu-wala-nya-muny", "dingkar", "bundanday"]), js([]),
     "Patz ex.492 supplies the restricted verb prior-event form wawu-wala-nya-muny.", "0.84"),
    (9, "After that, we light a fire.",
     "Wawu-yinya-muny, ngana baya wajul.",
     "wawu-yinya-muny, ngana baya waju-l | TEMP4-that-ABL we fire light-NONPAST",
     "prior_event_general_after_that", 4, js(["wawu-yinya-muny", "ngana", "baya", "wajul"]), js([]),
     "Patz ex.636 sources wawu-yinya-muny as the general after-that temporal bridge.", "0.82"),
    (10, "Since that time, the child grew big.",
     "Wawu-yinya-muny, karrkay yalbayman.",
     "wawu-yinya-muny, karrkay yalbay-ma-ny | TEMP4-that-ABL child big-INCHO-PAST",
     "prior_event_general_since_then", 5, js(["wawu-yinya-muny", "karrkay", "yalbay"]), js([]),
     "Patz ex.636 has wawu-yinya-muny plus yalbay-ma-ny; subject varied to avoid copying.", "0.86"),
    (11, "After the sleep, the children came back.",
     "Wawu-warngku-muny, karrkay-karrkay kadan-baja.",
     "wawu-warngku-muny, karrkay-karrkay kada-ny-baja | TEMP4-sleep-ABL children come-PAST-again",
     "prior_event_nominal_sleep", 4, js(["wawu-warngku-muny", "karrkay", "kaday"]), js([]),
     "Second wawu-warngku-muny row varies the main predicate and keeps the nominal ablative.", "0.80"),
    (12, "After the meal, the old people sang a song.",
     "Wawu-mayi-muny, mukul-bama wulngku badin.",
     "wawu-mayi-muny, mukul-bama wulngku badi-ny | TEMP4-food-ABL old-people song sing-PAST",
     "prior_event_nominal_meal_song", 4, js(["wawu-mayi-muny", "mukul-bama", "wulngku", "badi"]), js([]),
     "Combines sourced wawu-mayi-muny with dictionary-backed wulngku badi 'sing'.", "0.80"),

    (13, "Today we stay at the camp.",
     "Nyiku ngana bayan-ba bundanday.",
     "nyiku ngana bayan-ba bundanda-y | today we camp-LOC stay-NONPAST",
     "temporal_root_today", 5, js(["nyiku", "ngana", "bayan", "bundanday"]), js([]),
     "Patz §3.4 lists nyiku as now/today; uninflected time words can set temporal reference.", "0.84"),
    (14, "Tomorrow I will go to see grandmother.",
     "Wunkuny ngayu babi nyaji-nka dungay.",
     "wunkuny ngayu babi nyaji-nka dunga-y | tomorrow I grandmother see-PURP go-NONPAST",
     "temporal_root_tomorrow", 5, js(["wunkuny", "ngayu", "babi", "nyajil", "dungay"]), js([]),
     "Patz ex.114 gives wunkuny plus dunga-y ... nyaji-nka; object varied to grandmother.", "0.86"),
    (15, "Yesterday the child became sick.",
     "Yilayku karrkay bambayman.",
     "yilayku karrkay bambay-ma-ny | yesterday child sick-INCHO-PAST",
     "temporal_root_yesterday", 5, js(["yilayku", "karrkay", "bambay"]), js([]),
     "Patz ex.113 gives yilayku with bambay-ma-ny; subject varied.", "0.86"),
    (16, "During the night long ago, people sang songs.",
     "Wujurr-bu ngadiku bama wulngku badin.",
     "wujurr-bu ngadiku bama wulngku badi-ny | night-LOC long.ago people song sing-PAST",
     "temporal_noun_night_long_ago", 5, js(["wujurr", "ngadiku", "bama", "wulngku", "badi"]), js([]),
     "Patz note gives wujurr-bu ngadiku; wulngku badi is dictionary-backed.", "0.86"),
    (17, "At daybreak father went for water.",
     "Muduwajuny nganjan bana-ka dungan.",
     "muduwaju-ny nganjan bana-ka dunga-ny | daybreak-TIME father water-DAT go-PAST",
     "temporal_daybreak", 5, js(["muduwaju", "nganjan", "bana", "dungay"]), js([]),
     "Dictionary and Patz §5.2.2 source muduwajuny as at daybreak.", "0.84"),
    (18, "In the morning mother took water.",
     "Wunkuwingku ngamu-ngku bana wundin.",
     "wunkuwingku ngamu-ngku bana wundi-ny | morning mother-ERG water take-PAST",
     "temporal_morning", 5, js(["wunkuwingku", "ngamu", "bana", "wundil"]), js([]),
     "Dictionary sources wunkuwingku 'morning'; simple transitive row with sourced take-water lexicon.", "0.82"),
    (19, "In the late afternoon the friend came.",
     "Yilay-yilay jawun kadan.",
     "yilay-yilay jawun kada-ny | late.afternoon friend come-PAST",
     "temporal_late_afternoon", 5, js(["yilay-yilay", "jawun", "kaday"]), js([]),
     "Patz §3.4 and dictionary source yilay-yilay as late afternoon.", "0.84"),
    (20, "In the middle of the night, rain fell.",
     "Kunarangkal kaba daran.",
     "kunarangkal kaba dara-ny | middle.of.night rain fall-PAST",
     "temporal_middle_night", 5, js(["kunarangkal", "kaba", "daray"]), js([]),
     "Dictionary sources kunarangkal 'middle of the night'; rain-fall frame is already sourced.", "0.84"),
    (21, "During the night the child heard barking.",
     "Wujurr-bu karrkay-ngku ngangkurr nyajin.",
     "wujurr-bu karrkay-ngku ngangkurr nyaji-ny | night-LOC child-ERG barking.noise hear-PAST",
     "temporal_night_sound", 5, js(["wujurr", "karrkay", "ngangkurr", "nyajil"]), js([]),
     "Patz §3.4 gives wujurr-bu; dictionary/Patz source ngangkurr as barking noise.", "0.84"),
    (22, "The next day we walked again.",
     "Wunkuny ngana jilba-dungan-baja.",
     "wunkuny ngana jilba-dunga-ny-baja | next.day we walk-go-PAST-again",
     "temporal_next_day_walk", 5, js(["wunkuny", "ngana", "jilba-dunga-y"]), js([]),
     "Patz §3.4 lists wunkuny as next day/tomorrow; jilba-dunga-y is source-backed walk-go.", "0.84"),
    (23, "Yesterday they stayed at the camp.",
     "Yilayku jana bayan-ba bundan.",
     "yilayku jana bayan-ba bunda-ny | yesterday they camp-LOC stay-PAST",
     "temporal_yesterday_camp", 4, js(["yilayku", "jana", "bayan", "bundanday"]), js([]),
     "Yilayku is sourced as yesterday; camp-stay frame is common and source-backed.", "0.80"),
    (24, "At dawn the dog followed the track.",
     "Muduwajuny kaya-ngka jina wukurrin.",
     "muduwaju-ny kaya-ngka jina wukurri-ny | daybreak-TIME dog-ERG track follow-PAST",
     "temporal_daybreak_track", 4, js(["muduwaju", "kaya", "jina", "wukurril"]), js([]),
     "Muduwajuny daybreak plus dictionary-backed track/follow vocabulary.", "0.80"),
    (25, "In the morning grandmother cooked food.",
     "Wunkuwingku babi-ngka mayi wajun.",
     "wunkuwingku babi-ngka mayi waju-ny | morning grandmother-ERG food cook-PAST",
     "temporal_morning_meal", 4, js(["wunkuwingku", "babi", "mayi", "wajul"]), js([]),
     "Wunkuwingku 'morning' with source-backed mayi waju-l food-cooking frame.", "0.80"),
    (26, "In the late afternoon we came back.",
     "Yilay-yilay ngana kadan-baja.",
     "yilay-yilay ngana kada-ny-baja | late.afternoon we come-PAST-again",
     "temporal_late_afternoon_return", 4, js(["yilay-yilay", "ngana", "kaday"]), js([]),
     "Second yilay-yilay row varies the predicate and reinforces the time word.", "0.80"),

    (27, "At sunrise they went.",
     "Wungar dakal, jana dungan.",
     "wungar dakal, jana dunga-ny | sun sunrise they go-PAST",
     "time_phrase_sunrise", 5, js(["wungar dakal", "jana", "dungay"]), js([]),
     "Dictionary and Patz source wungar dakal as sunrise.", "0.84"),
    (28, "At midday the children rested in the shade.",
     "Wungar wangkar-wangkar, karrkay-karrkay wabarr-ba wunanan.",
     "wungar wangkar-wangkar, karrkay-karrkay wabarr-ba wunana-ny | sun above-REDUP children shade-LOC rest-PAST",
     "time_phrase_midday", 5, js(["wungar wangkar-wangkar", "karrkay", "wabarr", "wunana"]), js([]),
     "Patz describes wungar wangkar-wangkar as mid-morning to early afternoon; shade/rest vocabulary is sourced.", "0.84"),
    (29, "At sunset we came to camp.",
     "Wungar daray, ngana bayan-ka kadan.",
     "wungar daray, ngana bayan-ka kada-ny | sun sunset we camp-DAT come-PAST",
     "time_phrase_sunset", 5, js(["wungar daray", "ngana", "bayan", "kaday"]), js([]),
     "Dictionary sources wungar daray as sunset; camp-return frame varies earlier rows.", "0.84"),
    (30, "In the hot season people stay near water.",
     "Wungar-iji bama bana ngundu-ba bundanday.",
     "wungar-iji bama bana ngundu-ba bundanda-y | sun-COMIT people water close-LOC stay-NONPAST",
     "season_hot", 5, js(["wungar-iji", "bama", "bana", "ngundu", "bundanday"]), js([]),
     "Patz §3.4 lists wungar-iji as hot season; ngundu-ba close/near location is sourced.", "0.82"),
    (31, "In the cold season, fire is good.",
     "Bulur-iji baya ngulkurr.",
     "bulur-iji baya ngulkurr | cold.season fire good",
     "season_cold", 5, js(["bulur-iji", "baya", "ngulkurr"]), js([]),
     "Patz §3.4 lists bulur-iji as cold season; baya and ngulkurr are stable lexemes.", "0.82"),
    (32, "The moon is big now.",
     "Nyiku kija yalbay.",
     "nyiku kija yalbay | now moon big",
     "temporal_moon", 5, js(["nyiku", "kija", "yalbay"]), js([]),
     "Patz §3.4 restricts kija to moon/month semantics; row keeps the moon sense explicit.", "0.84"),
    (33, "The month is long.",
     "Kija kalbay.",
     "kija kalbay | month long",
     "temporal_month", 5, js(["kija", "kalbay"]), js([]),
     "Patz §3.4 gives kija as moon/month; English and gloss keep the month sense explicit.", "0.84"),
    (34, "At daybreak the sun rose.",
     "Muduwajuny wungar wandin.",
     "muduwaju-ny wungar wandi-ny | daybreak-TIME sun rise-PAST",
     "time_phrase_daybreak_sun", 4, js(["muduwaju", "wungar", "wandi"]), js([]),
     "Muduwajuny is sourced as daybreak; wungar wandi- is already used for sun-rise timing.", "0.80"),
    (35, "At midday we drink water.",
     "Wungar wangkar-wangkar, ngana bana nukal.",
     "wungar wangkar-wangkar, ngana bana nuka-l | midday we water drink-NONPAST",
     "time_phrase_midday_water", 4, js(["wungar wangkar-wangkar", "ngana", "bana", "nukal"]), js([]),
     "Avoids duplicating the bare wungar wangkar-wangkar row by adding a sourced main clause.", "0.80"),
    (36, "At sunset grandmother stayed at the camp.",
     "Wungar daray, babi bayan-ba bundan.",
     "wungar daray, babi bayan-ba bunda-ny | sunset grandmother camp-LOC stay-PAST",
     "time_phrase_sunset_camp", 4, js(["wungar daray", "babi", "bayan", "bundanday"]), js([]),
     "Second sunset row varies participant and predicate while preserving the time phrase.", "0.80"),

    (37, "The child heard the song from far away.",
     "Karrkay-ngku wulngku kalakalbay-mundu nyajin.",
     "karrkay-ngku wulngku kalakalbay-mundu nyaji-ny | child-ERG song far-ABL hear-PAST",
     "sound_song_hear", 5, js(["karrkay", "wulngku", "kalakalbay", "nyajil"]), js([]),
     "Grammar source has wulngku heard from far away; subject varied.", "0.84"),
    (38, "Grandmother sang a song in the morning.",
     "Wunkuwingku babi-ngka wulngku badin.",
     "wunkuwingku babi-ngka wulngku badi-ny | morning grandmother-ERG song sing-PAST",
     "sound_song_sing", 5, js(["wunkuwingku", "babi", "wulngku", "badi"]), js([]),
     "Dictionary sources wulngku badi 'sing'; wunkuwingku supplies a sourced time setting.", "0.82"),
    (39, "The child cried for food.",
     "Karrkay mayi-ka badin.",
     "karrkay mayi-ka badi-ny | child food-DAT cry-PAST",
     "sound_cry_food", 5, js(["karrkay", "mayi", "badi"]), js([]),
     "Dictionary example gives child crying for food with badi-ny and mayi-ka.", "0.86"),
    (40, "The children cried in the night.",
     "Karrkay-karrkay wujurr-bu banbadi.",
     "karrkay-karrkay wujurr-bu banbadi-y | children night-LOC cry.REDUP-NONPAST",
     "sound_repeated_cry_night", 5, js(["karrkay", "wujurr", "banbadi"]), js([]),
     "Patz §3.4 gives wujurr-bu; banbadi elder surface drops final -y after i.", "0.84"),
    (41, "A big thunderstorm came in the middle of the night.",
     "Kunarangkal jarramali yalbay kadan.",
     "kunarangkal jarramali yalbay kada-ny | middle.of.night thunderstorm big come-PAST",
     "weather_thunderstorm_night", 5, js(["kunarangkal", "jarramali", "yalbay", "kaday"]), js([]),
     "Dictionary sources jarramali as thunder/thunderstorm and kunarangkal as middle of the night.", "0.84"),
    (42, "Rain fell in the morning.",
     "Wunkuwingku kaba daran.",
     "wunkuwingku kaba dara-ny | morning rain fall-PAST",
     "weather_rain_morning", 5, js(["wunkuwingku", "kaba", "daray"]), js([]),
     "Dictionary sources kaba 'rain'; Patz examples source kaba dara-ny 'rain fell'.", "0.84"),
    (43, "Wind came from the sea.",
     "Muyar jalun-muny kadan.",
     "muyar jalun-muny kada-ny | wind sea-ABL come-PAST",
     "weather_wind_source", 5, js(["muyar", "jalun", "kaday"]), js([]),
     "Dictionary sources muyar 'wind'; ablative source phrase uses regular nominal case.", "0.82"),
    (44, "A big wind came.",
     "Muyar yalbay kadan.",
     "muyar yalbay kada-ny | wind big come-PAST",
     "weather_wind_big", 4, js(["muyar", "yalbay", "kaday"]), js([]),
     "Simple weather noun row varying prior strong-wind surfaces.", "0.78"),
    (45, "Mother sent news to the old people.",
     "Ngamu-ngku kuku mukul-bama-nka yungan.",
     "ngamu-ngku kuku mukul-bama-nka yunga-ny | mother-ERG news old-people-DAT send-PAST",
     "speech_news_send", 5, js(["ngamu", "kuku", "mukul-bama", "yungal"]), js([]),
     "Dictionary sources kuku as news/talk/language; yunga-l send is source-backed.", "0.82"),
    (46, "I heard grandmother's words.",
     "Ngayu babi-mu kuku nyajin.",
     "ngayu babi-mu kuku nyaji-ny | I grandmother-GEN words hear-PAST",
     "speech_words_hear", 5, js(["ngayu", "babi", "kuku", "nyajil"]), js([]),
     "Kuku is dictionary-backed as talk/language/news; hearing uses sourced nyaji-l perception verb.", "0.82"),
    (47, "The child asked about the song.",
     "Karrkay wulngku-ku babajin.",
     "karrkay wulngku-ku babaji-ny | child song-DAT ask-PAST",
     "speech_song_question", 4, js(["karrkay", "wulngku", "babajil"]), js([]),
     "Wulngku-ku about the song follows earlier source-shaped ask-about rows.", "0.80"),
    (48, "The old people know many songs.",
     "Mukul-bama wulngku wubul binal.",
     "mukul-bama wulngku wubul binal | old-people song many know",
     "speech_song_knowledge", 4, js(["mukul-bama", "wulngku", "wubul", "binal"]), js([]),
     "Dictionary-backed wulngku plus stable binal/wubul lexicon.", "0.78"),
    (49, "The barking came from the house.",
     "Ngangkurr bayan-mundu kadan.",
     "ngangkurr bayan-mundu kada-ny | barking.noise house-ABL come-PAST",
     "sound_barking_source", 5, js(["ngangkurr", "bayan", "kaday"]), js([]),
     "Dictionary and Patz source ngangkurr as barking sound; ablative source phrase avoids a bark-verb nominalization.", "0.84"),
    (50, "The thunderstorm did not come; only wind came.",
     "Jarramali kari kadan, muyar nganga kadan.",
     "jarramali kari kada-ny, muyar nganga kada-ny | thunderstorm NEG come-PAST wind only come-PAST",
     "weather_contrast", 4, js(["jarramali", "kari", "kaday", "muyar", "nganga"]), js([]),
     "Weather contrast using sourced jarramali and muyar; no new weather verb is invented.", "0.78"),
]


def scan_static() -> list[str]:
    issues: list[str] = []
    if len(ROWS) != 50:
        issues.append(f"expected 50 rows, got {len(ROWS)}")
    seqs = [r[0] for r in ROWS]
    if seqs != list(range(1, 51)):
        issues.append(f"seqs must be 1..50, got {seqs[:5]}...{seqs[-5:]}")
    seen_ku: set[str] = set()
    for row in ROWS:
        seq, english, kuku, analysis, frame, _tier, words_used, loans_used, evidence, _confidence = row
        label = f"{LABEL}.{seq:02d}"
        if not english.lstrip("'\"")[:1].isupper() or english.rstrip("'\"").rstrip()[-1:] not in ".!?":
            issues.append(f"{label}: English must be capitalized and final-punctuated")
        if not kuku.lstrip("'\"")[:1].isupper():
            issues.append(f"{label}: Kuku surface must start uppercase")
        if " | " not in analysis:
            issues.append(f"{label}: analysis missing gloss separator")
        for field_name, payload in (("words_used", words_used), ("loans_used", loans_used)):
            try:
                json.loads(payload)
            except Exception as exc:
                issues.append(f"{label}: {field_name} is not JSON: {exc}")
        low = f" {kuku.lower()} {analysis.lower()} {evidence.lower()} "
        for word in DENY:
            if re.search(rf"(?<![a-z]){re.escape(word)}(?![a-z])", low):
                issues.append(f"{label}: denied blocked/special token {word!r}")
        for tok in re.sub(r"[.!?,]", " ", kuku.lower()).split():
            if tok.strip("'\"") in DENY_STANDALONE:
                issues.append(f"{label}: denied standalone special interjection {tok!r}")
        if "wawu-" in kuku.lower():
            if "-muny" not in kuku.lower() or "TEMP4" not in analysis:
                issues.append(f"{label}: wawu prior-event row must carry -muny and TEMP4")
            for form in re.findall(r"wawu-[a-z-]+?-nya-muny", kuku.lower()):
                if form not in SOURCE_WAWU_VERB_FORMS:
                    issues.append(f"{label}: unsourced verb prior-event form {form!r}")
        if re.search(r"(?<![a-z])kija(?![a-z])", kuku.lower()):
            if not re.search(r"moon|month", english.lower() + " " + analysis.lower()):
                issues.append(f"{label}: kija row must keep moon/month semantics explicit")
        if kuku.lower() in seen_ku:
            issues.append(f"{label}: duplicate Kuku surface within batch")
        seen_ku.add(kuku.lower())
    return issues


def main() -> int:
    issues = scan_static()
    if issues:
        print("pre-bank scan failed:")
        for issue in issues:
            print(f"  - {issue}")
        return 1

    db = sqlite3.connect(DB)
    db.execute("PRAGMA foreign_keys = ON")
    db.execute("BEGIN")
    ensure_schema(db)
    existing = db.execute("SELECT id FROM batches WHERE label=?", (LABEL,)).fetchone()
    if existing:
        batch_id = existing[0]
        accepted = db.execute(
            "SELECT COUNT(*) FROM sentences WHERE batch_id=? AND status IN ('accepted','revised')",
            (batch_id,),
        ).fetchone()[0]
        if accepted:
            raise SystemExit(f"{LABEL} already has accepted/revised rows; refusing to overwrite")
        db.execute("DELETE FROM reviews WHERE sentence_id IN (SELECT id FROM sentences WHERE batch_id=?)", (batch_id,))
        db.execute("DELETE FROM sentences WHERE batch_id=?", (batch_id,))
        db.execute("UPDATE batches SET notes=?, created_at=? WHERE id=?", ("rebanked under_review", NOW, batch_id))
    else:
        cur = db.execute(
            "INSERT INTO batches(label, cheatsheet_version, guide_version, notes, created_at) VALUES(?,?,?,?,?)",
            (LABEL, "Rule 115 draft: event and temporal-reference nouns", "operator-guide-2026-07-07", "under_review", NOW),
        )
        batch_id = cur.lastrowid

    dupes = []
    for seq, _english, kuku, *_rest in ROWS:
        hit = db.execute(
            """
            SELECT b.label, s.seq
            FROM sentences s JOIN batches b ON b.id=s.batch_id
            WHERE lower(trim(s.kuku))=lower(trim(?))
              AND s.status!='rejected'
              AND s.batch_id!=?
            """,
            (kuku, batch_id),
        ).fetchone()
        if hit:
            dupes.append(f"{LABEL}.{seq:02d} duplicates {hit[0]}.{hit[1]:02d}: {kuku}")
    if dupes:
        db.rollback()
        print("cross-corpus duplicate check failed:")
        for dupe in dupes:
            print(f"  - {dupe}")
        return 1

    record_event(
        db,
        batch_label=LABEL,
        phase="source",
        event_type="source-pass",
        actor="claude-main",
        detail=(
            "Rule 115 source pass read Patz 3.4 time words and common time nouns; Patz 4.4.4.3/5.2.2 "
            "wawu- prior-event and temporal bridging notes; Patz 3.10.1 wawu-mayi-muny; and examples 491-497 "
            "for prior-event nominal/object ablatives."
        ),
        command="rg/sed over grammar.md and dictionary.yaml for Rule 115 event/time/sound inventory",
        artifact_path=PROCESS_LOG,
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="source",
        event_type="lexeme-source-check",
        actor="claude-main",
        detail=(
            "Checked lexical inventory: mayi, jilba, ngangkurr, warngku, kambi, jukijuki, yinya, muduwaju, "
            "wunkuwingku, kunarangkal, yilayku, yilay-yilay, wujurr, ngadiku, wungar dakal, wungar daray, "
            "wungar wangkar-wangkar, wungar-iji, bulur-iji, kija, wulngku, wulngku badi, kuku, badi, banbadi, "
            "jarramali, kaba, and muyar."
        ),
        artifact_path=PROCESS_LOG,
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="preflight",
        event_type="existing-surface-scan",
        actor="claude-main",
        detail=(
            "Scanned accepted/revised rows for wawu-, muduwajuny, wunkuwingku, yilay-yilay, kunarangkal, wungar, "
            "ngangkurr, wulngku, banbadi, jarramali, kaba, and muyar surfaces. Avoided exact Batch 156 prior-event "
            "surfaces and known bare rows such as Wujurr-bu jarramali kadan and Wungar wangkar-wangkar."
        ),
        command="sqlite scans over sentences joined to batches for Rule 115 surfaces",
        artifact_path=PROCESS_LOG,
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="scope",
        event_type="risk-controls",
        actor="claude-main",
        detail=(
            "Controls: no wawu- without -muny/TEMP4; wawu-VERB-nya-muny restricted to source forms; kija only "
            "moon/month; burri excluded from new rows; no invented action nouns; weather nouns kept to source-backed "
            "come/fall/not-come frames."
        ),
        artifact_path=PROCESS_LOG,
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="process",
        event_type="process-capture-expanded",
        actor="claude-main",
        detail=(
            "Following the user's instruction to store as much process as possible, this batch stores source inventory, "
            "exclusion rationale, exact-surface scan summary, row-section plan, static guard design, bank output, lint "
            "output, close counts, export counts, render result, and live docs verification."
        ),
        artifact_path=PROCESS_LOG,
        created_at=NOW,
    )
    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, english, kuku, analysis, frame, tier, words_used,
                loans_used, evidence, "under_review", confidence,
                "project_approved_synthetic_pending_elder_verification",
                "claude-main", NOW, NOW,
            )
            for seq, english, kuku, analysis, frame, tier, words_used, loans_used, evidence, confidence in ROWS
        ],
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="bank",
        event_type="bank-success",
        actor="claude-main",
        detail="Banked 50 hand-authored Rule 115 lexical rows under_review after static guards and duplicate checks.",
        command="python3 batch_scripts/bank_157.py",
        artifact_path="batch_scripts/bank_157.py",
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="bank",
        event_type="row-inventory",
        actor="claude-main",
        detail=(
            "Rows 1-12 cover prior-event lexical support; rows 13-26 cover time words and day/night reference; "
            "rows 27-36 cover sun/moon/month/season phrases; rows 37-50 cover sound, speech, song, crying, "
            "thunderstorm, rain, wind, and news/message nouns."
        ),
        artifact_path="batch_scripts/bank_157.py",
        created_at=NOW,
    )
    db.commit()
    avg_words = sum(len(row[2].replace("!", " !").replace("?", " ?").split()) for row in ROWS) / len(ROWS)
    print(f"banked {LABEL}: 50 rows under_review; avg Kuku words/row={avg_words:.2f}")
    return 0


if __name__ == "__main__":
    sys.exit(main())
