#!/usr/bin/env python3
"""Close batch-378 after main-loop five-lens review."""

from __future__ import annotations

import datetime as dt
import json
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-378"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
PROCESS_LOG = "process_logs/batch-378-mammal-underrepresented-nonsingular-past-perception-after-rule335-process.md"
LENSES = ("morphology", "lexicon", "syntax", "fidelity", "register")

NOTES = (
    "UNDERREPRESENTED NON-SINGULAR MAMMAL PAST-PERCEPTION EXPANSION AFTER RULE 335 (Rule 336). 50 rows over "
    "kaya-kaya, murral, jungarr, jayju, ngumbi, mali, kukur, murramu, darrba, and yawa. Selected bare "
    "nominatives: ngali 1du exclusive, ngaliny 1du inclusive, yubal 2du, yurra 2pl, and underrepresented nganjin "
    "1pl exclusive. Grammatical ngana 1pl inclusive was explicitly deferred because coverage was 1115 versus "
    "nganjin 268. Both orientations were collision-free; three-here/two-there reduces the support gap. Exact "
    "noun senses and all Rule 335 dialect, homonym, synonym, case, near-head, ecology, habitat, behavior, hunting, "
    "food/use, source, possession, event, nonpast/purposive/reduplicated-perception, and support boundaries remain closed."
)

