#!/usr/bin/env python3
"""Bank batch-219: Rule 177 native mammal reference lexical expansion."""

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-219"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
PROCESS_LOG = "process_logs/batch-219-native-mammal-reference-lexical-expansion-after-rule176-process.md"

TARGET_HEADS = {
    "bimbarrbay": "scrub wallaby",
    "durrkin": "white-tailed rat",
    "jibul": "large bat",
    "kirbaji": "dugong",
    "jumar": "little wallaby",
    "murrumu": "dingo",
    "nyarrkali": "black kangaroo",
    "wambiji": "platypus",
    "waykal": "native cat",
    "yalmburrajaka": "whale",
}
PRONOUN_A = {"ngayu", "yundu", "jana", "ngana"}
DENY_KUKU = {
    "biki", "bikibiki", "buji", "danda", "kaya", "kaya-kaya", "yarraman", "bala", "jakal",
    "jarrabina", "kambi", "kukur", "kulngu", "mali", "mayarriji", "murral", "murramu",
    "ngamu-murramu", "ngangkin", "ngumbi", "yawa", "darrba",
}
DENY_ENGLISH = (
    "loan", "pig", "horse", "dog", "cat loan", "pussy", "clothing", "iron", "mother", "food", "edible",
    "eat", "eats", "ate", "eaten", "hunt", "hunting", "catch", "catches", "caught", "trap", "trapped",
    "kill", "killed", "bite", "bit", "spear", "speared", "totem", "moiety", "story", "story-site",
    "myth", "mythological", "place", "place-name", "cave", "kangkaji", "kaway", "kurrbi", "skin",
    "body-part", "tail", "sinew", "gristle", "blood vessel", "habitat", "tree-climbing", "climb",
    "river", "sea", "ocean", "water", "country", "ceremony", "introduced", "post-contact", "use", "uses",
    "made", "material", "source", "bone", "meat", "plural", "many",
)


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, 4, js(words), js([]), evidence, "0.84")


