#!/usr/bin/env python3
"""Bank batch-147: human qualities, ability, and character/state 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-147"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")

DENY = {
    "manjarr", "wunbu-kari", "wawu-mumbu", "bikirr", "ngawuya", "wajan",
    "wawu-kaka", "janka-yukil", "nyawa", "jinbi", "jibin", "answer",
    "respect", "promise", "permission", "authority", "personality",
}


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


ROWS = [
    (1, "We two know how to spear.",
     "Ngali binal dama-nka.",
     "ngali binal dama-nka | we.two know spear-PURP",
     "binal_purposive_ability", 5, js(["ngali", "binal", "damal"]), js([]),
     "Patz ex.161 has binal + purposive 'know how to spear'; participant varied to avoid duplicate.", "0.86"),
    (2, "The child knows how to weave a dillybag.",
     "Karrkay binal balji wukurri-nka.",
     "karrkay binal balji wukurri-nka | child know dillybag weave-PURP",
     "binal_purposive_ability", 5, js(["karrkay", "binal", "balji", "wukurril"]), js([]),
     "Patz ex.585 has Jalbu binal balji wukurri-nka; participant varied after duplicate preflight.", "0.86"),
    (3, "The man is good with cattle.",
     "Nyulu dingkar juburr bulki-ka.",
     "nyulu dingkar juburr bulki-ka | he man good.at cattle-DAT",
     "juburr_dative_ability", 5, js(["nyulu", "dingkar", "juburr", "bulki"]), js([]),
     "Patz ex.586: juburr plus dative noun complement for being good at/with cattle.", "0.90"),
    (4, "The person knows very much.",
     "Bama binal-bajaku.",
     "bama binal-baja-ku | person know-DEG-EMPH",
     "binal_degree_exact_knowledge", 5, js(["bama", "binal", "-baja-ku"]), js([]),
     "Patz §3.9.1 lists binal-bajaku 'know very much, know exactly'.", "0.88"),
    (5, "The child does not know the language nowadays.",
     "Karrkay nyiku binal-kari kuku-ku.",
     "karrkay nyiku binal-kari kuku-ku | child today know-PRIV language-DAT",
     "binal_privative_dative", 5, js(["karrkay", "nyiku", "binal-kari", "kuku"]), js([]),
     "Patz ex.584 has Jana nyiku binal-kari kuku-ku; singular child variant avoids exact duplicate.", "0.86"),
    (6, "I am learning the language.",
     "Ngayu binalmal kuku-ku.",
     "ngayu binal-ma-l kuku-ku | I know-INCHO-NONPAST language-DAT",
     "binal_inchoative_learn", 5, js(["ngayu", "binal-ma-l", "kuku"]), js([]),
     "Patz ex.591: binal-ma-l with dative topic 'learn language'.", "0.88"),
    (7, "Grandmother taught the child to cook food.",
     "Babi-ngka karrkay binal-bungan mayi waju-nku.",
     "babi-ngka karrkay binal-bunga-ny mayi waju-nku | grandmother-ERG child know-CAUS-PAST food cook-PURP",
     "binal_causative_teach_purposive", 5, js(["babi", "karrkay", "binal-bungal", "mayi", "wajul"]), js([]),
     "Patz ex.592 and Rule 98 support binal-bunga-l with object and purposive complement.", "0.84"),
    (8, "He is competent.",
     "Nyulu mala-nganyi.",
     "nyulu mala-nganyi | he skilled-clever",
     "mala_competence_predicate", 4, js(["nyulu", "mala-nganyi"]), js([]),
     "Dictionary mala-nganyi = competent, clever; compound on mala 'good/skilled at'.", "0.88"),
    (9, "That one is a good hunter.",
     "Nyulu yinya mala-minya.",
     "nyulu yinya mala-minya | he that expert-meat",
     "mala_expert_predicate", 4, js(["nyulu", "yinya", "mala-minya"]), js([]),
     "Patz ex.509: Nyulu yinya mala-minya 'That one is a good hunter'.", "0.91"),
    (10, "The good hunter speared a sea turtle.",
     "Mala-minya-ngku ngawiya daman.",
     "mala-minya-ngku ngawiya dama-ny | expert-meat-ERG sea.turtle spear-PAST",
     "mala_expert_transitive", 5, js(["mala-minya", "ngawiya", "damal"]), js([]),
     "Combines Patz mala-minya with the sourced turtle-spear frame; ERG marks the expert-compound transitive A.", "0.85"),
    (11, "The good fisherman got fish.",
     "Mala-kuyu-ngku kuyu manin.",
     "mala-kuyu-ngku kuyu mani-ny | expert-fish-ERG fish get-PAST",
     "mala_expert_transitive", 5, js(["mala-kuyu", "kuyu", "manil"]), js([]),
     "Dictionary mala-kuyu = good fisherman; manil fish-get frame is stable; ERG marks transitive A.", "0.85"),
    (12, "The good singer sang a song.",
     "Mala-burri-ngku wulngku badin.",
     "mala-burri-ngku wulngku badi-ny | expert-song-ERG song sing/cry-PAST",
     "mala_expert_speech_song", 5, js(["mala-burri", "wulngku", "badi"]), js([]),
     "Grammar and errata support mala-burri 'song expert/good singer' and wulngku badi 'sing'; ERG marks transitive song frame.", "0.87"),
    (13, "The good cook cut up the fish.",
     "Nyulu mala-mayi-ngka kuyu yakan.",
     "nyulu mala-mayi-ngka kuyu yaka-ny | he expert-food-ERG fish cut-PAST",
     "mala_expert_ergative_source", 5, js(["nyulu", "mala-mayi", "kuyu", "yakal"]), js([]),
     "Patz ex.76: Nyulu mala-mayi-ngka kuyu yaka-ny.", "0.91"),
    (14, "The child asked the dillybag expert about dillybags.",
     "Karrkay mala-balji-nda babajin balji-ka.",
     "karrkay mala-balji-nda babaji-ny balji-ka | child expert-dillybag-LOC ask.about-PAST dillybag-DAT",
     "mala_expert_locative_ask_about", 5, js(["karrkay", "mala-balji", "babaji", "balji"]), js([]),
     "Patz ex.77 has mala-balji-nda babaji-ka balji-ka; converted to a past ask-about row without duplicate.", "0.84"),
    (15, "The man is a cattle expert.",
     "Dingkar mala-bulki.",
     "dingkar mala-bulki | man expert-cattle",
     "mala_expert_predicate", 4, js(["dingkar", "mala-bulki", "bulki"]), js([]),
     "Patz ex.75 has Charlie mala-bulki; common noun subject avoids proper-name dependency.", "0.86"),

    (16, "He is stupid.",
     "Nyulu kiru-kari.",
     "nyulu kiru-kari | he brain-PRIV/stupid",
     "privative_character_predicate", 4, js(["nyulu", "kiru-kari"]), js([]),
     "Patz ex.305: Nyulu kiru-kari 'He is stupid'.", "0.91"),
    (17, "The child is stupid.",
     "Karrkay kiru-kari.",
     "karrkay kiru-kari | child brain-PRIV/stupid",
     "privative_character_predicate", 4, js(["karrkay", "kiru-kari"]), js([]),
     "Dictionary kiru-kari = dull/stupid/silly; participant variant.", "0.84"),
    (18, "He became stupid.",
     "Nyulu kiru-kariman.",
     "nyulu kiru-kari-ma-ny | he brain-PRIV-INCHO-PAST",
     "privative_character_inchoative", 5, js(["nyulu", "kiru-kari", "kiru-kari-ma-l"]), js([]),
     "Patz ex.320 gives kiru-kari-ma-l 'getting stupid'; past surface follows -ma-ny.", "0.86"),
    (19, "You are lazy; go away.",
     "Yundu daki-daki, dungayda.",
     "yundu daki-daki, dunga-y-da | you lazy go-IMP-TEMP1",
     "lazy_source_usage_directive", 5, js(["yundu", "daki-daki", "dungay"]), js([]),
     "Dictionary daki-daki usage: Yundu daki-daki, dungayda.", "0.90"),
    (20, "The dog is lazy and no good for hunting.",
     "Kaya majarr.",
     "kaya majarr | dog lazy/no.good.for.hunting",
     "lazy_no_good_predicate", 4, js(["kaya", "majarr"]), js([]),
     "Dictionary majarr = lazy, no good for hunting/working, used of dogs and people.", "0.88"),
    (21, "The young man is lazy and no good for work.",
     "Warru majarr.",
     "warru majarr | young.man lazy/no.good.for.working",
     "lazy_no_good_predicate", 4, js(["warru", "majarr"]), js([]),
     "Dictionary majarr applies to people as well as dogs; spelling majarr, not stale manjarr.", "0.88"),
    (22, "He is too bossy.",
     "Nyulu majamal-majamal bajaku.",
     "nyulu majamal-majamal bajaku | he bossy very/too",
     "bossy_source_usage", 5, js(["nyulu", "majamal-majamal", "bajaku"]), js([]),
     "Dictionary majamal-majamal usage: Nyulu majamal-majamal bajaku.", "0.90"),
    (23, "The child fools around.",
     "Karrkay nguju-wuri.",
     "karrkay nguju-wuri-y | child fool.around-NONPAST",
     "fool_around_predicate", 5, js(["karrkay", "nguju-wuri-y"]), js([]),
     "Grammar-sourced nguju-wuri-y; surface drops final -iy as in Batch 126.", "0.84"),
    (24, "He does not do bad things; he does good things.",
     "Nyulu kari buyun-damal; nyulu ngulkurrku bunday.",
     "nyulu kari buyun-dama-l; nyulu ngulkurr-ku bunda-y | he NEG bad-do-NONPAST; he good-ADV sit/do-NONPAST",
     "moral_goodness_source_usage", 5, js(["nyulu", "kari", "buyun-damal", "ngulkurr", "bunday"]), js([]),
     "Dictionary ngulkurr example for moral good: Nyulu kari buyun-damal; nyulu ngulkurrku bunday.", "0.90"),
    (25, "That person is no good.",
     "Yinya bama nganjay.",
     "yinya bama nganjay | that person no.good",
     "no_good_person_predicate", 4, js(["yinya", "bama", "nganjay"]), js([]),
     "Nganyay/nganjay is no-good/wilted/bad-smell; English is narrowed to no-good person.", "0.80"),
    (26, "The always-angry person is there.",
     "Kuli-baka bama yinyay.",
     "kuli-baka bama yinyay | always.angry person there",
     "angry_person_lexical_predicate", 5, js(["kuli-baka", "bama", "yinyay"]), js([]),
     "Dictionary kuli-baka = person always fighting/always angry.", "0.86"),
    (27, "The young man is always angry.",
     "Warru kuli-baka.",
     "warru kuli-baka | young.man always.angry",
     "angry_person_lexical_predicate", 5, js(["warru", "kuli-baka"]), js([]),
     "Dictionary kuli-baka property applied to a human subject.", "0.84"),

    (28, "Grandmother told the truth.",
     "Babi-ngka manubaja balkan.",
     "babi-ngka manubaja balka-ny | grandmother-ERG truth speak-PAST",
     "truth_speech_transitive", 5, js(["babi", "manubaja", "balkal"]), js([]),
     "Batch 141 controls manubaja with balka-l; participant varied after duplicate preflight.", "0.84"),
    (29, "The young man told a lie.",
     "Warru-ngku jurril balkan.",
     "warru-ngku jurril balka-ny | young.man-ERG lie speak-PAST",
     "lie_speech_transitive", 5, js(["warru", "jurril", "balkal"]), js([]),
     "Dictionary jurril = lie/untruth; balka-l speech frame from Rule 99.", "0.84"),
    (30, "The young man lied.",
     "Warru warmbijin.",
     "warru warmbiji-ny | young.man lie/prevaricate-PAST",
     "lie_intransitive", 5, js(["warru", "warmbiji-y"]), js([]),
     "Dictionary warmbiji-y = lie/prevaricate; participant varied after duplicate preflight.", "0.84"),
    (31, "The liar told a lie.",
     "Warmbiji-bama jurril balkan.",
     "warmbiji-bama jurril balka-ny | liar-person lie speak-PAST",
     "liar_compound_speech", 5, js(["warmbiji-bama", "jurril", "balkal"]), js([]),
     "Errata records warmbiji-bama as liar; source-shaped with jurril balkan.", "0.82"),
    (32, "The woman believed the man.",
     "Jalbu-ngku dingkar manubaja-bungan.",
     "jalbu-ngku dingkar manubaja-bunga-ny | woman-ERG man truth-CAUS/believe-PAST",
     "believe_transitive", 5, js(["jalbu", "dingkar", "manubaja-bungal"]), js([]),
     "Dictionary manubaja-bungal = believe; participant varied after duplicate preflight.", "0.84"),
    (33, "He was sorry and confessed.",
     "Nyulu jiba-badin, mala-yirrkan.",
     "nyulu jiba-badi-ny, mala-yirrka-ny | he liver-cry-PAST confess/tell.truth-PAST",
     "confess_source_usage", 5, js(["nyulu", "jiba-badi-y", "mala-yirrkay"]), js([]),
     "Dictionary mala-yirrkay usage: Nyuly jiba-badin, mala-yirrkan.", "0.90"),
    (34, "The young man is ashamed.",
     "Warru milka-murruji.",
     "warru milka-murruji | young.man ear-ashamed/guilty",
     "ashamed_state_predicate", 4, js(["warru", "milka-murruji"]), js([]),
     "Dictionary milka-murruji = ashamed/guilty; participant varied after duplicate preflight.", "0.86"),
    (35, "The young man became ashamed.",
     "Warru murru-kadan.",
     "warru murru-kaday-ny | young.man become.ashamed-PAST",
     "shame_inchoative", 5, js(["warru", "murru-kaday"]), js([]),
     "Dictionary murru-kaday = become ashamed/shy/bashful; follows Batch 141 analysis convention.", "0.86"),
    (36, "The old man shamed the child.",
     "Mukul-dingkar-angka karrkay murru-kaday-manin.",
     "mukul-dingkar-angka karrkay murru-kaday-mani-ny | old-man-ERG child ashamed-CAUS-PAST",
     "shame_causative", 5, js(["mukul-dingkar", "karrkay", "murru-kaday-manil"]), js([]),
     "Dictionary murru-kaday-manil = shame someone; transitive A O V frame.", "0.84"),
    (37, "He is the guilty one.",
     "Nyulu mala bajaku.",
     "nyulu mala bajaku | he guilty very/indeed",
     "guilty_source_usage", 4, js(["nyulu", "mala bajaku"]), js([]),
     "Dictionary mala bajaku usage for guilty/the one responsible; kept as source phrase, not Rule 104 suffixal degree.", "0.86"),
    (38, "I am content about that.",
     "Ngayu milka-marri yinyanka.",
     "ngayu milka-marri yinya-nka | I ear-content that-DAT",
     "content_dative_state", 5, js(["ngayu", "milka-marri", "yinya"]), js([]),
     "Dictionary milka-marri = content/peaceful with dative complement; subject varied from Batch 129.", "0.84"),
    (39, "I agree.",
     "Ngayu wawumal.",
     "ngayu wawu-ma-l | I agree-NONPAST",
     "agree_predicate", 4, js(["ngayu", "wawumal"]), js([]),
     "Dictionary wawumal = agree; usage Yundu wawumal, ngali dungay.", "0.84"),
    (40, "He is willing.",
     "Nyulu wawurr-wawurr.",
     "nyulu wawurr-wawurr | he willing/glad",
     "willing_state_predicate", 4, js(["nyulu", "wawurr-wawurr"]), js([]),
     "Dictionary wawurr-wawurr = willing/glad.", "0.84"),
    (41, "Mother made the child happy.",
     "Ngamu-ngku karrkay wawurr-wawurr-bungan.",
     "ngamu-ngku karrkay wawurr-wawurr-bunga-ny | mother-ERG child happy-CAUS-PAST",
     "make_happy_causative", 5, js(["ngamu", "karrkay", "wawurr-wawurr-bungal"]), js([]),
     "Dictionary wawurr-wawurr-bungal = make happy/glad.", "0.84"),

    (42, "That pig is not afraid any more; it is tame now.",
     "Nyulu bikibiki yinyilji karida, mindayda.",
     "nyulu bikibiki yinyilji kari-da, minday-da | that pig frightened NEG-TEMP1 tame-TEMP1",
     "minday_source_usage", 5, js(["nyulu", "bikibiki", "yinyilji", "minday"]), js([]),
     "Dictionary minday usage: Nyulu bikibiki yinyilji karida, mindayda.", "0.90"),
    (43, "The pig is tame now.",
     "Bikibiki mindayda.",
     "bikibiki minday-da | pig tame-TEMP1",
     "minday_short_predicate", 4, js(["bikibiki", "minday"]), js([]),
     "Controlled short variant of the dictionary minday tame usage.", "0.84"),
    (44, "The Banabila people's dogs are fierce.",
     "Banabila-warra-mu kaya kuli-ji.",
     "banabila-warra-mu kaya kuli-ji | Banabila-INHAB-POSS dog rage-COMIT",
     "kuli_ji_source_predicate", 5, js(["Banabila-warra", "kaya", "kuli-ji"]), js([]),
     "Patz ex.89: Banabila-warra-mu kaya kuli-ji.", "0.90"),
    (45, "A rather wild dog bit my dog.",
     "Kaya jarra-kuli-ji ngayku kaya baykan.",
     "kaya jarra-kuli-ji ngayku kaya bayka-ny | dog rather-rage-COMIT my dog bite-PAST",
     "jarra_kuli_ji_source_variant", 5, js(["kaya", "jarra-kuli-ji", "ngayku", "baykal"]), js([]),
     "Patz ex.80 has a rather wild dog biting my dog; case marking simplified to ABS subject variant.", "0.80"),
    (46, "The young men went out for pigs.",
     "Warru-warru bikibiki-nga dungan.",
     "warru-warru bikibiki-nga dunga-ny | young.man-REDUP pig-LOC go-PAST",
     "young_men_activity", 4, js(["warru-warru", "bikibiki", "dungay"]), js([]),
     "Patz ex.269: Warru-warru bikibiki-nga dunga-ny.", "0.90"),
    (47, "The old man is there.",
     "Mukul-dingkar yinyay.",
     "mukul-dingkar yinyay | old-man there",
     "age_status_predicate", 3, js(["mukul-dingkar", "yinyay"]), js([]),
     "Uses mukul old in a stable age/status compound.", "0.82"),
    (48, "The old woman cooked food.",
     "Mukul-jalbu-ngku mayi wajun.",
     "mukul-jalbu-ngku mayi waju-ny | old-woman-ERG food cook-PAST",
     "age_status_transitive", 4, js(["mukul-jalbu", "mayi", "wajul"]), js([]),
     "Uses mukul old-woman compound with ERG transitive A; cook/burn past is wajun, not wajan.", "0.85"),
    (49, "The old horse walks slowly.",
     "Yarraman mukul waymbul-ku dungay.",
     "yarraman mukul waymbul-ku dunga-y | horse old slow-ADV go-NONPAST",
     "old_slow_source_usage", 5, js(["yarraman", "mukul", "waymbul", "dungay"]), js([]),
     "Patz ex.198: Yarraman mukul waymbul-ku dunga-y.", "0.90"),
    (50, "I am tired from walking.",
     "Ngayu baja-burray jilba-muny.",
     "ngayu baja-burray jilba-muny | I tired walk-ABL",
     "tired_ablative_cause", 4, js(["ngayu", "baja-burray", "jilba"]), js([]),
     "Dictionary baja-burray usage has ngayu baja-burray jilbamun; corpus uses regular ablative spelling jilba-muny.", "0.84"),
]


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}"
        e_start = english.lstrip("'\"")
        e_end = english.rstrip("'\"").rstrip()
        if not e_start[:1].isupper() or e_end[-1:] not in ".!?":
            issues.append(f"{label}: English must be capitalized and final-punctuated")
        if " | " not in analysis:
            issues.append(f"{label}: analysis missing gloss separator")
        k_start = kuku.lstrip("'\"")
        if not k_start[:1].isupper():
            issues.append(f"{label}: Kuku surface must start uppercase or with a quote before uppercase")
        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()} "
        for word in DENY:
            if re.search(rf"(?<![a-z]){re.escape(word)}(?![a-z])", low):
                issues.append(f"{label}: denied phantom/wrong-sense/blocked token {word!r}")
        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 105 draft: human qualities, ability, and character/state lexicon", "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 105 source pass checked Patz adjectival particles binal/juburr, mala- expert compounds, "
            "kiru-kari, daki-daki, majarr, majamal-majamal, nguju-wuri-y, manubaja/jurril/warmbiji, "
            "mala-yirrkay, milka-murruji, murru-kaday, minday, kuli-ji/kuli-baka, age/status terms, and "
            "baja-burray. Duplicate preflight rejected already accepted source examples before script writing."
        ),
        command="rg/sed over grammar.md, dictionary.yaml, living books, plus sqlite duplicate scan",
        artifact_path="process_logs/batch-147-human-qualities-process.md",
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="scope",
        event_type="risk-controls",
        actor="claude-main",
        detail=(
            "Guarded against stale or English-shaped quality words: no manjarr spelling for lazy, no wunbu-kari as lazy, "
            "no wawu-mumbu for jealous/worried, no bikirr shame noun, no broad personality labels, no ngawuya in this "
            "corpus-normalized turtle row, and cook/burn past kept as wajun not wajan."
        ),
        artifact_path="process_logs/batch-147-human-qualities-process.md",
        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 105 human-quality, ability, and character/state lexical rows under_review after static and duplicate checks.",
        command="python3 batch_scripts/bank_147.py",
        artifact_path="batch_scripts/bank_147.py",
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="bank",
        event_type="row-inventory",
        actor="claude-main",
        detail=(
            "Rows 1-15 knowledge, ability, and mala- expert compounds; 16-27 foolishness, laziness, bossiness, "
            "moral good/no-good, and angry/wild character terms; 28-41 truth, lying, confession, shame, contentment, "
            "agreement, willingness, and make-happy; 42-50 tame/fierce/young/old/tired status terms."
        ),
        artifact_path="process_logs/batch-147-human-qualities-process.md",
        created_at=NOW,
    )
    db.commit()
    count = db.execute("SELECT COUNT(*) FROM sentences WHERE batch_id=?", (batch_id,)).fetchone()[0]
    avg_words = db.execute(
        "SELECT AVG(LENGTH(kuku)-LENGTH(REPLACE(kuku,' ',''))+1.0) FROM sentences WHERE batch_id=?",
        (batch_id,),
    ).fetchone()[0]
    print(f"banked {LABEL}: {count} rows under_review; avg Kuku words/row={avg_words:.2f}")
    return 0


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