#!/usr/bin/env python3
"""Bank batch-325: Rule 283 non-singular visible sky/celestial 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-325"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
PROCESS_LOG = "process_logs/batch-325-visible-sky-celestial-nonsingular-complementary-past-pronoun-perception-after-rule282-process.md"

TARGET_HEADS = {
    "balbay": "lightning",
    "binyu": "shooting star",
    "dawar": "star",
    "jiri": "sky",
    "kaba": "rain",
    "wungar": "sun",
    "kurrinkurrin": "mackerel sky",
    "kurrubijal": "morning star",
    "ngurrban": "cloud",
    "yiril": "rainbow",
}
TARGET_ORDER = [
    "balbay", "binyu", "dawar", "jiri", "kaba", "wungar", "kurrinkurrin", "kurrubijal", "ngurrban", "yiril",
]
SUPPORT = {"ngali", "ngaliny", "yubal", "yurra", "jana", "yaluy", "yinyay", "nyajin"}
DENY_KUKU = {
    "kija", "dawarr", "jiri bajaku", "jiri-warra", "jiri-wuran", "kababina", "kaba-kada",
    "wungar dakal", "wungar daray", "wungar jalamal", "wungar jarra-jarra", "wungar wandil-wandil",
    "wungar wangkar-wangkar", "wungar-iji", "wungariji", "yirilngka", "ngalingan", "ngalinyan",
    "yubalan", "yurrangan", "janangan", "ngalininy", "ngalinyiny", "yubaliny", "yurraniny",
    "jananiny", "ngalinka", "ngalinyanka", "yubalanka", "yurranka", "jananka", "ngalinda",
    "ngalinyanda", "yubalanda", "yurranda", "jananda", "ngalinji", "ngalinyanji", "yubalanji",
    "yurranji", "jananji", "ngalinga", "ngalinyanga", "yubalanga", "yurranga", "jananga",
    "nyajil", "nyaji-l", "nyaji-nka", "nyaji-l-nyaji", "yinyangka", "yinyayngka", "yinyamba",
    "yinyamuny", "yalungku", "yaluyngku", "yaluymbu", "yaluyundu", "yalamuny",
}
DENY_ENGLISH = (
    "moon", "month", "roaring meg", "spirit", "omen", "death", "dead", "die", "died", "strike",
    "struck", "weather event", "falling rain", "rain falls", "rainbird", "thunder", "wind", "storm",
    "hot season", "season", "sunrise", "sunset", "midday", "time", "heaven", "sky mob", "cloudless",
    "fine day", "story", "snake", "water hole", "place", "country", "belong", "use", "used", "route",
    "travel", "danger", "illness", "body", "case", "compound", "event",
)


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


def row(seq: int, english: str, kuku: str, analysis: str, frame: str, words: list[str], evidence: str) -> tuple:
    return (seq, english, kuku, analysis, frame, 3, js(words), js([]), evidence, "0.86")


EVIDENCE = {
    "balbay": "Dictionary lines 900-911 give balbay as noun 'lightning' and include lightning-strike example prose. Rule 283 selects visible lightning only and leaves strike/event rows closed. Patz lines 2577-2586 and 2592-2603 source bare non-singular nominative pronouns; lines 2674-2686 source non-singular contrasts; lines 2838-2845 source yaluy/yinyay; and lines 2568-2571 source nyaji-ny 'see-PAST'.",
    "binyu": "Dictionary lines 3063-3074 give binyu as noun 'shooting star' and record death-spirit/death-omen belief prose. Rule 283 selects visible shooting-star reference only.",
    "dawar": "Dictionary lines 5374-5382 give dawar as noun 'star'. Rule 283 selects visible star reference only and leaves dawarr 'straw hat' closed.",
    "jiri": "Dictionary lines 9720-9730 give jiri as noun 'sky/heaven'. Rule 283 selects visible sky reference only and leaves heaven, fine-day, sky-mob, and place-name compounds closed.",
    "kaba": "Dictionary lines 11671-11679 give kaba as noun 'rain'. Rule 283 selects visible rain reference only and leaves falling/coming/weather-event rows closed.",
    "wungar": "Dictionary lines 28081-28089 give wungar as noun 'sun'. Rule 283 selects visible sun reference only and leaves sunrise, sunset, midday, hot-season, and sun-locative compounds closed.",
    "kurrinkurrin": "Dictionary lines 16406-16419 give kurrinkurrin as noun 'mackerel sky' and mark it as reduplicated. Rule 283 treats it as a lexicalized noun only, not productive reduplication.",
    "kurrubijal": "Dictionary lines 16557-16567 give kurrubijal as noun 'morning star', Venus as morning star. Rule 283 selects visible morning-star reference only.",
    "ngurrban": "Dictionary lines 23885-23893 give ngurrban as noun 'cloud'. Rule 283 selects visible cloud reference only and leaves weather-event predicates closed.",
    "yiril": "Dictionary lines 30419-30427 give yiril as noun 'rainbow'. Rule 283 selects visible rainbow reference only and leaves story/snake/water-hole extensions closed.",
}

ROWS = [
    row(1, "We two (not you) saw the lightning there.", "Ngali balbay yinyay nyajin.", "ngali balbay yinyay nyajin | 1du.EXCL.NOM lightning there see.PAST", "r283_1du_excl_sky_celestial_there_saw_balbay", ["ngali", "balbay", "yinyay", "nyajin"], EVIDENCE["balbay"]),
    row(2, "We two (not you) saw the shooting star there.", "Ngali binyu yinyay nyajin.", "ngali binyu yinyay nyajin | 1du.EXCL.NOM shooting.star there see.PAST", "r283_1du_excl_sky_celestial_there_saw_binyu", ["ngali", "binyu", "yinyay", "nyajin"], EVIDENCE["binyu"]),
    row(3, "We two (not you) saw the star there.", "Ngali dawar yinyay nyajin.", "ngali dawar yinyay nyajin | 1du.EXCL.NOM star there see.PAST", "r283_1du_excl_sky_celestial_there_saw_dawar", ["ngali", "dawar", "yinyay", "nyajin"], EVIDENCE["dawar"]),
    row(4, "We two (not you) saw the sky there.", "Ngali jiri yinyay nyajin.", "ngali jiri yinyay nyajin | 1du.EXCL.NOM sky there see.PAST", "r283_1du_excl_sky_celestial_there_saw_jiri", ["ngali", "jiri", "yinyay", "nyajin"], EVIDENCE["jiri"]),
    row(5, "We two (not you) saw the rain there.", "Ngali kaba yinyay nyajin.", "ngali kaba yinyay nyajin | 1du.EXCL.NOM rain there see.PAST", "r283_1du_excl_sky_celestial_there_saw_kaba", ["ngali", "kaba", "yinyay", "nyajin"], EVIDENCE["kaba"]),
    row(6, "We two (not you) saw the sun there.", "Ngali wungar yinyay nyajin.", "ngali wungar yinyay nyajin | 1du.EXCL.NOM sun there see.PAST", "r283_1du_excl_sky_celestial_there_saw_wungar", ["ngali", "wungar", "yinyay", "nyajin"], EVIDENCE["wungar"]),
    row(7, "We two (not you) saw the mackerel sky there.", "Ngali kurrinkurrin yinyay nyajin.", "ngali kurrinkurrin yinyay nyajin | 1du.EXCL.NOM mackerel.sky there see.PAST", "r283_1du_excl_sky_celestial_there_saw_kurrinkurrin", ["ngali", "kurrinkurrin", "yinyay", "nyajin"], EVIDENCE["kurrinkurrin"]),
    row(8, "We two (not you) saw the morning star there.", "Ngali kurrubijal yinyay nyajin.", "ngali kurrubijal yinyay nyajin | 1du.EXCL.NOM morning.star there see.PAST", "r283_1du_excl_sky_celestial_there_saw_kurrubijal", ["ngali", "kurrubijal", "yinyay", "nyajin"], EVIDENCE["kurrubijal"]),
    row(9, "We two (not you) saw the cloud there.", "Ngali ngurrban yinyay nyajin.", "ngali ngurrban yinyay nyajin | 1du.EXCL.NOM cloud there see.PAST", "r283_1du_excl_sky_celestial_there_saw_ngurrban", ["ngali", "ngurrban", "yinyay", "nyajin"], EVIDENCE["ngurrban"]),
    row(10, "We two (not you) saw the rainbow there.", "Ngali yiril yinyay nyajin.", "ngali yiril yinyay nyajin | 1du.EXCL.NOM rainbow there see.PAST", "r283_1du_excl_sky_celestial_there_saw_yiril", ["ngali", "yiril", "yinyay", "nyajin"], EVIDENCE["yiril"]),
    row(11, "You and I saw the lightning here.", "Ngaliny balbay yaluy nyajin.", "ngaliny balbay yaluy nyajin | 1du.INCL.NOM lightning here see.PAST", "r283_1du_incl_sky_celestial_here_saw_balbay", ["ngaliny", "balbay", "yaluy", "nyajin"], EVIDENCE["balbay"]),
    row(12, "You and I saw the shooting star here.", "Ngaliny binyu yaluy nyajin.", "ngaliny binyu yaluy nyajin | 1du.INCL.NOM shooting.star here see.PAST", "r283_1du_incl_sky_celestial_here_saw_binyu", ["ngaliny", "binyu", "yaluy", "nyajin"], EVIDENCE["binyu"]),
    row(13, "You and I saw the star here.", "Ngaliny dawar yaluy nyajin.", "ngaliny dawar yaluy nyajin | 1du.INCL.NOM star here see.PAST", "r283_1du_incl_sky_celestial_here_saw_dawar", ["ngaliny", "dawar", "yaluy", "nyajin"], EVIDENCE["dawar"]),
    row(14, "You and I saw the sky here.", "Ngaliny jiri yaluy nyajin.", "ngaliny jiri yaluy nyajin | 1du.INCL.NOM sky here see.PAST", "r283_1du_incl_sky_celestial_here_saw_jiri", ["ngaliny", "jiri", "yaluy", "nyajin"], EVIDENCE["jiri"]),
    row(15, "You and I saw the rain here.", "Ngaliny kaba yaluy nyajin.", "ngaliny kaba yaluy nyajin | 1du.INCL.NOM rain here see.PAST", "r283_1du_incl_sky_celestial_here_saw_kaba", ["ngaliny", "kaba", "yaluy", "nyajin"], EVIDENCE["kaba"]),
    row(16, "You and I saw the sun here.", "Ngaliny wungar yaluy nyajin.", "ngaliny wungar yaluy nyajin | 1du.INCL.NOM sun here see.PAST", "r283_1du_incl_sky_celestial_here_saw_wungar", ["ngaliny", "wungar", "yaluy", "nyajin"], EVIDENCE["wungar"]),
    row(17, "You and I saw the mackerel sky here.", "Ngaliny kurrinkurrin yaluy nyajin.", "ngaliny kurrinkurrin yaluy nyajin | 1du.INCL.NOM mackerel.sky here see.PAST", "r283_1du_incl_sky_celestial_here_saw_kurrinkurrin", ["ngaliny", "kurrinkurrin", "yaluy", "nyajin"], EVIDENCE["kurrinkurrin"]),
    row(18, "You and I saw the morning star here.", "Ngaliny kurrubijal yaluy nyajin.", "ngaliny kurrubijal yaluy nyajin | 1du.INCL.NOM morning.star here see.PAST", "r283_1du_incl_sky_celestial_here_saw_kurrubijal", ["ngaliny", "kurrubijal", "yaluy", "nyajin"], EVIDENCE["kurrubijal"]),
    row(19, "You and I saw the cloud here.", "Ngaliny ngurrban yaluy nyajin.", "ngaliny ngurrban yaluy nyajin | 1du.INCL.NOM cloud here see.PAST", "r283_1du_incl_sky_celestial_here_saw_ngurrban", ["ngaliny", "ngurrban", "yaluy", "nyajin"], EVIDENCE["ngurrban"]),
    row(20, "You and I saw the rainbow here.", "Ngaliny yiril yaluy nyajin.", "ngaliny yiril yaluy nyajin | 1du.INCL.NOM rainbow here see.PAST", "r283_1du_incl_sky_celestial_here_saw_yiril", ["ngaliny", "yiril", "yaluy", "nyajin"], EVIDENCE["yiril"]),
    row(21, "You two saw the lightning there.", "Yubal balbay yinyay nyajin.", "yubal balbay yinyay nyajin | 2du.NOM lightning there see.PAST", "r283_2du_sky_celestial_there_saw_balbay", ["yubal", "balbay", "yinyay", "nyajin"], EVIDENCE["balbay"]),
    row(22, "You two saw the shooting star there.", "Yubal binyu yinyay nyajin.", "yubal binyu yinyay nyajin | 2du.NOM shooting.star there see.PAST", "r283_2du_sky_celestial_there_saw_binyu", ["yubal", "binyu", "yinyay", "nyajin"], EVIDENCE["binyu"]),
    row(23, "You two saw the star there.", "Yubal dawar yinyay nyajin.", "yubal dawar yinyay nyajin | 2du.NOM star there see.PAST", "r283_2du_sky_celestial_there_saw_dawar", ["yubal", "dawar", "yinyay", "nyajin"], EVIDENCE["dawar"]),
    row(24, "You two saw the sky there.", "Yubal jiri yinyay nyajin.", "yubal jiri yinyay nyajin | 2du.NOM sky there see.PAST", "r283_2du_sky_celestial_there_saw_jiri", ["yubal", "jiri", "yinyay", "nyajin"], EVIDENCE["jiri"]),
    row(25, "You two saw the rain there.", "Yubal kaba yinyay nyajin.", "yubal kaba yinyay nyajin | 2du.NOM rain there see.PAST", "r283_2du_sky_celestial_there_saw_kaba", ["yubal", "kaba", "yinyay", "nyajin"], EVIDENCE["kaba"]),
    row(26, "You two saw the sun there.", "Yubal wungar yinyay nyajin.", "yubal wungar yinyay nyajin | 2du.NOM sun there see.PAST", "r283_2du_sky_celestial_there_saw_wungar", ["yubal", "wungar", "yinyay", "nyajin"], EVIDENCE["wungar"]),
    row(27, "You two saw the mackerel sky there.", "Yubal kurrinkurrin yinyay nyajin.", "yubal kurrinkurrin yinyay nyajin | 2du.NOM mackerel.sky there see.PAST", "r283_2du_sky_celestial_there_saw_kurrinkurrin", ["yubal", "kurrinkurrin", "yinyay", "nyajin"], EVIDENCE["kurrinkurrin"]),
    row(28, "You two saw the morning star there.", "Yubal kurrubijal yinyay nyajin.", "yubal kurrubijal yinyay nyajin | 2du.NOM morning.star there see.PAST", "r283_2du_sky_celestial_there_saw_kurrubijal", ["yubal", "kurrubijal", "yinyay", "nyajin"], EVIDENCE["kurrubijal"]),
    row(29, "You two saw the cloud there.", "Yubal ngurrban yinyay nyajin.", "yubal ngurrban yinyay nyajin | 2du.NOM cloud there see.PAST", "r283_2du_sky_celestial_there_saw_ngurrban", ["yubal", "ngurrban", "yinyay", "nyajin"], EVIDENCE["ngurrban"]),
    row(30, "You two saw the rainbow there.", "Yubal yiril yinyay nyajin.", "yubal yiril yinyay nyajin | 2du.NOM rainbow there see.PAST", "r283_2du_sky_celestial_there_saw_yiril", ["yubal", "yiril", "yinyay", "nyajin"], EVIDENCE["yiril"]),
    row(31, "You all saw the lightning here.", "Yurra balbay yaluy nyajin.", "yurra balbay yaluy nyajin | 2pl.NOM lightning here see.PAST", "r283_2pl_sky_celestial_here_saw_balbay", ["yurra", "balbay", "yaluy", "nyajin"], EVIDENCE["balbay"]),
    row(32, "You all saw the shooting star here.", "Yurra binyu yaluy nyajin.", "yurra binyu yaluy nyajin | 2pl.NOM shooting.star here see.PAST", "r283_2pl_sky_celestial_here_saw_binyu", ["yurra", "binyu", "yaluy", "nyajin"], EVIDENCE["binyu"]),
    row(33, "You all saw the star here.", "Yurra dawar yaluy nyajin.", "yurra dawar yaluy nyajin | 2pl.NOM star here see.PAST", "r283_2pl_sky_celestial_here_saw_dawar", ["yurra", "dawar", "yaluy", "nyajin"], EVIDENCE["dawar"]),
    row(34, "You all saw the sky here.", "Yurra jiri yaluy nyajin.", "yurra jiri yaluy nyajin | 2pl.NOM sky here see.PAST", "r283_2pl_sky_celestial_here_saw_jiri", ["yurra", "jiri", "yaluy", "nyajin"], EVIDENCE["jiri"]),
    row(35, "You all saw the rain here.", "Yurra kaba yaluy nyajin.", "yurra kaba yaluy nyajin | 2pl.NOM rain here see.PAST", "r283_2pl_sky_celestial_here_saw_kaba", ["yurra", "kaba", "yaluy", "nyajin"], EVIDENCE["kaba"]),
    row(36, "You all saw the sun here.", "Yurra wungar yaluy nyajin.", "yurra wungar yaluy nyajin | 2pl.NOM sun here see.PAST", "r283_2pl_sky_celestial_here_saw_wungar", ["yurra", "wungar", "yaluy", "nyajin"], EVIDENCE["wungar"]),
    row(37, "You all saw the mackerel sky here.", "Yurra kurrinkurrin yaluy nyajin.", "yurra kurrinkurrin yaluy nyajin | 2pl.NOM mackerel.sky here see.PAST", "r283_2pl_sky_celestial_here_saw_kurrinkurrin", ["yurra", "kurrinkurrin", "yaluy", "nyajin"], EVIDENCE["kurrinkurrin"]),
    row(38, "You all saw the morning star here.", "Yurra kurrubijal yaluy nyajin.", "yurra kurrubijal yaluy nyajin | 2pl.NOM morning.star here see.PAST", "r283_2pl_sky_celestial_here_saw_kurrubijal", ["yurra", "kurrubijal", "yaluy", "nyajin"], EVIDENCE["kurrubijal"]),
    row(39, "You all saw the cloud here.", "Yurra ngurrban yaluy nyajin.", "yurra ngurrban yaluy nyajin | 2pl.NOM cloud here see.PAST", "r283_2pl_sky_celestial_here_saw_ngurrban", ["yurra", "ngurrban", "yaluy", "nyajin"], EVIDENCE["ngurrban"]),
    row(40, "You all saw the rainbow here.", "Yurra yiril yaluy nyajin.", "yurra yiril yaluy nyajin | 2pl.NOM rainbow here see.PAST", "r283_2pl_sky_celestial_here_saw_yiril", ["yurra", "yiril", "yaluy", "nyajin"], EVIDENCE["yiril"]),
    row(41, "They saw the lightning there.", "Jana balbay yinyay nyajin.", "jana balbay yinyay nyajin | 3pl.NOM lightning there see.PAST", "r283_3pl_sky_celestial_there_saw_balbay", ["jana", "balbay", "yinyay", "nyajin"], EVIDENCE["balbay"]),
    row(42, "They saw the shooting star there.", "Jana binyu yinyay nyajin.", "jana binyu yinyay nyajin | 3pl.NOM shooting.star there see.PAST", "r283_3pl_sky_celestial_there_saw_binyu", ["jana", "binyu", "yinyay", "nyajin"], EVIDENCE["binyu"]),
    row(43, "They saw the star there.", "Jana dawar yinyay nyajin.", "jana dawar yinyay nyajin | 3pl.NOM star there see.PAST", "r283_3pl_sky_celestial_there_saw_dawar", ["jana", "dawar", "yinyay", "nyajin"], EVIDENCE["dawar"]),
    row(44, "They saw the sky there.", "Jana jiri yinyay nyajin.", "jana jiri yinyay nyajin | 3pl.NOM sky there see.PAST", "r283_3pl_sky_celestial_there_saw_jiri", ["jana", "jiri", "yinyay", "nyajin"], EVIDENCE["jiri"]),
    row(45, "They saw the rain there.", "Jana kaba yinyay nyajin.", "jana kaba yinyay nyajin | 3pl.NOM rain there see.PAST", "r283_3pl_sky_celestial_there_saw_kaba", ["jana", "kaba", "yinyay", "nyajin"], EVIDENCE["kaba"]),
    row(46, "They saw the sun there.", "Jana wungar yinyay nyajin.", "jana wungar yinyay nyajin | 3pl.NOM sun there see.PAST", "r283_3pl_sky_celestial_there_saw_wungar", ["jana", "wungar", "yinyay", "nyajin"], EVIDENCE["wungar"]),
    row(47, "They saw the mackerel sky there.", "Jana kurrinkurrin yinyay nyajin.", "jana kurrinkurrin yinyay nyajin | 3pl.NOM mackerel.sky there see.PAST", "r283_3pl_sky_celestial_there_saw_kurrinkurrin", ["jana", "kurrinkurrin", "yinyay", "nyajin"], EVIDENCE["kurrinkurrin"]),
    row(48, "They saw the morning star there.", "Jana kurrubijal yinyay nyajin.", "jana kurrubijal yinyay nyajin | 3pl.NOM morning.star there see.PAST", "r283_3pl_sky_celestial_there_saw_kurrubijal", ["jana", "kurrubijal", "yinyay", "nyajin"], EVIDENCE["kurrubijal"]),
    row(49, "They saw the cloud there.", "Jana ngurrban yinyay nyajin.", "jana ngurrban yinyay nyajin | 3pl.NOM cloud there see.PAST", "r283_3pl_sky_celestial_there_saw_ngurrban", ["jana", "ngurrban", "yinyay", "nyajin"], EVIDENCE["ngurrban"]),
    row(50, "They saw the rainbow there.", "Jana yiril yinyay nyajin.", "jana yiril yinyay nyajin | 3pl.NOM rainbow there see.PAST", "r283_3pl_sky_celestial_there_saw_yiril", ["jana", "yiril", "yinyay", "nyajin"], EVIDENCE["yiril"]),
]

EXPECTED_BANDS = [
    ("ngali", "yinyay"),
    ("ngaliny", "yaluy"),
    ("yubal", "yinyay"),
    ("yurra", "yaluy"),
    ("jana", "yinyay"),
]


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")
    kukus = [r[2] for r in ROWS]
    if len(set(kukus)) != len(kukus):
        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)
        lower_kuku = kuku.lower()
        lower_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\\.]|$)", lower_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.strip())}\b", lower_english)
        ]
        if denied_english:
            issues.append(f"{seq}: denied English drift {denied_english}")
        target_hits = [w for w in TARGET_ORDER if w in words]
        if len(target_hits) != 1:
            issues.append(f"{seq}: target hits {target_hits}")
        if len(words) != 4:
            issues.append(f"{seq}: expected 4 words, got {words}")
        if "nyajin" not in words or not lower_kuku.endswith(" nyajin."):
            issues.append(f"{seq}: missing final nyajin")
        if len([w for w in ("yaluy", "yinyay") if w in words]) != 1:
            issues.append(f"{seq}: demonstrative problem {words}")
        expected_pronoun, expected_demo = EXPECTED_BANDS[(seq - 1) // 10]
        if words[0] != expected_pronoun:
            issues.append(f"{seq}: expected pronoun {expected_pronoun}, got {words[0]}")
        if words[2] != expected_demo:
            issues.append(f"{seq}: expected demonstrative {expected_demo}, got {words[2]}")
        if words[1] not in TARGET_HEADS:
            issues.append(f"{seq}: word 2 is not a target {words[1]}")
        if words[3] != "nyajin":
            issues.append(f"{seq}: word 4 is not nyajin {words[3]}")
        if not frame.startswith("r283_"):
            issues.append(f"{seq}: frame not r283 {frame}")
    return issues


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 value=?)
            """,
            (word,),
        ).fetchone()[0]
        for word in words
    }