ROWS = [
    row(1, "The scrub wallaby is here.", "Bimbarrbay yaluy.", "bimbarrbay yaluy | scrub.wallaby here", "r177_deictic_bimbarrbay_here", ["bimbarrbay", "yaluy"], "Rule 177 admits bimbarrbay as scrub wallaby; ordinary reference only."),
    row(2, "The white-tailed rat is here.", "Durrkin yaluy.", "durrkin yaluy | white-tailed.rat here", "r177_deictic_durrkin_here", ["durrkin", "yaluy"], "Rule 177 admits durrkin as white-tailed rat; ordinary reference only."),
    row(3, "The large bat is here.", "Jibul yaluy.", "jibul yaluy | large.bat here", "r177_deictic_jibul_here", ["jibul", "yaluy"], "Rule 177 admits jibul as large bat; cave, place-name, and story-site prose remains closed."),
    row(4, "The dugong is here.", "Kirbaji yaluy.", "kirbaji yaluy | dugong here", "r177_deictic_kirbaji_here", ["kirbaji", "yaluy"], "Rule 177 admits kirbaji as dugong; marine-event prose not imported."),
    row(5, "The little wallaby is here.", "Jumar yaluy.", "jumar yaluy | little.wallaby here", "r177_deictic_jumar_here", ["jumar", "yaluy"], "Rule 177 admits jumar as little wallaby; size is lexical in the English gloss only."),
    row(6, "The dingo is here.", "Murrumu yaluy.", "murrumu yaluy | dingo here", "r177_deictic_murrumu_here", ["murrumu", "yaluy"], "Rule 177 admits murrumu as dingo; dog/loan and mother-compound drift remain closed."),
    row(7, "The black kangaroo is here.", "Nyarrkali yaluy.", "nyarrkali yaluy | black.kangaroo here", "r177_deictic_nyarrkali_here", ["nyarrkali", "yaluy"], "Rule 177 admits nyarrkali as black kangaroo; no colour-predicate row."),
    row(8, "The platypus is here.", "Wambiji yaluy.", "wambiji yaluy | platypus here", "r177_deictic_wambiji_here", ["wambiji", "yaluy"], "Rule 177 admits wambiji as platypus; no water/habitat row."),
    row(9, "The native cat is here.", "Waykal yaluy.", "waykal yaluy | native.cat here", "r177_deictic_waykal_here", ["waykal", "yaluy"], "Rule 177 admits waykal as native cat; not the cat-loan buji."),
    row(10, "The whale is here.", "Yalmburrajaka yaluy.", "yalmburrajaka yaluy | whale here", "r177_deictic_yalmburrajaka_here", ["yalmburrajaka", "yaluy"], "Rule 177 admits yalmburrajaka as whale; no sea/ocean event row."),
    row(11, "I see the scrub wallaby.", "Ngayu bimbarrbay nyajil.", "ngayu bimbarrbay nyaji-l | I scrub.wallaby see-NONPAST", "r177_present_i_bimbarrbay", ["ngayu", "bimbarrbay", "nyaji-l"], "First-person present perception; target object bare."),
    row(12, "I see the white-tailed rat.", "Ngayu durrkin nyajil.", "ngayu durrkin nyaji-l | I white-tailed.rat see-NONPAST", "r177_present_i_durrkin", ["ngayu", "durrkin", "nyaji-l"], "First-person present perception; target object bare."),
    row(13, "I see the large bat.", "Ngayu jibul nyajil.", "ngayu jibul nyaji-l | I large.bat see-NONPAST", "r177_present_i_jibul", ["ngayu", "jibul", "nyaji-l"], "First-person present perception; cave/place-name sense not imported."),
    row(14, "I see the dugong.", "Ngayu kirbaji nyajil.", "ngayu kirbaji nyaji-l | I dugong see-NONPAST", "r177_present_i_kirbaji", ["ngayu", "kirbaji", "nyaji-l"], "First-person present perception; target object bare."),
    row(15, "I see the little wallaby.", "Ngayu jumar nyajil.", "ngayu jumar nyaji-l | I little.wallaby see-NONPAST", "r177_present_i_jumar", ["ngayu", "jumar", "nyaji-l"], "First-person present perception; target object bare."),
    row(16, "I see the dingo.", "Ngayu murrumu nyajil.", "ngayu murrumu nyaji-l | I dingo see-NONPAST", "r177_present_i_murrumu", ["ngayu", "murrumu", "nyaji-l"], "First-person present perception; dog/loan drift closed."),
    row(17, "I see the black kangaroo.", "Ngayu nyarrkali nyajil.", "ngayu nyarrkali nyaji-l | I black.kangaroo see-NONPAST", "r177_present_i_nyarrkali", ["ngayu", "nyarrkali", "nyaji-l"], "First-person present perception; selected mammal sense only."),
    row(18, "I see the platypus.", "Ngayu wambiji nyajil.", "ngayu wambiji nyaji-l | I platypus see-NONPAST", "r177_present_i_wambiji", ["ngayu", "wambiji", "nyaji-l"], "First-person present perception; habitat prose not imported."),
    row(19, "I see the native cat.", "Ngayu waykal nyajil.", "ngayu waykal nyaji-l | I native.cat see-NONPAST", "r177_present_i_waykal", ["ngayu", "waykal", "nyaji-l"], "First-person present perception; native cat as dictionary head only."),
    row(20, "I see the whale.", "Ngayu yalmburrajaka nyajil.", "ngayu yalmburrajaka nyaji-l | I whale see-NONPAST", "r177_present_i_yalmburrajaka", ["ngayu", "yalmburrajaka", "nyaji-l"], "First-person present perception; marine-event prose not imported."),
    row(21, "You see the scrub wallaby there.", "Yundu bimbarrbay yinyay nyajil.", "yundu bimbarrbay yinyay nyaji-l | you scrub.wallaby there see-NONPAST", "r177_present_you_bimbarrbay_there", ["yundu", "bimbarrbay", "yinyay", "nyaji-l"], "Second-person present perception with yinyay support."),
    row(22, "You see the white-tailed rat there.", "Yundu durrkin yinyay nyajil.", "yundu durrkin yinyay nyaji-l | you white-tailed.rat there see-NONPAST", "r177_present_you_durrkin_there", ["yundu", "durrkin", "yinyay", "nyaji-l"], "Second-person present perception with yinyay support."),
    row(23, "You see the large bat there.", "Yundu jibul yinyay nyajil.", "yundu jibul yinyay nyaji-l | you large.bat there see-NONPAST", "r177_present_you_jibul_there", ["yundu", "jibul", "yinyay", "nyaji-l"], "Second-person present perception; place/story sense closed."),
    row(24, "You see the dugong there.", "Yundu kirbaji yinyay nyajil.", "yundu kirbaji yinyay nyaji-l | you dugong there see-NONPAST", "r177_present_you_kirbaji_there", ["yundu", "kirbaji", "yinyay", "nyaji-l"], "Second-person present perception with yinyay support."),
    row(25, "You see the little wallaby there.", "Yundu jumar yinyay nyajil.", "yundu jumar yinyay nyaji-l | you little.wallaby there see-NONPAST", "r177_present_you_jumar_there", ["yundu", "jumar", "yinyay", "nyaji-l"], "Second-person present perception with yinyay support."),
    row(26, "You see the dingo there.", "Yundu murrumu yinyay nyajil.", "yundu murrumu yinyay nyaji-l | you dingo there see-NONPAST", "r177_present_you_murrumu_there", ["yundu", "murrumu", "yinyay", "nyaji-l"], "Second-person present perception; dog/loan drift closed."),
    row(27, "You see the black kangaroo there.", "Yundu nyarrkali yinyay nyajil.", "yundu nyarrkali yinyay nyaji-l | you black.kangaroo there see-NONPAST", "r177_present_you_nyarrkali_there", ["yundu", "nyarrkali", "yinyay", "nyaji-l"], "Second-person present perception with yinyay support."),
    row(28, "You see the platypus there.", "Yundu wambiji yinyay nyajil.", "yundu wambiji yinyay nyaji-l | you platypus there see-NONPAST", "r177_present_you_wambiji_there", ["yundu", "wambiji", "yinyay", "nyaji-l"], "Second-person present perception with yinyay support."),
    row(29, "You see the native cat there.", "Yundu waykal yinyay nyajil.", "yundu waykal yinyay nyaji-l | you native.cat there see-NONPAST", "r177_present_you_waykal_there", ["yundu", "waykal", "yinyay", "nyaji-l"], "Second-person present perception; native cat as dictionary head only."),
    row(30, "You see the whale there.", "Yundu yalmburrajaka yinyay nyajil.", "yundu yalmburrajaka yinyay nyaji-l | you whale there see-NONPAST", "r177_present_you_yalmburrajaka_there", ["yundu", "yalmburrajaka", "yinyay", "nyaji-l"], "Second-person present perception; sea/ocean event prose closed."),
    row(31, "They saw the scrub wallaby there.", "Jana bimbarrbay yinyay nyajin.", "jana bimbarrbay yinyay nyaji-ny | they scrub.wallaby there see-PAST", "r177_past_they_bimbarrbay_there", ["jana", "bimbarrbay", "yinyay", "nyaji-l"], "Third-person plural past perception; target object bare."),
    row(32, "They saw the white-tailed rat there.", "Jana durrkin yinyay nyajin.", "jana durrkin yinyay nyaji-ny | they white-tailed.rat there see-PAST", "r177_past_they_durrkin_there", ["jana", "durrkin", "yinyay", "nyaji-l"], "Third-person plural past perception; target object bare."),
    row(33, "They saw the large bat there.", "Jana jibul yinyay nyajin.", "jana jibul yinyay nyaji-ny | they large.bat there see-PAST", "r177_past_they_jibul_there", ["jana", "jibul", "yinyay", "nyaji-l"], "Third-person plural past perception; cave/place/story sense closed."),
    row(34, "They saw the dugong there.", "Jana kirbaji yinyay nyajin.", "jana kirbaji yinyay nyaji-ny | they dugong there see-PAST", "r177_past_they_kirbaji_there", ["jana", "kirbaji", "yinyay", "nyaji-l"], "Third-person plural past perception; target object bare."),
    row(35, "They saw the little wallaby there.", "Jana jumar yinyay nyajin.", "jana jumar yinyay nyaji-ny | they little.wallaby there see-PAST", "r177_past_they_jumar_there", ["jana", "jumar", "yinyay", "nyaji-l"], "Third-person plural past perception; target object bare."),
    row(36, "They saw the dingo there.", "Jana murrumu yinyay nyajin.", "jana murrumu yinyay nyaji-ny | they dingo there see-PAST", "r177_past_they_murrumu_there", ["jana", "murrumu", "yinyay", "nyaji-l"], "Third-person plural past perception; dog/loan drift closed."),
    row(37, "They saw the black kangaroo there.", "Jana nyarrkali yinyay nyajin.", "jana nyarrkali yinyay nyaji-ny | they black.kangaroo there see-PAST", "r177_past_they_nyarrkali_there", ["jana", "nyarrkali", "yinyay", "nyaji-l"], "Third-person plural past perception; selected mammal sense only."),
    row(38, "They saw the platypus there.", "Jana wambiji yinyay nyajin.", "jana wambiji yinyay nyaji-ny | they platypus there see-PAST", "r177_past_they_wambiji_there", ["jana", "wambiji", "yinyay", "nyaji-l"], "Third-person plural past perception; habitat prose not imported."),
    row(39, "They saw the native cat there.", "Jana waykal yinyay nyajin.", "jana waykal yinyay nyaji-ny | they native.cat there see-PAST", "r177_past_they_waykal_there", ["jana", "waykal", "yinyay", "nyaji-l"], "Third-person plural past perception; native cat as dictionary head only."),
    row(40, "They saw the whale there.", "Jana yalmburrajaka yinyay nyajin.", "jana yalmburrajaka yinyay nyaji-ny | they whale there see-PAST", "r177_past_they_yalmburrajaka_there", ["jana", "yalmburrajaka", "yinyay", "nyaji-l"], "Third-person plural past perception; marine-event prose closed."),
    row(41, "We see the scrub wallaby here.", "Ngana bimbarrbay yaluy nyajil.", "ngana bimbarrbay yaluy nyaji-l | we scrub.wallaby here see-NONPAST", "r177_present_we_bimbarrbay_here", ["ngana", "bimbarrbay", "yaluy", "nyaji-l"], "Inclusive present perception with yaluy support."),
    row(42, "We see the white-tailed rat here.", "Ngana durrkin yaluy nyajil.", "ngana durrkin yaluy nyaji-l | we white-tailed.rat here see-NONPAST", "r177_present_we_durrkin_here", ["ngana", "durrkin", "yaluy", "nyaji-l"], "Inclusive present perception with yaluy support."),
    row(43, "We see the large bat here.", "Ngana jibul yaluy nyajil.", "ngana jibul yaluy nyaji-l | we large.bat here see-NONPAST", "r177_present_we_jibul_here", ["ngana", "jibul", "yaluy", "nyaji-l"], "Inclusive present perception; place/story sense closed."),
    row(44, "We see the dugong here.", "Ngana kirbaji yaluy nyajil.", "ngana kirbaji yaluy nyaji-l | we dugong here see-NONPAST", "r177_present_we_kirbaji_here", ["ngana", "kirbaji", "yaluy", "nyaji-l"], "Inclusive present perception with yaluy support."),
    row(45, "We see the little wallaby here.", "Ngana jumar yaluy nyajil.", "ngana jumar yaluy nyaji-l | we little.wallaby here see-NONPAST", "r177_present_we_jumar_here", ["ngana", "jumar", "yaluy", "nyaji-l"], "Inclusive present perception with yaluy support."),
    row(46, "We see the dingo here.", "Ngana murrumu yaluy nyajil.", "ngana murrumu yaluy nyaji-l | we dingo here see-NONPAST", "r177_present_we_murrumu_here", ["ngana", "murrumu", "yaluy", "nyaji-l"], "Inclusive present perception; dog/loan drift closed."),
    row(47, "We see the black kangaroo here.", "Ngana nyarrkali yaluy nyajil.", "ngana nyarrkali yaluy nyaji-l | we black.kangaroo here see-NONPAST", "r177_present_we_nyarrkali_here", ["ngana", "nyarrkali", "yaluy", "nyaji-l"], "Inclusive present perception with yaluy support."),
    row(48, "We see the platypus here.", "Ngana wambiji yaluy nyajil.", "ngana wambiji yaluy nyaji-l | we platypus here see-NONPAST", "r177_present_we_wambiji_here", ["ngana", "wambiji", "yaluy", "nyaji-l"], "Inclusive present perception; habitat prose not imported."),
    row(49, "We see the native cat here.", "Ngana waykal yaluy nyajil.", "ngana waykal yaluy nyaji-l | we native.cat here see-NONPAST", "r177_present_we_waykal_here", ["ngana", "waykal", "yaluy", "nyaji-l"], "Inclusive present perception; native cat as dictionary head only."),
    row(50, "We see the whale here.", "Ngana yalmburrajaka yaluy nyajil.", "ngana yalmburrajaka yaluy nyaji-l | we whale here see-NONPAST", "r177_present_we_yalmburrajaka_here", ["ngana", "yalmburrajaka", "yaluy", "nyaji-l"], "Inclusive present perception; sea/ocean event prose closed."),
]


