#!/usr/bin/env python3
"""Bank batch-380: Rule 338 complementary singular/third-person reptile 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-380"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
PROCESS_LOG = "process_logs/batch-380-reptile-complementary-singular-third-past-perception-after-rule337-process.md"

TARGET_EVIDENCE = {
    "jalbil": "Dictionary yaml lines 7374-7386 give jalbil as a fauna-reptile noun whose primary sense is a lizard and whose prose adds colour, size, a mythological being, Snapper Island, and story material. Rule 338 admits only conservative jalbil lizard reference; colour, size, personification, island, cooking story, source, and events remain closed.",
    "kalkarrumbarr": "Dictionary yaml lines 12679-12689 give kalkarrumbarr as a fauna-reptile lizard noun with size and legend prose. Rule 338 admits lizard reference only; measurement, legend, role, behavior, source, possession, and events remain closed.",
    "kurmba-kurmba": "Dictionary yaml lines 16154-16169 give exact hyphenated kurmba-kurmba as a fauna-reptile slippery-lizard noun and also a mythological person with kin/marriage story. Rule 338 uses the whole lizard head only; free-base/productive reduplication, slipperiness predication, personification, kinship, marriage, place/story, source, and events remain closed.",
    "jimalili": "Dictionary yaml lines 9284-9294 give jimalili as a fauna-reptile mountain-lizard noun with a firestick-teaching cultural note. Rule 338 admits conservative jimalili lizard reference only; mountain habitat, teaching, firestick, origin/cultural story, source, and events remain closed.",
    "yuray": "Dictionary yaml lines 31016-31033 contain two exact noun-typed fauna-reptile yuray records, both licensing sea-snake/snake reference. Rule 338 uses conservative yuray snake without adjudicating duplicate-record identity, species, sea habitat, danger, poison, source, possession, or events.",
    "bakay": "Dictionary yaml lines 635-653 contain two exact noun-typed fauna-reptile bakay records licensing water-snake/snake reference and carrying colour/size detail. Rule 338 uses conservative bakay snake without collapsing records or adding size, colour, water habitat, danger, poison, source, possession, or events.",
    "kungkun": "Dictionary yaml lines 15748-15768 contain two exact noun-typed fauna-reptile kungkun records with carpet-snake/North-Queensland-python and brown-tree-snake labels. Rule 338 uses conservative kungkun snake only; duplicate identity, species resolution, tree habitat, colour, body, danger, source, possession, and events remain closed.",
    "bilbil-bilbil": "Dictionary yaml lines 2529-2542 give exact hyphenated bilbil-bilbil as a fully reduplicated fauna-reptile gecko noun. Rule 338 admits the whole gecko head only; free base, new productive rule, size, shelter, night, sound, feeding, habitat, behavior, source, and events remain closed.",
    "bajalji": "Dictionary yaml lines 387-409 contain two exact noun-typed fauna-reptile bajalji records: rock python with distribution/lore and poisonous snake. Rule 338 retains the established conservative bajalji python label without resolving duplicate identity or adding poison, colour/head, distribution/place, chasing lore, baldness/hat, danger, source, possession, or events.",
    "jabil": "Dictionary yaml lines 6929-6951 distinguish transitive verb jabil 'kick' from homophonous fauna-reptile noun jabil 'scrub lizard'. Rule 338 admits only the bare lizard noun O; kicking, verbal inflection, scrub habitat, catching, source, possession, and events remain closed.",
}

SUPPORT_EVIDENCE = (
    "Patz lines 2577-2584 source bare nominative ngayu, yundu, nyulu, and bula. Although one OCR table cell "
    "renders the third-plural form as iana, running examples at lines 1419, 1947, 2686, 2807-2811, 3240, and "
    "5460 attest Jana/jana, and dictionary yaml lines 7749-7759 independently record jana as the third-person "
    "plural personal pronoun 'they'. Patz lines 2834-2847 source Yalanji yaluy 'here' and yinyay 'there'; "
    "2021-2024 and 2568-2571 attest nyaji-ny 'see-PAST'; 3160-3162 define past -ny; and 4256-4265 license "
    "nominative pronoun A with bare absolutive O in sensory perception. Dictionary examples at 23876-23883 and "
    "23968-23976 contain running nyajin. Fresh Patz search found no standalone selected reptile noun: kungkun "
    "occurs only inside unrelated kungkunbunga- 'watch closely' at 5504/5520, so it supplies no snake-noun "
    "evidence. Rule 338 relies on direct dictionary noun records plus independently sourced constructional evidence."
)

TARGET_ORDER = ["jalbil", "kalkarrumbarr", "kurmba-kurmba", "jimalili", "yuray", "bakay", "kungkun", "bilbil-bilbil", "bajalji", "jabil"]
TARGET_LABELS = {"jalbil": "jalbil lizard", "kalkarrumbarr": "kalkarrumbarr lizard", "kurmba-kurmba": "kurmba-kurmba lizard", "jimalili": "jimalili lizard", "yuray": "yuray snake", "bakay": "bakay snake", "kungkun": "kungkun snake", "bilbil-bilbil": "bilbil-bilbil gecko", "bajalji": "bajalji python", "jabil": "jabil lizard"}
TARGET_GLOSSES = {"jalbil": "jalbil.lizard", "kalkarrumbarr": "kalkarrumbarr.lizard", "kurmba-kurmba": "kurmba-kurmba.lizard", "jimalili": "jimalili.lizard", "yuray": "yuray.snake", "bakay": "bakay.snake", "kungkun": "kungkun.snake", "bilbil-bilbil": "bilbil-bilbil.gecko", "bajalji": "bajalji.python", "jabil": "jabil.lizard"}
TARGET_CONFIDENCE = {"jalbil": "0.87", "kalkarrumbarr": "0.88", "kurmba-kurmba": "0.87", "jimalili": "0.89", "yuray": "0.89", "bakay": "0.88", "kungkun": "0.86", "bilbil-bilbil": "0.92", "bajalji": "0.84", "jabil": "0.88"}
EXPECTED_TARGET_COVERAGE = {"jalbil": 10, "kalkarrumbarr": 10, "kurmba-kurmba": 10, "jimalili": 11, "yuray": 11, "bakay": 12, "kungkun": 12, "bilbil-bilbil": 13, "bajalji": 14, "jabil": 15}
EXPECTED_SUPPORT_COVERAGE = {"ngayu": 1451, "yundu": 1047, "nyulu": 722, "bula": 518, "jana": 1223, "yaluy": 4332, "yinyay": 4504, "nyajin": 1950}
FRAME_SPECS = [
    ("ngayu", "yaluy", "I saw", "here", "1sg"),
    ("yundu", "yinyay", "You saw", "there", "2sg"),
    ("nyulu", "yaluy", "He saw", "here", "3sg"),
    ("bula", "yinyay", "The two of them saw", "there", "3du"),
    ("jana", "yaluy", "They saw", "here", "3pl"),
]

DENY_KUKU = {"ngali", "ngaliny", "yubal", "yurra", "nganjin", "ngana", "yulu", "iana", "bilbil", "kurmba", "yalay", "yala", "yanyu", "yinya", "nyajil", "nyaji-l", "nyaji-nka", "nyaji-l-nyaji", "milka", "baykal", "jalngkay"}
DENY_ENGLISH = ("greenish", "black colour", "inch", "feet long", "myth", "legend", "person", "island", "cook", "husband", "sister", "marriage", "firestick", "teach", "water habitat", "sea habitat", "tree habitat", "brown", "yellow", "white head", "poison", "danger", "chase", "bald", "hat", "kick", "scrub habitat", "catch", "source", "possess", "event", "productive reduplication", "free base")


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 jalbil lizard here.", "Ngayu jalbil yaluy nyajin.", "ngayu jalbil yaluy nyajin | 1sg.NOM jalbil.lizard here see.PST", "r338_1sg_here_reptile_saw_jalbil", ["ngayu", "jalbil", "yaluy", "nyajin"]),
    row(2, "I saw the kalkarrumbarr lizard here.", "Ngayu kalkarrumbarr yaluy nyajin.", "ngayu kalkarrumbarr yaluy nyajin | 1sg.NOM kalkarrumbarr.lizard here see.PST", "r338_1sg_here_reptile_saw_kalkarrumbarr", ["ngayu", "kalkarrumbarr", "yaluy", "nyajin"]),
    row(3, "I saw the kurmba-kurmba lizard here.", "Ngayu kurmba-kurmba yaluy nyajin.", "ngayu kurmba-kurmba yaluy nyajin | 1sg.NOM kurmba-kurmba.lizard here see.PST", "r338_1sg_here_reptile_saw_kurmba_kurmba", ["ngayu", "kurmba-kurmba", "yaluy", "nyajin"]),
    row(4, "I saw the jimalili lizard here.", "Ngayu jimalili yaluy nyajin.", "ngayu jimalili yaluy nyajin | 1sg.NOM jimalili.lizard here see.PST", "r338_1sg_here_reptile_saw_jimalili", ["ngayu", "jimalili", "yaluy", "nyajin"]),
    row(5, "I saw the yuray snake here.", "Ngayu yuray yaluy nyajin.", "ngayu yuray yaluy nyajin | 1sg.NOM yuray.snake here see.PST", "r338_1sg_here_reptile_saw_yuray", ["ngayu", "yuray", "yaluy", "nyajin"]),
    row(6, "I saw the bakay snake here.", "Ngayu bakay yaluy nyajin.", "ngayu bakay yaluy nyajin | 1sg.NOM bakay.snake here see.PST", "r338_1sg_here_reptile_saw_bakay", ["ngayu", "bakay", "yaluy", "nyajin"]),
    row(7, "I saw the kungkun snake here.", "Ngayu kungkun yaluy nyajin.", "ngayu kungkun yaluy nyajin | 1sg.NOM kungkun.snake here see.PST", "r338_1sg_here_reptile_saw_kungkun", ["ngayu", "kungkun", "yaluy", "nyajin"]),
    row(8, "I saw the bilbil-bilbil gecko here.", "Ngayu bilbil-bilbil yaluy nyajin.", "ngayu bilbil-bilbil yaluy nyajin | 1sg.NOM bilbil-bilbil.gecko here see.PST", "r338_1sg_here_reptile_saw_bilbil_bilbil", ["ngayu", "bilbil-bilbil", "yaluy", "nyajin"]),
    row(9, "I saw the bajalji python here.", "Ngayu bajalji yaluy nyajin.", "ngayu bajalji yaluy nyajin | 1sg.NOM bajalji.python here see.PST", "r338_1sg_here_reptile_saw_bajalji", ["ngayu", "bajalji", "yaluy", "nyajin"]),
    row(10, "I saw the jabil lizard here.", "Ngayu jabil yaluy nyajin.", "ngayu jabil yaluy nyajin | 1sg.NOM jabil.lizard here see.PST", "r338_1sg_here_reptile_saw_jabil", ["ngayu", "jabil", "yaluy", "nyajin"]),
    row(11, "You saw the jalbil lizard there.", "Yundu jalbil yinyay nyajin.", "yundu jalbil yinyay nyajin | 2sg.NOM jalbil.lizard there see.PST", "r338_2sg_there_reptile_saw_jalbil", ["yundu", "jalbil", "yinyay", "nyajin"]),
    row(12, "You saw the kalkarrumbarr lizard there.", "Yundu kalkarrumbarr yinyay nyajin.", "yundu kalkarrumbarr yinyay nyajin | 2sg.NOM kalkarrumbarr.lizard there see.PST", "r338_2sg_there_reptile_saw_kalkarrumbarr", ["yundu", "kalkarrumbarr", "yinyay", "nyajin"]),
    row(13, "You saw the kurmba-kurmba lizard there.", "Yundu kurmba-kurmba yinyay nyajin.", "yundu kurmba-kurmba yinyay nyajin | 2sg.NOM kurmba-kurmba.lizard there see.PST", "r338_2sg_there_reptile_saw_kurmba_kurmba", ["yundu", "kurmba-kurmba", "yinyay", "nyajin"]),
    row(14, "You saw the jimalili lizard there.", "Yundu jimalili yinyay nyajin.", "yundu jimalili yinyay nyajin | 2sg.NOM jimalili.lizard there see.PST", "r338_2sg_there_reptile_saw_jimalili", ["yundu", "jimalili", "yinyay", "nyajin"]),
    row(15, "You saw the yuray snake there.", "Yundu yuray yinyay nyajin.", "yundu yuray yinyay nyajin | 2sg.NOM yuray.snake there see.PST", "r338_2sg_there_reptile_saw_yuray", ["yundu", "yuray", "yinyay", "nyajin"]),
    row(16, "You saw the bakay snake there.", "Yundu bakay yinyay nyajin.", "yundu bakay yinyay nyajin | 2sg.NOM bakay.snake there see.PST", "r338_2sg_there_reptile_saw_bakay", ["yundu", "bakay", "yinyay", "nyajin"]),
    row(17, "You saw the kungkun snake there.", "Yundu kungkun yinyay nyajin.", "yundu kungkun yinyay nyajin | 2sg.NOM kungkun.snake there see.PST", "r338_2sg_there_reptile_saw_kungkun", ["yundu", "kungkun", "yinyay", "nyajin"]),
    row(18, "You saw the bilbil-bilbil gecko there.", "Yundu bilbil-bilbil yinyay nyajin.", "yundu bilbil-bilbil yinyay nyajin | 2sg.NOM bilbil-bilbil.gecko there see.PST", "r338_2sg_there_reptile_saw_bilbil_bilbil", ["yundu", "bilbil-bilbil", "yinyay", "nyajin"]),
    row(19, "You saw the bajalji python there.", "Yundu bajalji yinyay nyajin.", "yundu bajalji yinyay nyajin | 2sg.NOM bajalji.python there see.PST", "r338_2sg_there_reptile_saw_bajalji", ["yundu", "bajalji", "yinyay", "nyajin"]),
    row(20, "You saw the jabil lizard there.", "Yundu jabil yinyay nyajin.", "yundu jabil yinyay nyajin | 2sg.NOM jabil.lizard there see.PST", "r338_2sg_there_reptile_saw_jabil", ["yundu", "jabil", "yinyay", "nyajin"]),
    row(21, "He saw the jalbil lizard here.", "Nyulu jalbil yaluy nyajin.", "nyulu jalbil yaluy nyajin | 3sg.NOM jalbil.lizard here see.PST", "r338_3sg_here_reptile_saw_jalbil", ["nyulu", "jalbil", "yaluy", "nyajin"]),
    row(22, "He saw the kalkarrumbarr lizard here.", "Nyulu kalkarrumbarr yaluy nyajin.", "nyulu kalkarrumbarr yaluy nyajin | 3sg.NOM kalkarrumbarr.lizard here see.PST", "r338_3sg_here_reptile_saw_kalkarrumbarr", ["nyulu", "kalkarrumbarr", "yaluy", "nyajin"]),
    row(23, "He saw the kurmba-kurmba lizard here.", "Nyulu kurmba-kurmba yaluy nyajin.", "nyulu kurmba-kurmba yaluy nyajin | 3sg.NOM kurmba-kurmba.lizard here see.PST", "r338_3sg_here_reptile_saw_kurmba_kurmba", ["nyulu", "kurmba-kurmba", "yaluy", "nyajin"]),
    row(24, "He saw the jimalili lizard here.", "Nyulu jimalili yaluy nyajin.", "nyulu jimalili yaluy nyajin | 3sg.NOM jimalili.lizard here see.PST", "r338_3sg_here_reptile_saw_jimalili", ["nyulu", "jimalili", "yaluy", "nyajin"]),
    row(25, "He saw the yuray snake here.", "Nyulu yuray yaluy nyajin.", "nyulu yuray yaluy nyajin | 3sg.NOM yuray.snake here see.PST", "r338_3sg_here_reptile_saw_yuray", ["nyulu", "yuray", "yaluy", "nyajin"]),
    row(26, "He saw the bakay snake here.", "Nyulu bakay yaluy nyajin.", "nyulu bakay yaluy nyajin | 3sg.NOM bakay.snake here see.PST", "r338_3sg_here_reptile_saw_bakay", ["nyulu", "bakay", "yaluy", "nyajin"]),
    row(27, "He saw the kungkun snake here.", "Nyulu kungkun yaluy nyajin.", "nyulu kungkun yaluy nyajin | 3sg.NOM kungkun.snake here see.PST", "r338_3sg_here_reptile_saw_kungkun", ["nyulu", "kungkun", "yaluy", "nyajin"]),
    row(28, "He saw the bilbil-bilbil gecko here.", "Nyulu bilbil-bilbil yaluy nyajin.", "nyulu bilbil-bilbil yaluy nyajin | 3sg.NOM bilbil-bilbil.gecko here see.PST", "r338_3sg_here_reptile_saw_bilbil_bilbil", ["nyulu", "bilbil-bilbil", "yaluy", "nyajin"]),
    row(29, "He saw the bajalji python here.", "Nyulu bajalji yaluy nyajin.", "nyulu bajalji yaluy nyajin | 3sg.NOM bajalji.python here see.PST", "r338_3sg_here_reptile_saw_bajalji", ["nyulu", "bajalji", "yaluy", "nyajin"]),
    row(30, "He saw the jabil lizard here.", "Nyulu jabil yaluy nyajin.", "nyulu jabil yaluy nyajin | 3sg.NOM jabil.lizard here see.PST", "r338_3sg_here_reptile_saw_jabil", ["nyulu", "jabil", "yaluy", "nyajin"]),
    row(31, "The two of them saw the jalbil lizard there.", "Bula jalbil yinyay nyajin.", "bula jalbil yinyay nyajin | 3du.NOM jalbil.lizard there see.PST", "r338_3du_there_reptile_saw_jalbil", ["bula", "jalbil", "yinyay", "nyajin"]),
    row(32, "The two of them saw the kalkarrumbarr lizard there.", "Bula kalkarrumbarr yinyay nyajin.", "bula kalkarrumbarr yinyay nyajin | 3du.NOM kalkarrumbarr.lizard there see.PST", "r338_3du_there_reptile_saw_kalkarrumbarr", ["bula", "kalkarrumbarr", "yinyay", "nyajin"]),
    row(33, "The two of them saw the kurmba-kurmba lizard there.", "Bula kurmba-kurmba yinyay nyajin.", "bula kurmba-kurmba yinyay nyajin | 3du.NOM kurmba-kurmba.lizard there see.PST", "r338_3du_there_reptile_saw_kurmba_kurmba", ["bula", "kurmba-kurmba", "yinyay", "nyajin"]),
    row(34, "The two of them saw the jimalili lizard there.", "Bula jimalili yinyay nyajin.", "bula jimalili yinyay nyajin | 3du.NOM jimalili.lizard there see.PST", "r338_3du_there_reptile_saw_jimalili", ["bula", "jimalili", "yinyay", "nyajin"]),
    row(35, "The two of them saw the yuray snake there.", "Bula yuray yinyay nyajin.", "bula yuray yinyay nyajin | 3du.NOM yuray.snake there see.PST", "r338_3du_there_reptile_saw_yuray", ["bula", "yuray", "yinyay", "nyajin"]),
    row(36, "The two of them saw the bakay snake there.", "Bula bakay yinyay nyajin.", "bula bakay yinyay nyajin | 3du.NOM bakay.snake there see.PST", "r338_3du_there_reptile_saw_bakay", ["bula", "bakay", "yinyay", "nyajin"]),
    row(37, "The two of them saw the kungkun snake there.", "Bula kungkun yinyay nyajin.", "bula kungkun yinyay nyajin | 3du.NOM kungkun.snake there see.PST", "r338_3du_there_reptile_saw_kungkun", ["bula", "kungkun", "yinyay", "nyajin"]),
    row(38, "The two of them saw the bilbil-bilbil gecko there.", "Bula bilbil-bilbil yinyay nyajin.", "bula bilbil-bilbil yinyay nyajin | 3du.NOM bilbil-bilbil.gecko there see.PST", "r338_3du_there_reptile_saw_bilbil_bilbil", ["bula", "bilbil-bilbil", "yinyay", "nyajin"]),
    row(39, "The two of them saw the bajalji python there.", "Bula bajalji yinyay nyajin.", "bula bajalji yinyay nyajin | 3du.NOM bajalji.python there see.PST", "r338_3du_there_reptile_saw_bajalji", ["bula", "bajalji", "yinyay", "nyajin"]),
    row(40, "The two of them saw the jabil lizard there.", "Bula jabil yinyay nyajin.", "bula jabil yinyay nyajin | 3du.NOM jabil.lizard there see.PST", "r338_3du_there_reptile_saw_jabil", ["bula", "jabil", "yinyay", "nyajin"]),
    row(41, "They saw the jalbil lizard here.", "Jana jalbil yaluy nyajin.", "jana jalbil yaluy nyajin | 3pl.NOM jalbil.lizard here see.PST", "r338_3pl_here_reptile_saw_jalbil", ["jana", "jalbil", "yaluy", "nyajin"]),
    row(42, "They saw the kalkarrumbarr lizard here.", "Jana kalkarrumbarr yaluy nyajin.", "jana kalkarrumbarr yaluy nyajin | 3pl.NOM kalkarrumbarr.lizard here see.PST", "r338_3pl_here_reptile_saw_kalkarrumbarr", ["jana", "kalkarrumbarr", "yaluy", "nyajin"]),
    row(43, "They saw the kurmba-kurmba lizard here.", "Jana kurmba-kurmba yaluy nyajin.", "jana kurmba-kurmba yaluy nyajin | 3pl.NOM kurmba-kurmba.lizard here see.PST", "r338_3pl_here_reptile_saw_kurmba_kurmba", ["jana", "kurmba-kurmba", "yaluy", "nyajin"]),
    row(44, "They saw the jimalili lizard here.", "Jana jimalili yaluy nyajin.", "jana jimalili yaluy nyajin | 3pl.NOM jimalili.lizard here see.PST", "r338_3pl_here_reptile_saw_jimalili", ["jana", "jimalili", "yaluy", "nyajin"]),
    row(45, "They saw the yuray snake here.", "Jana yuray yaluy nyajin.", "jana yuray yaluy nyajin | 3pl.NOM yuray.snake here see.PST", "r338_3pl_here_reptile_saw_yuray", ["jana", "yuray", "yaluy", "nyajin"]),
    row(46, "They saw the bakay snake here.", "Jana bakay yaluy nyajin.", "jana bakay yaluy nyajin | 3pl.NOM bakay.snake here see.PST", "r338_3pl_here_reptile_saw_bakay", ["jana", "bakay", "yaluy", "nyajin"]),
    row(47, "They saw the kungkun snake here.", "Jana kungkun yaluy nyajin.", "jana kungkun yaluy nyajin | 3pl.NOM kungkun.snake here see.PST", "r338_3pl_here_reptile_saw_kungkun", ["jana", "kungkun", "yaluy", "nyajin"]),
    row(48, "They saw the bilbil-bilbil gecko here.", "Jana bilbil-bilbil yaluy nyajin.", "jana bilbil-bilbil yaluy nyajin | 3pl.NOM bilbil-bilbil.gecko here see.PST", "r338_3pl_here_reptile_saw_bilbil_bilbil", ["jana", "bilbil-bilbil", "yaluy", "nyajin"]),
    row(49, "They saw the bajalji python here.", "Jana bajalji yaluy nyajin.", "jana bajalji yaluy nyajin | 3pl.NOM bajalji.python here see.PST", "r338_3pl_here_reptile_saw_bajalji", ["jana", "bajalji", "yaluy", "nyajin"]),
    row(50, "They saw the jabil lizard here.", "Jana jabil yaluy nyajin.", "jana jabil yaluy nyajin | 3pl.NOM jabil.lizard here see.PST", "r338_3pl_here_reptile_saw_jabil", ["jana", "jabil", "yaluy", "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")
    if len({r[2] for r in ROWS}) != 50: issues.append("duplicate Kuku surface")
    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=FRAME_SPECS[band]
        ek=f"{pronoun.capitalize()} {target} {demo} nyajin."; ee=f"{prefix} the {TARGET_LABELS[target]} {location}."; ea=f"{pronoun} {target} {demo} nyajin | {person}.NOM {TARGET_GLOSSES[target]} {location} see.PST"
        if loans: issues.append(f"{seq}: loans {loans}")
        denied=sorted({w for w in DENY_KUKU if re.search(rf"(^|\s){re.escape(w)}([\s\.]|$)",kuku.lower())})
        if denied: issues.append(f"{seq}: denied Kuku {denied}")
        de=[x for x in DENY_ENGLISH if re.search(rf"\b{re.escape(x)}\b",english.lower())]
        if de: issues.append(f"{seq}: English drift {de}")
        if kuku!=ek: issues.append(f"{seq}: Kuku mismatch")
        if english!=ee: issues.append(f"{seq}: English mismatch")
        if analysis!=ea: issues.append(f"{seq}: analysis mismatch")
        if words!=[pronoun,target,demo,"nyajin"]: issues.append(f"{seq}: words mismatch")
        if kuku.lower().rstrip(".")!=" ".join(words): issues.append(f"{seq}: surface/words mismatch")
        if not frame.startswith("r338_"): issues.append(f"{seq}: frame mismatch")
        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} exists")
    tc=count_words(db,TARGET_ORDER); sc=count_words(db,list(EXPECTED_SUPPORT_COVERAGE))
    if tc!=EXPECTED_TARGET_COVERAGE: raise SystemExit(f"target coverage changed: {tc}")
    if sc!=EXPECTED_SUPPORT_COVERAGE: raise SystemExit(f"support coverage changed: {sc}")
    selected=[]
    selected_specs=[("ngayu","yaluy"),("yundu","yinyay"),("nyulu","yaluy"),("bula","yinyay"),("jana","yaluy")]
    for p,de in selected_specs:
        for t in TARGET_ORDER:
            surf=f"{p.capitalize()} {t} {de} nyajin."
            hits=db.execute("SELECT b.label,s.seq FROM sentences s JOIN batches b ON b.id=s.batch_id WHERE lower(s.kuku)=lower(?) AND s.status!='rejected' ORDER BY b.label,s.seq",(surf,)).fetchall()
            if hits: selected.append((surf,hits))
    if selected: raise SystemExit(f"selected collisions: {selected}")
    inverse_mismatches=[]
    inverse_specs=[("ngayu","yinyay"),("yundu","yaluy"),("nyulu","yinyay"),("bula","yaluy"),("jana","yinyay")]
    for band,(p,de) in enumerate(inverse_specs):
        for offset,t in enumerate(TARGET_ORDER):
            surf=f"{p.capitalize()} {t} {de} nyajin."
            hits=db.execute("SELECT b.label,s.seq FROM sentences s JOIN batches b ON b.id=s.batch_id WHERE lower(s.kuku)=lower(?) AND s.status!='rejected' ORDER BY b.label,s.seq",(surf,)).fetchall()
            expected=[("batch-361",band*10+offset+1)]
            if hits!=expected: inverse_mismatches.append((surf,hits,expected))
    if inverse_mismatches: raise SystemExit(f"inverse complement changed: {inverse_mismatches}")
    verified,words=db.execute("SELECT COUNT(*),SUM(LENGTH(kuku)-LENGTH(REPLACE(kuku,' ',''))+1) FROM sentences WHERE status IN ('accepted','revised')").fetchone()
    if (verified,words)!=(19047,131547): raise SystemExit(f"baseline changed {verified}/{words}")
    notes=("REPTILE COMPLEMENTARY SINGULAR/THIRD-PERSON PAST PERCEPTION AFTER RULE 337 (Rule 338). 50 under-review rows over the Rule 319/337 low-coverage reptile set. Duplicate exact records for yuray, bakay, kungkun, and bajalji remain uncollapsed; noun jabil remains distinct from kick verb; myth/lore, colour, size, habitat, poison/danger, species resolution, reduplication, kin/marriage, firestick, place/story, source, possession, and events remain closed. The selected ngayu/yundu/nyulu/bula/jana orientation is empty and exactly complements Batch 361 / Rule 319. Three-here/two-there reduces deictic gap 172->162.")
    cur=db.execute("INSERT INTO batches(label,cheatsheet_version,guide_version,notes,created_at) VALUES(?,?,?,?,?)",(LABEL,"Rule 338 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])
    events=[
        ("source","source-readback","Reread all selected, duplicate, and homonymous dictionary records; Patz pronoun/local/past/perception passages; jana running examples; dictionary running nyajin; and the target search, whose only apparent hit is unrelated verb kungkunbunga- rather than snake noun kungkun."),
        ("planning","record-sense-audit","Recorded duplicate exact yuray/bakay/kungkun/bajalji records, jabil noun/verb homonym, reduplicated heads, and all myth/lore/property/poison/habitat exclusions without collapsing them."),
        ("planning","construction-gap-audit","Exact five-pronoun x ten-target x two-deictic matrix has 50 occupied inverse cells, all exactly Batch 361 / Rule 319, and 50 empty selected complementary cells."),
        ("planning","deictic-balance-audit","Before banking yaluy=4332 and yinyay=4504, gap 172; selected three-here/two-there projects 162, while the hypothetical inverse projects 182."),
        ("preflight","coverage-audit",f"Coverage before banking: targets={tc}; support={sc}."),
        ("preflight","duplicate-preflight","Selected 50 surfaces are internally unique and collision-free; inverse 50 map one-for-one to Batch 361 and are deliberately excluded."),
        ("preflight","static-guard-pass","50 explicit rows; exact singular/third-person complementary contracts; conservative creature labels; no record collapse, homonym, lore/property/event, loan, case, or support drift."),
    ]
    for phase,etype,detail in events: record_event(db,batch_label=LABEL,phase=phase,event_type=etype,actor="codex",detail=detail,artifact_path=PROCESS_LOG,created_at=NOW)
    record_event(db,batch_label=LABEL,phase="bank",event_type="bank-success",actor="codex",detail=f"Banked 50 Rule 338 rows under_review; verified remains {verified}; words {words}.",command="python3 batch_scripts/bank_380.py",output_excerpt="50 under_review",artifact_path=PROCESS_LOG,created_at=NOW)
    db.commit();print("banked batch-380: 50 rows under_review");return 0


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