LESSONS = [
    ("source", "Rule 336 freshly revalidated the ten exact non-loan fauna-mammal heads from Rule 335: kaya-kaya, murral, jungarr, jayju, ngumbi, mali, kukur, murramu, darrba, and yawa.", "Rule 336: mammal inventory."),
    ("source", "Dictionary lines reread: darrba 5306-5315, jayju 8602-8610, jungarr 10882-10892, kaya-kaya 13966-13979, kukur 15002-15010, mali 17566-17577, murral/murramu 20999-21020, ngumbi 23562-23572, and yawa/yawarr 29634-29650.", "Rule 336: dictionary source lines."),
    ("source", "Patz 1659/1730 inflected kukur and 5946-5956 former-possession mali were reread; neither licensed target case or bat/possession merger. Patz 1476, 2577-2584, 2834-2847, 2021-2024, 2568-2571, 3160-3162, and 4256-4265 source the selected construction.", "Rule 336: grammar source and boundary audit."),
    ("source", "All six non-third non-singular nominatives were compared. Nganjin 1pl exclusive had 268 verified uses versus 1115 for grammatical ngana 1pl inclusive, so nganjin was selected and ngana explicitly deferred.", "Rule 336: participant-selection audit."),
    ("source", "The exact five-pronoun x ten-target x two-deictic past grid was empty. Both orientations were collision-free; three yaluy bands reduce the deictic gap from 192 to 182 rather than increasing it to 202.", "Rule 336: construction-gap and balance audit."),
    ("process", "Rule 336 was scoped as underrepresented non-singular participant coverage, not full non-singular completion: 1pl inclusive ngana remains grammatical and deferred.", "Rule 336: bounded participant scope."),
    ("process", "All 50 rows were explicit authored calls; exact contracts, linter probes, internal uniqueness, complete 100-cell gap matrix, and both collision-free orientation matrices passed before banking.", "Rule 336: authorship and preflight."),
    ("process", "Target coverage before banking was kaya-kaya 10, murral 14, jungarr 32, jayju 33, ngumbi 33, mali 35, kukur 36, murramu 59, darrba 61, and yawa 64.", "Rule 336: target coverage audit."),
    ("process", "Support coverage before banking was ngali 603, ngaliny 545, yubal 555, yurra 540, nganjin 268, ngana 1115, yaluy 4272, yinyay 4464, and nyajin 1850.", "Rule 336: support coverage audit."),
    ("process", "Deferred ngana remains a licensed first-plural-inclusive nominative and an explicit future coverage cell; Rule 336's selection of lower-count nganjin must never be rewritten as a grammatical exclusion of ngana.", "Rule 336: deferred-participant record."),
    ("lexicon", "Kaya-kaya remained the exact whole plural dog head; free-base substitution, a new productive rule, ownership, behavior, camp, source, and events stayed closed.", "Rule 336: kaya-kaya."),
    ("lexicon", "Murral remained exact Yalanji tree-kangaroo reference; Nyungkul jarrabina substitution/equivalence, habitat, climbing, hunting, food, source, and events stayed closed.", "Rule 336: murral."),
    ("lexicon", "Jungarr retained the conservative marsupial-native-cat label; taxonomic identity, size, fierceness, predation, habitat, source, possession, and events stayed closed.", "Rule 336: jungarr."),
    ("lexicon", "Jayju remained kangaroo rat only; size, burrow, habitat, hiding, day/night activity, feeding, source, possession, and events stayed closed.", "Rule 336: jayju."),
    ("lexicon", "Ngumbi remained bandicoot; size/spot predication, burrowing, habitat, hunting, cooking, food, source, possession, and events stayed closed.", "Rule 336: ngumbi."),
    ("lexicon", "Mali remained the small-bat noun, distinct from former possession; flight, hanging, hollow, night, insects, source, possession, and events stayed closed.", "Rule 336: mali."),
    ("lexicon", "Kukur remained bare rat reference; potent case, camp/food, predation, source, possession, and events stayed closed.", "Rule 336: kukur."),
    ("lexicon", "Murramu remained exact bare dingo; ngamu-murramu synonym generation, murramungku inflection, hunting, tracking, call/family, food, source, possession, and events stayed closed.", "Rule 336: murramu."),
    ("lexicon", "Darrba remained the grass-wallaby noun and distinct from darra; size/habitat, feeding, tracks, hunting, food, ceremony, source, possession, and events stayed closed.", "Rule 336: darrba."),
    ("lexicon", "Yawa remained possum and distinct from palm yawarr; habitat, climbing, night, eye-shine, hunting, food, fur/use, source, possession, and events stayed closed.", "Rule 336: yawa."),
    ("morphology", "All Rule 336 mammal heads stayed bare absolutive objects, with no case, possession, derivation, dialect, homonym, synonym, habitat, event, property, source, or use morphology added.", "Rule 336: bare mammal O."),
    ("morphology", "Kaya-kaya stayed an exact whole plural head; murral stayed Yalanji; mali bat stayed distinct from former possession; kukur and murramu stayed bare; darrba/yawa stayed distinct from darra/yawarr.", "Rule 336: lexical-form restraint."),
    ("morphology", "All subject forms stayed bare non-singular nominatives: ngali, ngaliny, yubal, yurra, and nganjin. No ngana substitution, third-person substitution, or pronoun case was admitted.", "Rule 336: selected non-singular A forms."),
    ("morphology", "Yaluy, yinyay, and nyajin stayed fixed; no demonstrative case, Nyungkul substitution, nonpast nyajil, purposive nyaji-nka, reduplicated watching, hearing/smell compound, or support inflection entered.", "Rule 336: fixed support morphology."),
    ("syntax", "Rows 1-10 used Ngali TARGET yaluy nyajin for first-dual-exclusive here past visual perception.", "Rule 336: 1du exclusive here band."),
    ("syntax", "Rows 11-20 used Ngaliny TARGET yinyay nyajin for first-dual-inclusive there past visual perception.", "Rule 336: 1du inclusive there band."),
    ("syntax", "Rows 21-30 used Yubal TARGET yaluy nyajin for second-dual here past visual perception.", "Rule 336: 2du here band."),
    ("syntax", "Rows 31-40 used Yurra TARGET yinyay nyajin for second-plural there past visual perception.", "Rule 336: 2pl there band."),
    ("syntax", "Rows 41-50 used Nganjin TARGET yaluy nyajin for first-plural-exclusive here past visual perception.", "Rule 336: 1pl exclusive here band."),
    ("fidelity", "English overtly preserved dual and exclusive/inclusive contrasts: ngali 'we two, not you', ngaliny 'you and I', yubal 'you two', yurra 'you all', and nganjin 'we, not you'.", "Rule 336: participant fidelity."),
    ("fidelity", "English added only selected observer, exact conservative mammal label, here/there, and saw. No source cross-reference, rich prior row, dialect, homonym, synonym, case, ecology, behavior, use, or event was imported.", "Rule 336: literal English and source restraint."),
    ("register", "Rows remained neutral elicitation-style mammal-reference clauses; hunting, killing, tracking, camp food, cultural practice, ecology, danger, and event-heavy readings stayed closed.", "Rule 336: register and cultural restraint."),
    ("process", "Every Rule 336 sentence is an explicit sequence-specific row call with exact Kuku, English, analysis, evidence, and confidence contracts; no runtime generator authored content.", "Rule 336: explicit-row authorship evidence."),
    ("process", "Rules 149-335 carry-forward traps stayed closed, including all Rule 335 dialect, homonym, synonym, case, near-head, ecology, habitat, behavior, hunting, food/use, source, possession, and event boundaries.", "Rule 336: cumulative trap closure."),
    ("handoff", "Next batch may continue from 18,997 if this closes; Rule 337 requires a fresh source and coverage audit. The deferred ngana cells remain an explicit option, not an automatic mandate.", "Rule 336: next cadence."),
]