def has_token(low: str, token: str) -> bool:
    return re.search(rf"(?<![a-z-]){re.escape(token)}(?![a-z-])", low) is not None


def first_word(low: str) -> str:
    return low.split()[0].strip(".,!?;:\"")


def has_target_case(low: str, head: str) -> bool:
    return re.search(rf"(?<![a-z-]){re.escape(head)}-(?:ngka|ngku|angka|nga|ngu|ba|mba|mbu|muny|darr|burr|bu|ka|nka|nku|ji|jirr|ku|mundu|amu|mu|iji|nda|ndu|anda|undu|unji|nji|kari|baka)\b", low) is not None


def english_has_denied(english_low: str, denied: str) -> bool:
    return denied in english_low if " " in denied else re.search(rf"\b{re.escape(denied)}\b", english_low) is not None


def scan_static() -> list[str]:
    issues: list[str] = []
    if len(ROWS) != 50:
        issues.append(f"{LABEL}: expected 50 rows, found {len(ROWS)}")
    seen_ku: set[str] = set()
    for expected, row_data in enumerate(ROWS, start=1):
        seq, english, kuku, analysis, frame, _tier, words_used, loans_used, evidence, confidence = row_data
        label = f"{LABEL}.{seq:02d}"
        low = kuku.lower()
        english_low = english.lower()
        words = json.loads(words_used)
        if seq != expected:
            issues.append(f"{label}: sequence mismatch; expected {expected}")
        if not english[:1].isupper() or english[-1:] not in ".!?":
            issues.append(f"{label}: English punctuation/capitalization failure")
        if " | " not in analysis:
            issues.append(f"{label}: analysis missing gloss separator")
        if not frame.startswith("r177_"):
            issues.append(f"{label}: Rule 177 frame must start with r177_")
        if low in seen_ku:
            issues.append(f"{label}: duplicate Kuku surface within batch")
        seen_ku.add(low)
        if json.loads(loans_used):
            issues.append(f"{label}: no loans are admitted in Rule 177")
        for denied in DENY_KUKU:
            if has_token(low, denied):
                issues.append(f"{label}: denied mammal/loan/old-field token {denied!r}")
        targets = [head for head in TARGET_HEADS if has_token(low, head)]
        if len(targets) != 1:
            issues.append(f"{label}: expected exactly one Rule 177 target head, found {targets}")
        for head in targets:
            selected = TARGET_HEADS[head]
            if head not in words:
                issues.append(f"{label}: target head {head} missing from words_used")
            if selected.replace(" ", ".") not in analysis:
                issues.append(f"{label}: target head {head} must be glossed as {selected}")
            if selected not in english_low:
                issues.append(f"{label}: {head} must be translated with selected sense {selected!r}")
            if has_target_case(low, head):
                issues.append(f"{label}: target head {head} has forbidden case/compound morphology")
        if seq <= 10:
            if "nyajil" in low or "nyajin" in low or "nyaji-l" in words:
                issues.append(f"{label}: deictic rows must not use nyaji-l")
            if not has_token(low, "yaluy") or "yaluy" not in words or "here" not in english_low:
                issues.append(f"{label}: Rule 177 deictic rows require yaluy/here")
        else:
            if ("nyajin" not in low and "nyajil" not in low) or "nyaji-l" not in words:
                issues.append(f"{label}: Rule 177 perception rows must use nyaji-l")
            first = first_word(low)
            if first not in PRONOUN_A:
                issues.append(f"{label}: perception A should be an approved bare pronoun")
            if 11 <= seq <= 20 and first != "ngayu":
                issues.append(f"{label}: rows 11-20 require ngayu")
            if 21 <= seq <= 30 and (first != "yundu" or not has_token(low, "yinyay") or "there" not in english_low):
                issues.append(f"{label}: rows 21-30 require yundu + yinyay/there")
            if 31 <= seq <= 40 and (first != "jana" or not has_token(low, "yinyay") or "saw" not in english_low):
                issues.append(f"{label}: rows 31-40 require jana + yinyay + past saw")
            if 41 <= seq <= 50 and (first != "ngana" or not has_token(low, "yaluy") or "here" not in english_low):
                issues.append(f"{label}: rows 41-50 require ngana + yaluy/here")
            if "nyajin" in low and "see-PAST" not in analysis:
                issues.append(f"{label}: nyajin must be glossed as see-PAST")
            if "nyajil" in low and "see-NONPAST" not in analysis:
                issues.append(f"{label}: nyajil must be glossed as see-NONPAST")
        if any(english_has_denied(english_low, bad) for bad in DENY_ENGLISH):
            issues.append(f"{label}: denied mammal event/use/polysemy field in English")
        if not evidence or not confidence:
            issues.append(f"{label}: missing evidence/confidence")
    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 177 draft: native mammal reference lexical expansion after Rule 176", "operator-guide-2026-07-08", "under_review", NOW),
        )
        batch_id = cur.lastrowid

    dupes: list[str] = []
    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 177 source pass selected ten native mammal-reference heads with exact dictionary readback: bimbarrbay scrub wallaby, durrkin white-tailed rat, jibul large bat, kirbaji dugong, jumar little wallaby, murrumu dingo, nyarrkali black kangaroo, wambiji platypus, waykal native cat, and yalmburrajaka whale. Corpus readback found zero active hits for durrkin, jibul, kirbaji, murrumu, nyarrkali, wambiji, waykal, and yalmburrajaka, with only low historical hits for bimbarrbay and jumar. Patz readback reconfirmed support forms yaluy/yinyay, nyaji-l/nyaji-ny, and bare pronoun A forms.",
                 command="rg dictionary mammal readback; rg grammar readback; sqlite boundary-aware corpus readback",
                 artifact_path=PROCESS_LOG, created_at=NOW)
    record_event(db, batch_label=LABEL, phase="scope", event_type="lexical-scope", actor="claude-main",
                 detail="Rule 177 is a lexical native-mammal reference pass for ten bare target heads. It excludes dog/pig/horse/cat-loan drift, introduced-animal rows, place/story/cave senses for jibul, iron/clothing/source-material extensions, food, hunting, catching, biting, killing, habitat/ecology, body-part, target case, target compounds, possession, plural derivation, and event claims.",
                 artifact_path=PROCESS_LOG, created_at=NOW)
    record_event(db, batch_label=LABEL, phase="preflight", event_type="duplicate-preflight", actor="claude-main",
                 detail="Exact duplicate preflight found 50 planned Kuku surfaces, 50 unique within-batch surfaces, and no exact accepted/revised/under_review cross-corpus duplicates.",
                 command="sqlite exact lower(trim(kuku)) duplicate scan before banking", artifact_path="batch_scripts/bank_219.py", created_at=NOW)
    record_event(db, batch_label=LABEL, phase="preflight", event_type="static-guard-pass", actor="claude-main",
                 detail="Static guards passed: exactly one Rule 177 mammal target per row; all targets bare; no loans; no old mammal heads outside the selected set; no event/use/polysemy tokens; no target case/compound forms; pronoun A bare; yinyay/yaluy support only.",
                 command="python3 batch_scripts/bank_219.py static scan", artifact_path="batch_scripts/bank_219.py", created_at=NOW)

    db.executemany(
        """
        INSERT INTO sentences(
          batch_id, seq, english, kuku, analysis, frame, tier, words_used,
          loans_used, evidence, status, confidence, author, created_at, updated_at
        )
        VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
        """,
        [(batch_id, *row_data[:9], "under_review", row_data[9], "claude-main", NOW, NOW) for row_data in ROWS],
    )
    db.commit()

    under_review = db.execute(
        "SELECT COUNT(*) FROM sentences WHERE batch_id=? AND status='under_review'",
        (batch_id,),
    ).fetchone()[0]
    verified = db.execute("SELECT COUNT(*) FROM sentences WHERE status IN ('accepted','revised')").fetchone()[0]
    print(f"banked {LABEL}: rows={len(ROWS)}, under_review={under_review}, verified_before_close={verified}")
    return 0


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