#!/usr/bin/env python3
"""Bank batch-143: health, sickness, injury, soreness, healing, recovery."""

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-143"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")

DENY = {
    "nyawa", "jinbi", "jibin", "walba", "julmbu", "wanan", "ngampula",
    "ngana-jinji", "jubuny", "wural", "bigan", "jiwuny", "warngkul",
    "wanaba", "jarrkunji", "munjal", "murku", "buni", "kunya",
    "milkan", "kulur-jambul", "janyji", "buburr", "jarrmba", "jinji",
    "daga", "wanka", "yumbul", "kuku-yumbul", "jubi", "yilbay",
    "jarrakay", "janka-yukil", "jukarr", "kunkul", "bubu-jandu",
    "bubu-warral", "jani-warra", "balbay-nja", "bunjurril", "buri",
    "ngara", "rrunyuji", "murri", "warmba", "dukal", "kalbali",
    "medicine", "hospital", "answer",
}


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


ROWS = [
    (1, "The old woman is sick.",
     "Mukul-jalbu bambay.",
     "mukul-jalbu bambay | old-woman sick",
     "health_simple_sick_predicate", 4, js(["mukul-jalbu", "bambay"]), js([]),
     "Dictionary bambay 'sick'; Patz ex.389 uses a sick woman as predicate state.", "0.90"),
    (2, "The young man became sick yesterday.",
     "Yilayku warru bambayman.",
     "yilayku warru bambay-ma-ny | yesterday young.man sick-INCHO-PAST",
     "health_bambay_inchoative_past", 4, js(["yilayku", "warru", "bambay"]), js([]),
     "Patz ex.113 Yilayku nyulu bambay-ma-ny controls yesterday + inchoative illness.", "0.90"),
    (3, "I became sick from eating unripe mangoes.",
     "Ngayu bambayman mayngku kayal nuka-nya.",
     "ngayu bambay-ma-ny mayngku kayal nuka-nya | I sick-INCHO-PAST mango unripe eat-SUB",
     "health_causal_subordinate_sickness", 6, js(["ngayu", "bambay", "mayngku", "kayal", "nukal"]), js([]),
     "Patz ex.167 controls bambay-ma-ny plus causal subordinate nuka-nya.", "0.92"),
    (4, "The child is getting quite sick.",
     "Karrkay bambay-mal-baja.",
     "karrkay bambay-ma-l-baja | child sick-INCHO-NONPAST-DEGREE",
     "health_bambay_inchoative_degree", 5, js(["karrkay", "bambay", "baja"]), js([]),
     "Patz ex.216 controls bambay-ma-l-baja 'getting quite sick'.", "0.91"),
    (5, "The eel meat made him sick.",
     "Nyunguny bambay-bungan kubarr-da.",
     "nyunguny bambay-bunga-ny kubarr-da | him sick-CAUS-PAST eel-ERG",
     "health_bambay_causative_food", 5, js(["nyunguny", "bambay", "bungal", "kubarr"]), js([]),
     "Patz ex.238 Nganya bambay-bunga-ny kubarr-da controls causative sickness frame.", "0.90"),
    (6, "The sick man is sleeping.",
     "Dingkar bambay warngku-wunay.",
     "dingkar bambay warngku-wuna-y | man sick sleep-lie-NONPAST",
     "health_sick_np_sleep", 4, js(["dingkar", "bambay", "warngku-wunay"]), js([]),
     "Patz ex.480 controls Dingkar bambay warngku-wuna-y with sick as NP modifier.", "0.88"),
    (7, "The sick child is lying in the house.",
     "Karrkay bambay bayan-ba wunanay.",
     "karrkay bambay bayan-ba wuna-na-y | child sick house-LOC lie-REDUP-NONPAST",
     "health_sick_child_locative_rest", 5, js(["karrkay", "bambay", "bayan", "wunanay"]), js([]),
     "Combines sourced sick modifier with common locative rest/lie frame.", "0.84"),
    (8, "He is well now after being sick.",
     "Nyulu bambay-mun ngulkurr-da.",
     "nyulu bambay-mun ngulkurr-da | he sick-ABL well-now",
     "health_recovery_after_sickness", 5, js(["nyulu", "bambay", "ngulkurr"]), js([]),
     "Dictionary ngulkurr example Nyulu bambaymun ngulkurrda controls after-sickness recovery.", "0.91"),
    (9, "The child got better.",
     "Karrkay ngulkurrman.",
     "karrkay ngulkurr-ma-ny | child good/well-INCHO-PAST",
     "health_ngulkurr_inchoative_recovery", 4, js(["karrkay", "ngulkurr"]), js([]),
     "Patz ex.410/556 control ngulkurr-ma-l/-ny as get better/be well again.", "0.88"),
    (10, "He has no cold; he got well again.",
     "Nyulu ngiki-kari, ngulkurrman baja.",
     "nyulu ngiki-kari ngulkurr-ma-ny baja | he cold-PRIV well-INCHO-PAST again",
     "health_privative_cold_recovery", 5, js(["nyulu", "ngiki", "kari", "ngulkurr", "baja"]), js([]),
     "Patz ex.556 Ngayu ngiki-kari, ngulkurr-ma-ny controls cold-privative recovery.", "0.90"),
    (11, "Do you have a cold?",
     "Yundu ngikiji?",
     "yundu ngiki-ji | you cold-COMIT",
     "health_ngikiji_polar_question", 4, js(["yundu", "ngiki", "ngikiji"]), js([]),
     "Patz conversation note gives Yundu ngikiji? for asking whether someone has a cold.", "0.91"),
    (12, "The child has a cough.",
     "Karrkay ngiki-ji.",
     "karrkay ngiki-ji | child cough/cold-COMIT",
     "health_ngiki_comitative_state", 4, js(["karrkay", "ngiki"]), js([]),
     "Dictionary ngiki/ngikiji and Patz ex.545 control cough/cold as comitative bodily state.", "0.87"),
    (13, "If he has a cough, he breaks up green ants and eats them.",
     "Kaki nyulu ngiki-ji, nyulu yangka dumbarril, nukal.",
     "kaki nyulu ngiki-ji nyulu yangka dumbarri-l nuka-l | if he cough-COMIT he green.ant break-NONPAST eat-NONPAST",
     "health_conditional_green_ant_treatment", 6, js(["kaki", "nyulu", "ngiki", "yangka", "dumbarril", "nukal"]), js([]),
     "Patz ex.394 controls conditional cough/cold plus breaking and eating green ants; actor varied to avoid exact duplicate.", "0.90"),
    (14, "Grandmother gave green ants to the child with the cough.",
     "Babi-ngka yangka dajin karrkay-anda ngiki-ji-nda.",
     "babi-ngka yangka daji-ny karrkay-anda ngiki-ji-nda | grandmother-ERG green.ant give-PAST child-LOC cough-COMIT-LOC",
     "health_green_ant_give_to_coughing_child", 6, js(["babi", "yangka", "dajil", "karrkay", "ngiki"]), js([]),
     "Patz ex.545 controls yangka daji-ny karrkay-anda ngiki-ji-nda.", "0.92"),
    (15, "Grandmother takes green ants in order to get better.",
     "Babi-ngka yangka nukal, ngulkurr-manka.",
     "babi-ngka yangka nuka-l ngulkurr-ma-nka | grandmother-ERG green.ant eat/take-NONPAST well-INCHO-PURP",
     "health_green_ant_purposive_recovery", 6, js(["babi", "yangka", "nukal", "ngulkurr"]), js([]),
     "Patz ex.410 controls Babi-ngka yangka nuka-l, ngulkurr-ma-nka.", "0.92"),
    (16, "Green ant is a remedy for colds.",
     "Yangka ngiki-ka kalbal.",
     "yangka ngiki-ka kalbal | green.ant cold-DAT remedy",
     "health_green_ant_remedy_np", 4, js(["yangka", "ngiki", "kalbal"]), js([]),
     "Grammar medicine section and dictionary yangka/kalbal identify green ant as a remedy for colds.", "0.86"),
    (17, "The bush medicine is for the sick child.",
     "Dukunjaka karrkay bambay-nka.",
     "dukunjaka karrkay bambay-nka | bush-med child sick-DAT",
     "health_bush_medicine_for_sick_child", 4, js(["dukunjaka", "karrkay", "bambay"]), js([]),
     "Dictionary dukunjaka 'bush medicine'; dative adjective frame follows Patz sick-DAT examples.", "0.84"),
    (18, "Grandfather takes a remedy for the road in case he gets sick.",
     "Ngaji-ngka kalbal wundil baral-ka, kunka nyulu bambay-ma-nya-mun-ku.",
     "ngaji-ngka kalbal wundi-l baral-ka kunka nyulu bambay-ma-nya-mun-ku | grandfather-ERG remedy take-NONPAST road-DAT in.case he sick-INCHO-SUB-mun-DAT",
     "health_precautionary_medicine_for_road", 6, js(["ngaji", "kalbal", "wundil", "baral", "kunka", "bambay"]), js([]),
     "Patz ex.500 controls medicine/road/in-case sickness frame; kalbal replaces English loan medicine.", "0.88"),
    (19, "Bangkan root is a remedy for a sore.",
     "Bangkan baji-ka kalbal.",
     "bangkan baji-ka kalbal | bangkan.root sore-DAT remedy",
     "health_bangkan_sore_remedy_np", 4, js(["bangkan", "baji", "kalbal"]), js([]),
     "Dictionary bangkan: root used as medicine for sores; baji is 'a sore'.", "0.88"),
    (20, "Grandmother washed the sore with water.",
     "Babi-ngka baji julurrin bana-bu.",
     "babi-ngka baji julurri-ny bana-bu | grandmother-ERG sore wash-PAST water-INST",
     "health_wash_sore_instrument", 5, js(["babi", "baji", "julurril", "bana"]), js([]),
     "Dictionary julurril 'wash something'; bangkan note licenses washing sores with water.", "0.86"),
    (21, "The child is sore.",
     "Karrkay kaka.",
     "karrkay kaka | child sore/achey",
     "health_kaka_pain_state", 4, js(["karrkay", "kaka"]), js([]),
     "Dictionary kaka 'sore, achey'; existing living rules restrict this batch to the bodily pain sense.", "0.89"),
    (22, "His body is painful.",
     "Nyungu bangkarr bajaybajay.",
     "nyungu bangkarr bajaybajay | his body painful",
     "health_bajaybajay_body_pain", 4, js(["nyungu", "bangkarr", "bajaybajay"]), js([]),
     "Dictionary bajaybajay example uses bangkarr plus painful/sore body.", "0.89"),
    (23, "The sore is painful.",
     "Baji bajaybajay.",
     "baji bajaybajay | sore painful",
     "health_sore_painful_predicate", 4, js(["baji", "bajaybajay"]), js([]),
     "Dictionary baji 'a sore' and bajaybajay 'painful'.", "0.88"),
    (24, "I am sore all over.",
     "Ngayu kakajirr.",
     "ngayu kaka-jirr | I sore-COMIT/with",
     "health_kaka_all_over_source", 4, js(["ngayu", "kaka"]), js([]),
     "Dictionary kaka example Ngayu kakajirr controls this exact bodily-pain expression.", "0.91"),
    (25, "The child's head aches.",
     "Karrkay dukul baykal.",
     "karrkay dukul bayka-l | child head ache-NONPAST",
     "health_baykal_ache_head", 5, js(["karrkay", "dukul", "baykal"]), js([]),
     "Dictionary duplicate baykal entry gives intransitive ache/pain with head as affected part.", "0.88"),
    (26, "My head aches.",
     "Ngayu dukul baykal.",
     "ngayu dukul bayka-l | I head ache-NONPAST",
     "health_baykal_ache_first_person", 5, js(["ngayu", "dukul", "baykal"]), js([]),
     "Dictionary baykal ache example controls first-person head-ache frame; source typo dukal corrected to dukul.", "0.88"),
    (27, "The child's sore is not good.",
     "Karrkay-mu baji kari ngulkurr.",
     "karrkay-mu baji kari ngulkurr | child-GEN sore NEG good",
     "health_negated_sore_goodness", 4, js(["karrkay", "baji", "kari", "ngulkurr"]), js([]),
     "Uses sourced baji sore and ordinary kari predicate negation to avoid inventing a wound-status verb.", "0.83"),
    (28, "The sore got better again.",
     "Baji ngulkurrman baja.",
     "baji ngulkurr-ma-ny baja | sore good-INCHO-PAST again",
     "health_sore_recovery_inchoative", 5, js(["baji", "ngulkurr", "baja"]), js([]),
     "Patz ngulkurr-ma-ny recovery frame extended to baji as the recovering patient.", "0.84"),
    (29, "Grandmother healed the child.",
     "Babi-ngka karrkay kakawarri-bungan.",
     "babi-ngka karrkay kakawarri-bunga-ny | grandmother-ERG child well/healed-CAUS-PAST",
     "health_kakawarri_causative_heal", 5, js(["babi", "karrkay", "kakawarri", "bungal"]), js([]),
     "Living cheatsheet Rule 64/101 licenses kakawarri-bunga-l 'heal'; dictionary has kakawarri 'well'.", "0.85"),
    (30, "The child got well.",
     "Karrkay kakawarri-man.",
     "karrkay kakawarri-ma-ny | child well/healed-INCHO-PAST",
     "health_kakawarri_inchoative_get_well", 5, js(["karrkay", "kakawarri"]), js([]),
     "Living cheatsheet licenses kakawarri-ma-l 'get well' as the preferred heal lexeme.", "0.85"),
    (31, "The dog bit the child.",
     "Kaya-ngka karrkay baykan.",
     "kaya-ngka karrkay bayka-ny | dog-ERG child bite-PAST",
     "health_baykal_transitive_bite", 4, js(["kaya", "karrkay", "baykal"]), js([]),
     "Dictionary baykal transitive bite; Patz ex.237 controls animal ERG biting patient.", "0.89"),
    (32, "The snake bit him.",
     "Jarba-bu nyunguny baykan.",
     "jarba-bu nyunguny bayka-ny | snake-ERG/INST him bite-PAST",
     "health_snake_bite_pronominal_object", 5, js(["jarba", "nyunguny", "baykal"]), js([]),
     "Patz ex.252 controls Jarba-bu nyunguny bayka-ny 'A snake bit him'.", "0.91"),
    (33, "The snake did not bite the child; the child is well.",
     "Jarba-bu karrkay kari baykan, karrkay ngulkurr.",
     "jarba-bu karrkay kari bayka-ny karrkay ngulkurr | snake-ERG/INST child NEG bite-PAST child well",
     "health_negative_bite_well_result", 5, js(["jarba", "karrkay", "kari", "baykal", "ngulkurr"]), js([]),
     "Contrasts bite event with ngulkurr well state; keeps baykal bite distinct from ache.", "0.84"),
    (34, "If the child hits the dog with a stick, it will bite him.",
     "Kaki karrkay-ngka kaya juku-bu kunil, nyunguny baykal.",
     "kaki karrkay-ngka kaya juku-bu kuni-l nyunguny bayka-l | if child-ERG dog stick-INST hit-NONPAST him bite-NONPAST",
     "health_conditional_hit_bite", 6, js(["kaki", "karrkay", "kaya", "juku", "kunil", "baykal"]), js([]),
     "Patz ex.393 controls conditional hit-with-stick leading to bite.", "0.88"),
    (35, "The stinging tree burnt the child.",
     "Karrkay mili-bu wajun.",
     "karrkay mili-bu waju-ny | child stinging.tree-ERG/INST burn-PAST",
     "health_mili_burn_transitive", 5, js(["karrkay", "mili", "wayjul"]), js([]),
     "Patz ex.230/241 and dictionary mili support stinging tree/jellyfish burn frame.", "0.89"),
    (36, "He was burnt by a stinging tree.",
     "Nyulu mili-bu waju-jin.",
     "nyulu mili-bu waju-ji-ny | he stinging.tree-INST burn-ITR-PAST",
     "health_mili_burn_intransitive", 5, js(["nyulu", "mili", "wayjuji"]), js([]),
     "Patz ex.249 controls Nyulu mili-bu waju-ji-ny 'He was burnt by a stinging tree'.", "0.91"),
    (37, "The child was burnt by a jellyfish.",
     "Karrkay mili-bu waju-jin.",
     "karrkay mili-bu waju-ji-ny | child jellyfish-INST burn-ITR-PAST",
     "health_mili_jellyfish_burn_intransitive", 5, js(["karrkay", "mili", "wayjuji"]), js([]),
     "Dictionary mili also means jellyfish; Patz ex.251 permits mili-bu/nga with waju-ji-ny.", "0.87"),
    (38, "The man cut himself with a knife.",
     "Dingkar naybu-bu yakajin.",
     "dingkar naybu-bu yaka-ji-ny | man knife-INST cut-REF-PAST",
     "health_yakal_reflexive_cut_self", 5, js(["dingkar", "naybu", "yakal"]), js(["naybu"]),
     "Patz ex.247 controls yaka-ji-ny with naybu-bu instrument.", "0.90"),
    (39, "Grandmother cut the fish with a knife.",
     "Babi-ngka kuyu naybu-bu yakan.",
     "babi-ngka kuyu naybu-bu yaka-ny | grandmother-ERG fish knife-INST cut-PAST",
     "health_yakal_transitive_instrument", 5, js(["babi", "kuyu", "naybu", "yakal"]), js(["naybu"]),
     "Patz ex.247 controls yaka-l transitive with naybu-bu instrument.", "0.87"),
    (40, "Blood came from the hand.",
     "Mula mara-muny kadan.",
     "mula mara-muny kada-ny | blood hand-ABL come-PAST",
     "health_blood_from_body_part", 4, js(["mula", "mara", "kaday"]), js([]),
     "Dictionary mula 'blood'; ablative body-part source follows ordinary -muny from-frame.", "0.84"),
    (41, "The woman washed the blood with water.",
     "Jalbu-ngku mula julurrin bana-bu.",
     "jalbu-ngku mula julurri-ny bana-bu | woman-ERG blood wash-PAST water-INST",
     "health_wash_blood_instrument", 5, js(["jalbu", "mula", "julurril", "bana"]), js([]),
     "Dictionary julurril transitive wash plus mula blood; bana-bu instrument is sourced pattern.", "0.86"),
    (42, "The man made the child bleed.",
     "Dingkar-angka karrkay mula-kangan.",
     "dingkar-angka karrkay mula-kanga-ny | man-ERG child blood-CAUS-PAST",
     "health_mula_kangal_induce_bleeding", 5, js(["dingkar", "karrkay", "mula", "kangal"]), js([]),
     "Patz causative table explicitly licenses mula-kanga-l 'induce bleeding' and forbids mula-bunga-l.", "0.89"),
    (43, "The child is vomiting.",
     "Nyulu karrkay kaljil.",
     "nyulu karrkay kalji-l | he child vomit-NONPAST",
     "health_kaljil_vomit_source", 4, js(["nyulu", "karrkay", "kaljil"]), js([]),
     "Patz ex.230 controls Nyulu karrkay kalji-l 'The child is vomiting'.", "0.92"),
    (44, "The young man vomited.",
     "Warru kaljin.",
     "warru kalji-ny | young.man vomit-PAST",
     "health_kaljil_vomit_past", 4, js(["warru", "kaljil"]), js([]),
     "Dictionary/Patz kalji-l vomit; surface past follows corpus -ny to -n convention.", "0.86"),
    (45, "The old man is exhausted.",
     "Mukul-dingkar wawulay.",
     "mukul-dingkar wawu-wula-y | old-man breath-die-NONPAST",
     "health_wawulay_exhausted", 4, js(["mukul-dingkar", "wawulay"]), js([]),
     "Patz ex.232 controls wawula-y from wawu-wula-y 'exhausted'.", "0.88"),
    (46, "The child is hungry.",
     "Karrkay dakwuy.",
     "karrkay dakwuy | child hungry",
     "health_dakwuy_hungry_state", 4, js(["karrkay", "dakwuy"]), js([]),
     "Dictionary/living rules: dakwuy is hungry; keep distinct from old dakuy typo.", "0.88"),
    (47, "The old woman gave soft food to the sick child.",
     "Mukul-jalbu-ngku mayi kima dajin karrkay-anda bambay-nda.",
     "mukul-jalbu-ngku mayi kima daji-ny karrkay-anda bambay-nda | old-woman-ERG food soft give-PAST child-LOC sick-LOC",
     "health_give_food_to_sick_child", 6, js(["mukul-jalbu", "mayi", "kima", "dajil", "karrkay", "bambay"]), js([]),
     "Modeled on Patz ex.545 give-to child-with-cough; adjective LOC agrees with locative child.", "0.84"),
    (48, "Mother gave water to the sick child.",
     "Ngamu-ngku bana dajin karrkay-anda bambay-nda.",
     "ngamu-ngku bana daji-ny karrkay-anda bambay-nda | mother-ERG water give-PAST child-LOC sick-LOC",
     "health_give_water_to_sick_child", 6, js(["ngamu", "bana", "dajil", "karrkay", "bambay"]), js([]),
     "Same controlled dative/locative recipient pattern as Patz ex.545.", "0.84"),
    (49, "The old woman asked the sick child: \"What are you ill with?\"",
     "Mukul-jalbu karrkay-anda babajin: \"Yundu wanyurrinji bambay?\"",
     "mukul-jalbu karrkay-anda babaji-ny: \"yundu wanyurri-nji bambay\" | old-woman child-LOC ask-PAST: \"you what-COMIT sick\"",
     "health_direct_question_ill_with_what", 6, js(["mukul-jalbu", "karrkay", "babaji", "yundu", "wanyurrinji", "bambay"]), js([]),
     "Patz ex.128 Yundu wanyurrinji bambay? plus Rule 100 babaji-y quoted-question frame.", "0.88"),
    (50, "The child said: \"My head aches.\"",
     "Karrkay-ngku balkan: \"Ngayu dukul baykal.\"",
     "karrkay-ngku balka-ny: \"ngayu dukul bayka-l\" | child-ERG say-PAST: \"I head ache-NONPAST\"",
     "health_direct_quote_head_ache", 5, js(["karrkay", "balkal", "ngayu", "dukul", "baykal"]), js([]),
     "Rule 100 direct speech frame plus dictionary baykal ache example.", "0.86"),
]


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 101 draft: health/sickness/injury/recovery 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=(
            "Source pass for Rule 101 checked Patz medicine section, bambay/ngiki/ngulkurr examples, "
            "kaka/baji/bajaybajay pain entries, baykal bite-vs-ache duplicate entries, mili burn frames, "
            "yaka/yakaji cut frames, mula-kanga-l bleed causative, kalji-l vomit, yangka/kalbal/dukunjaka/bangkan remedies."
        ),
        command="rg/sed over dictionary.yaml, grammar.md, living books",
        artifact_path="process_logs/batch-143-health-process.md",
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="scope",
        event_type="risk-controls",
        actor="claude-main",
        detail=(
            "Rejected or fenced off risky forms: no warmba as heal, no English medicine/hospital loan, no murri/rrunyuji doctor "
            "sentences, no dukal typo, no kalbali confusion, no kujil as medical care, no bada/karrbal scope drift, and no mula-bunga-l."
        ),
        artifact_path="process_logs/batch-143-health-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 101 health/sickness/injury/recovery rows under_review after static and duplicate checks.",
        command="python3 batch_scripts/bank_143.py",
        artifact_path="batch_scripts/bank_143.py",
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="bank",
        event_type="row-inventory",
        actor="claude-main",
        detail=(
            "Rows cover sick/well states, bambay inchoative/causative, ngiki/ngikiji cold/cough, yangka/kalbal/dukunjaka/bangkan remedies, "
            "kaka/baji/bajaybajay pain and sores, baykal ache vs bite, mili burns, yaka/yakaji cuts, mula blood/bleeding, julurril washing, "
            "kalji-l vomit, dakwuy hunger, wawulay exhaustion, and two direct health-question/reporting frames."
        ),
        artifact_path="process_logs/batch-143-health-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())