LEXEMES = [
    ("kaya-kaya", "noun", None, "NA", "dogs", "batch-378: exact plural dog head in selected non-singular past perception only; free-base/productive extension/ownership/behavior/source/event content closed."),
    ("murral", "noun", None, "NA", "tree kangaroo", "batch-378: exact Yalanji head in selected non-singular past perception only; jarrabina substitution/equivalence/habitat/hunting/food/source/event content closed."),
    ("jungarr", "noun", None, "NA", "marsupial native cat", "batch-378: conservative label in selected non-singular past perception only; taxonomic/property/predation/habitat/source/event content closed."),
    ("jayju", "noun", None, "NA", "kangaroo rat", "batch-378: selected non-singular past perception only; size/burrow/habitat/activity/feeding/source/event content closed."),
    ("ngumbi", "noun", None, "NA", "bandicoot", "batch-378: selected non-singular past perception only; size/spot/burrow/habitat/hunting/food/source/event content closed."),
    ("mali", "noun", None, "NA", "small bat", "batch-378: bat noun in selected non-singular past perception only; former-possession homonym/flight/hollow/night/insect/source/event content closed."),
    ("kukur", "noun", None, "NA", "rat", "batch-378: bare rat in selected non-singular past perception only; potent case/camp/food/predation/source/event content closed."),
    ("murramu", "noun", None, "NA", "dingo", "batch-378: exact bare dingo in selected non-singular past perception only; synonym/inflection/hunting/tracking/call/food/source/event content closed."),
    ("darrba", "noun", None, "NA", "grass wallaby", "batch-378: exact noun in selected non-singular past perception only; darra confusion/habitat/hunting/food/ceremony/source/event content closed."),
    ("yawa", "noun", None, "NA", "possum", "batch-378: exact noun in selected non-singular past perception only; yawarr confusion/habitat/night/hunting/food/fur/source/event content closed."),
    ("ngali", "pronoun", None, "NA", "first dual exclusive nominative", "batch-378: bare nominative subject support only."),
    ("ngaliny", "pronoun", None, "NA", "first dual inclusive nominative", "batch-378: bare nominative subject support only."),
    ("yubal", "pronoun", None, "NA", "second dual nominative", "batch-378: bare nominative subject support only."),
    ("yurra", "pronoun", None, "NA", "second plural nominative", "batch-378: bare nominative subject support only."),
    ("nganjin", "pronoun", None, "NA", "first plural exclusive nominative", "batch-378: underrepresented bare nominative subject support selected over higher-coverage ngana."),
    ("yaluy", "demonstrative", None, "NA", "here", "batch-378: bare Yalanji local demonstrative support only."),
    ("yinyay", "demonstrative", None, "NA", "there", "batch-378: bare Yalanji local demonstrative support only."),
    ("nyajin", "verb-tr", "ny", "NA", "see; see.PST", "batch-378: dictionary-attested past visual-perception surface corresponding to Patz nyaji-ny."),
]