def main() -> int:
    issues = scan_static()
    if issues:
        for issue in issues:
            print(issue)
        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:
        existing = 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 existing:
            collisions.append((kuku, existing))
    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", "jana", "yaluy", "yinyay", "nyajin"])
    verified_before, words_before = db.execute(
        """
        SELECT COUNT(*), SUM(LENGTH(kuku)-LENGTH(REPLACE(kuku,' ',''))+1)
        FROM sentences
        WHERE status IN ('accepted','revised')
        """
    ).fetchone()

    notes = (
        "VISIBLE SKY/CELESTIAL NON-SINGULAR COMPLEMENTARY PAST PRONOUN PERCEPTION SWEEP AFTER RULE 282 "
        "(Rule 283). 50 under-review rows over balbay lightning, binyu shooting star, dawar star, jiri sky, "
        "kaba rain, wungar sun, kurrinkurrin mackerel sky, kurrubijal morning star, ngurrban cloud, and yiril "
        "rainbow with bare nominative ngali, ngaliny, yubal, yurra, and jana. Kija was rejected after exact "
        "duplicate pressure; wungar replaced it. Only bare visual past reference/perception rows are opened; "
        "moon/place-story, lightning-strike, death-spirit/death-omen, heaven/sky-mob/fine-day compounds, rain "
        "events, sun-time/hot-season compounds, rainbow story/snake/water-hole extensions, target case, pronoun "
        "case, demonstrative case, compounds, productive reduplication, nonpast/purposive/reduplicated perception "
        "drift, and support inflection remain closed."
    )
    cur = db.execute(
        "INSERT INTO batches(label, cheatsheet_version, guide_version, notes, created_at) VALUES(?,?,?,?,?)",
        (LABEL, "Rule 283 under review", "operator-guide-2026-07-09", 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, english, kuku, analysis, frame, tier, words_used, loans_used,
                evidence, "under_review", confidence,
                "project_approved_synthetic_pending_elder_verification", "claude", NOW, NOW,
            )
            for seq, english, kuku, analysis, frame, tier, words_used, loans_used, evidence, confidence in ROWS
        ],
    )
    record_event(db, batch_label=LABEL, phase="source", event_type="source-readback", actor="claude-main", detail="Reread dictionary source lines for final visible sky/celestial targets, including wungar as the kija replacement, and Patz non-singular pronoun, demonstrative, and nyaji-ny past support before authoring.", artifact_path=PROCESS_LOG, created_at=NOW)
    record_event(db, batch_label=LABEL, phase="planning", event_type="debt-sweep-scope", actor="claude-main", detail="Selected a visible sky/celestial non-singular complementary past pronoun perception sweep after Rule 282. Initial kija candidate was rejected after Batch 195 duplicate pressure; sourced wungar sun replaced it.", artifact_path=PROCESS_LOG, created_at=NOW)
    record_event(db, batch_label=LABEL, phase="preflight", event_type="coverage-audit", actor="claude-main", detail=f"Token-aware accepted/revised coverage before banking from words_used JSON: 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="claude-main", detail="Opposite-band Jana TARGET yaluy candidate collided with older sky/weather rows; complementary-band kija candidate found duplicate Jana kija yinyay nyajin. from Batch 195; final 50 Rule 283 surfaces with wungar 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="claude-main", detail="Static guard passed: 50 rows, one target each, bare non-singular nominative pronouns, bare yaluy/yinyay, final nyajin, no loans, no denied Kuku forms, no kija/moon/place-story/death-omen/strike/weather-event/time-compound drift.", command="python3 -m py_compile batch_scripts/bank_325.py && python3 -c \"import sys; sys.path.insert(0,'batch_scripts'); import bank_325; print(bank_325.scan_static())\"", output_excerpt="issues 0", artifact_path="batch_scripts/bank_325.py", created_at=NOW)
    record_event(db, batch_label=LABEL, phase="bank", event_type="bank-success", actor="claude-main", detail=f"Banked 50 Rule 283 rows as under_review. Verified total remains {verified_before}; Kuku word count remains {words_before}.", command="python3 batch_scripts/bank_325.py", output_excerpt=f"banked batch-325: 50 rows under_review; verified_before={verified_before}; kuku_words_before={words_before}", artifact_path=PROCESS_LOG, created_at=NOW)
    db.commit()
    print("banked batch-325: 50 rows under_review")
    return 0


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