def main() -> int:
    if len(LESSONS) != 35: raise SystemExit(f"lesson inventory changed: {len(LESSONS)} != 35")
    if len(LEXEMES) != 18: raise SystemExit(f"lexeme inventory changed: {len(LEXEMES)} != 18")
    db = sqlite3.connect(DB); db.execute("PRAGMA foreign_keys=ON"); db.execute("BEGIN"); ensure_schema(db)
    batch = db.execute("SELECT id FROM batches WHERE label=?", (LABEL,)).fetchone()
    if not batch: raise SystemExit(f"{LABEL} has not been banked")
    bid = batch[0]; total, ur, ac = db.execute("SELECT COUNT(*),COUNT(*) FILTER(WHERE status='under_review'),COUNT(*) FILTER(WHERE status IN ('accepted','revised')) FROM sentences WHERE batch_id=?", (bid,)).fetchone()
    if total != 50 or ur != 50 or ac: raise SystemExit(f"close precheck failed total={total} under_review={ur} accepted={ac}")
    er = db.execute("SELECT COUNT(*) FROM reviews WHERE sentence_id IN (SELECT id FROM sentences WHERE batch_id=?)", (bid,)).fetchone()[0]; el = db.execute("SELECT COUNT(*) FROM lessons WHERE batch_id=?", (bid,)).fetchone()[0]; eg = db.execute("SELECT COUNT(*) FROM lexeme_log WHERE action='batch-378-verify'").fetchone()[0]
    if er or el or eg: raise SystemExit(f"non-destructive close precheck failed reviews={er} lessons={el} logs={eg}")
    total_rows = db.execute("SELECT COUNT(*) FROM sentences WHERE status!='rejected'").fetchone()[0]; before, words_before = db.execute("SELECT COUNT(*),SUM(LENGTH(kuku)-LENGTH(REPLACE(kuku,' ',''))+1) FROM sentences WHERE status IN ('accepted','revised')").fetchone(); ids = [r[0] for r in db.execute("SELECT id FROM sentences WHERE batch_id=? ORDER BY seq", (bid,))]
    db.executemany("INSERT INTO reviews(sentence_id,round,lens,verdict,issues,suggested_fix,reviewer,created_at) VALUES(?,?,?,?,?,?,?,?)", [(sid, 1, lens, "pass", None, None, "codex-main-five-lens", NOW) for sid in ids for lens in LENSES])
    db.executemany("INSERT INTO lessons(batch_id,category,lesson,guide_change,created_at) VALUES(?,?,?,?,?)", [(bid, c, l, g, NOW) for c, l, g in LESSONS])
    for head, pos, conj, case_class, gloss, note in LEXEMES:
        senses = json.dumps([{"sense": gloss, "definition": note, "status": "attested"}], ensure_ascii=False); att = json.dumps([{"source": LABEL, "ref": "five-lens close", "quote": note}], ensure_ascii=False)
        db.execute("""INSERT INTO lexemes(headword,phonemic,pos,conj_class,case_class,gloss,senses,attestation,allomorphy,morphology,collocations,usage_notes,antonyms_contrasts,corpus_freq,status,verified_at,notes) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) ON CONFLICT(headword) DO UPDATE SET verified_at=excluded.verified_at,status=excluded.status,notes=CASE WHEN lexemes.notes IS NULL OR lexemes.notes='' THEN excluded.notes WHEN instr(lexemes.notes,?)>0 THEN lexemes.notes ELSE lexemes.notes||'; '||excluded.notes END""", (head, None, pos, conj, case_class, gloss, senses, att, None, None, None, note, None, 0, "verified", NOW, note, LABEL))
        db.execute("INSERT INTO lexeme_log(headword,action,detail,created_at) VALUES(?,?,?,?)", (head, "batch-378-verify", note, NOW))
    record_event(db, batch_label=LABEL, phase="lint", event_type="under-review-lint-green", actor="codex", detail=f"After banking, whole-corpus lint scanned {total_rows} rows and found 0 issues; verified remained {before} before close.", command="python3 lint_corpus.py", output_excerpt=f"lint: {total_rows} rows scanned, 0 issues; GOAL {before}/20000 ({words_before} words)", artifact_path=PROCESS_LOG, created_at=NOW)
    record_event(db, batch_label=LABEL, phase="review", event_type="five-lens-pass", actor="codex", detail="Manual five-lens review passed all 50 Rule 336 rows: bare mammal O, selected bare non-singular nominative A including underrepresented nganjin, fixed Yalanji local/past support, exact dictionary heads, participant-faithful English, and neutral register; every Rule 335 lexical/event boundary remained closed.", artifact_path=PROCESS_LOG, created_at=NOW)
    record_event(db, batch_label=LABEL, phase="review", event_type="review-detail", actor="codex", detail="No ngana substitution, third-person substitution, kaya free-base/productive extension, jarrabina dialect substitution, mali former-possession reading, kukur case, murramu synonym/inflection, darra/yawarr confusion, rich event, target/pronoun case, or support drift remained.", artifact_path=PROCESS_LOG, created_at=NOW)
    record_event(db, batch_label=LABEL, phase="review", event_type="lesson-inventory", actor="codex", detail=f"Inserted {len(LESSONS)} Rule 336 lessons covering source, participant selection, exact gap, deictic balance, coverage, lexical boundaries, morphology, syntax, participant fidelity, register, authorship, traps, and handoff.", artifact_path=PROCESS_LOG, created_at=NOW)
    record_event(db, batch_label=LABEL, phase="review", event_type="lexeme-source-log", actor="codex", detail=f"Inserted {len(LEXEMES)} lexeme/source-log rows: ten targets and eight support heads.", artifact_path=PROCESS_LOG, created_at=NOW)
    db.execute("UPDATE sentences SET status='accepted',updated_at=? WHERE batch_id=?", (NOW, bid)); db.execute("UPDATE batches SET notes=?,cheatsheet_version=?,guide_version=? WHERE id=?", (NOTES, "Rule 336 accepted", "operator-guide-2026-07-10", bid))
    after, words_after = db.execute("SELECT COUNT(*),SUM(LENGTH(kuku)-LENGTH(REPLACE(kuku,' ',''))+1) FROM sentences WHERE status IN ('accepted','revised')").fetchone(); accepted = db.execute("SELECT COUNT(*) FROM sentences WHERE batch_id=? AND status='accepted'", (bid,)).fetchone()[0]; reviews = db.execute("SELECT COUNT(*) FROM reviews WHERE sentence_id IN (SELECT id FROM sentences WHERE batch_id=?)", (bid,)).fetchone()[0]; lessons = db.execute("SELECT COUNT(*) FROM lessons WHERE batch_id=?", (bid,)).fetchone()[0]; logs = db.execute("SELECT COUNT(*) FROM lexeme_log WHERE action='batch-378-verify'").fetchone()[0]
    record_event(db, batch_label=LABEL, phase="close", event_type="close-success", actor="codex", detail=f"Closed Batch 378 / Rule 336: {accepted} accepted, {reviews} reviews, {lessons} lessons, {logs} lexeme logs; verified {before}->{after}; Kuku words {words_before}->{words_after}.", command="python3 batch_scripts/close_378.py", output_excerpt=f"closed batch-378 accepted={accepted} reviews={reviews} lessons={lessons} lexeme_logs={logs} verified {before}->{after} words {words_before}->{words_after}", artifact_path=PROCESS_LOG, created_at=NOW)
    db.commit(); print(f"closed batch-378: accepted={accepted}, reviews={reviews}, lessons={lessons}, lexeme_logs={logs}, verified {before}->{after}, kuku_words {words_before}->{words_after}"); return 0


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