#!/usr/bin/env python3
"""Close batch-377 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-377"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
PROCESS_LOG = "process_logs/batch-377-mammal-singular-third-past-perception-after-rule334-process.md"
LENSES = ("morphology", "lexicon", "syntax", "fidelity", "register")

NOTES = (
    "MAMMAL SINGULAR/THIRD-PERSON PAST-PERCEPTION COMPLETION AFTER RULE 334 (Rule 335). 50 rows. TARGETS: "
    "kaya-kaya dogs, murral tree kangaroo, jungarr marsupial native cat, jayju kangaroo rat, ngumbi bandicoot, "
    "mali small bat, kukur rat, murramu dingo, darrba grass wallaby, yawa possum. SUPPORT: bare nominative "
    "ngayu, yundu, nyulu, bula, jana; Yalanji yaluy/yinyay; dictionary-attested past nyajin. The exact four-token "
    "bare-target past grid was empty in both deictic orientations; three-here/two-there reduces the support gap. "
    "Exact noun senses only; no free-base/productive reduplication, Nyungkul substitution, synonym generation, "
    "mali former-possession homonym, kukur case, inflected murramungku, darra/yawarr confusion, body/property, "
    "habitat, behavior, hunting, food/use, source, possession, cultural event, target case, nonpast/purposive/"
    "reduplicated perception, support inflection, or prior-row event was opened."
)

LESSONS = [
    ("source", "Rule 335 freshly selected ten exact non-loan fauna-mammal heads: kaya-kaya, murral, jungarr, jayju, ngumbi, mali, kukur, murramu, darrba, and yawa.", "Rule 335: 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 335: dictionary source lines."),
    ("source", "Fresh Patz target search found inflected kukur rat examples at lines 1659 and 1730 and homophonous mali former-possession material at 5946-5956; no grammar occurrence licensed a new mammal event or a bat/possession merger.", "Rule 335: Patz target and homonym audit."),
    ("source", "Patz line 1476 includes fauna among noun referents; 2577-2586 source selected nominatives, 2834-2847 Yalanji yaluy/yinyay, 2021-2024 and 2568-2571 past nyaji-ny, 3160-3162 past -ny, and 4256-4265 perception A/O; dictionary examples 23876-23883 and 23968-23976 contain running nyajin.", "Rule 335: construction source."),
    ("source", "The exact five-pronoun x ten-target x two-deictic four-token past grid was empty. Both orientations were collision-free; three yaluy bands reduce the support gap from 202 to 192 rather than increasing it to 212.", "Rule 335: construction-gap and balance audit."),
    ("process", "Rule 335 was scoped as bare-target singular/third-person past-perception completion, not dialect alignment, homonym resolution, synonym generation, morphology, ecology, behavior, hunting, food/use, source, possession, property, or cultural-event expansion.", "Rule 335: bounded scope."),
    ("process", "All 50 rows were explicit authored calls; exact contracts, linter probes, internal uniqueness, the complete two-deictic gap matrix, and both collision-free orientation matrices passed before banking.", "Rule 335: authorship and preflight."),
    ("process", "Target coverage before banking was kaya-kaya 5, murral 9, jungarr 27, jayju 28, ngumbi 28, mali 30, kukur 31, murramu 54, darrba 56, and yawa 59.", "Rule 335: target coverage audit."),
    ("process", "Support coverage before banking was ngayu 1441, yundu 1037, nyulu 712, bula 508, jana 1213, yaluy 4242, yinyay 4444, and nyajin 1800.", "Rule 335: support coverage audit."),
    ("lexicon", "Kaya-kaya remained the exact whole plural dog head. The source records full reduplication from kaya, but Rule 335 generated no free-base substitution, new productive-reduplication generalization, ownership, behavior, camp, source, or event claim.", "Rule 335: kaya-kaya."),
    ("lexicon", "Murral remained exact Yalanji tree-kangaroo reference. Nyungkul jarrabina substitution/equivalence generation, tree/canopy habitat, climbing, sleeping, hunting, spearing, catching, food, source, and events stayed closed.", "Rule 335: murral."),
    ("lexicon", "Jungarr retained the conservative dictionary label marsupial native cat. Modern taxonomic equivalence, size, fierceness, hunting, rat/bird predation, branch/nest/night behavior, source, possession, and events stayed closed.", "Rule 335: jungarr."),
    ("lexicon", "Jayju remained kangaroo rat only; size, burrow, sand/grass habitat, hiding, day/night activity, seed/root feeding, source, possession, and events stayed closed.", "Rule 335: jayju."),
    ("lexicon", "Ngumbi remained the bandicoot noun from the little-spotted-bandicoot record; size/spot predication, burrowing, grass habitat, night activity, hunting, catching, cooking, food, source, possession, and events stayed closed.", "Rule 335: ngumbi."),
    ("lexicon", "Mali remained the small-bat noun. Patz's homophonous former-possession particle/suffix/clitic, flight, hanging, hollow, night, insect-catching, source, possession, and events stayed closed.", "Rule 335: mali."),
    ("lexicon", "Kukur remained bare rat reference. Patz kukur-uku/kukur-undu potent case examples licensed no target case, camp/food, night, predation, source, possession, or event proposition.", "Rule 335: kukur."),
    ("lexicon", "Murramu remained exact bare dingo reference. Dictionary synonym ngamu-murramu, inflected murramungku, decomposition, wild-dog relation, hunting, tracking, call/howl, family, food, source, possession, and events stayed closed.", "Rule 335: murramu."),
    ("lexicon", "Darrba remained the grass-wallaby noun and distinct from nearby adjective darra 'narrow, too small'; size, grass habitat, feeding, tracks, hunting, spearing, food, ceremony, source, possession, and events stayed closed.", "Rule 335: darrba."),
    ("lexicon", "Yawa remained possum and distinct from nearby palm noun yawarr; tree/hollow habitat, climbing, sleeping, night activity, eye-shine, hunting, catching, biting, food, fur/cloak, source, possession, and events stayed closed.", "Rule 335: yawa."),
    ("morphology", "All Rule 335 mammal heads stayed bare absolutive objects, with no case, possession, derivation, dialect, homonym, synonym, habitat, event, property, source, or use morphology added.", "Rule 335: bare mammal O."),
    ("morphology", "Kaya-kaya remained an exact whole hyphenated plural head. Its record-specific full-reduplication analysis licensed no arbitrary free base, new productive rule, spelling variant, derivation, or event.", "Rule 335: kaya-kaya form restraint."),
    ("morphology", "Mali bat remained distinct from the uninflected former-possession homonym; kukur remained bare rather than potent kukur-uku/kukur-undu; murramu remained bare rather than inflected murramungku.", "Rule 335: homonym and case restraint."),
    ("morphology", "All subject forms stayed bare nominatives: ngayu, yundu, nyulu, bula, and jana. No non-singular substitution beyond selected third dual/plural, accusative, dative, local, ablative, comitative, possessive, or expanded pronoun was admitted.", "Rule 335: selected pronoun A forms."),
    ("morphology", "Yaluy, yinyay, and nyajin stayed fixed support; no demonstrative case, Nyungkul substitution, nonpast nyajil, purposive nyaji-nka, reduplicated watching, hearing/smell compound, or support inflection was admitted.", "Rule 335: fixed support morphology."),
    ("syntax", "Rows 1-10 used Ngayu TARGET yaluy nyajin for first-singular here past visual perception.", "Rule 335: 1sg here band."),
    ("syntax", "Rows 11-20 used Yundu TARGET yinyay nyajin for second-singular there past visual perception.", "Rule 335: 2sg there band."),
    ("syntax", "Rows 21-30 used Nyulu TARGET yaluy nyajin for third-singular here past visual perception.", "Rule 335: 3sg here band."),
    ("syntax", "Rows 31-40 used Bula TARGET yinyay nyajin for third-dual there past visual perception.", "Rule 335: 3du there band."),
    ("syntax", "Rows 41-50 used Jana TARGET yaluy nyajin for third-plural here past visual perception.", "Rule 335: 3pl here band."),
    ("fidelity", "English stayed literal past visual-perception prose: selected observer, exact conservative mammal label, here or there, and saw only. Labels do not assert dialect identity, homonym resolution, synonymy, morphology, ecology, behavior, hunting, food/use, source, or events.", "Rule 335: literal English."),
    ("fidelity", "No dictionary cross-reference, Patz case example, former-possession homonym, nearby head, or rich historical corpus row was converted into a new equivalence, habitat, behavior, hunting, food, property, source, possession, or cultural-practice claim.", "Rule 335: source and prior-row restraint."),
    ("register", "Rows remained neutral elicitation-style mammal-reference clauses. Hunting, killing, tracking, camp food, sacred/cultural practice, ecology, danger, and event-heavy readings stayed closed.", "Rule 335: register and cultural restraint."),
    ("process", "Every Rule 335 sentence is an explicit sequence-specific row call with exact Kuku, English, analysis, evidence, and confidence contracts; no runtime generator authored content.", "Rule 335: explicit-row authorship evidence."),
    ("process", "Rules 149-334 carry-forward traps stayed closed, including all Rule 333-334 bird boundaries and the new Rule 335 dialect, homonym, synonym, case, habitat, behavior, hunting, food/use, source, possession, and event boundaries.", "Rule 335: cumulative trap closure."),
    ("handoff", "Next batch may continue from 18,947 if this closes; Rule 336 requires a fresh source and coverage audit and must not infer closed mammal dialect, homonym, synonym, morphology, ecology, behavior, hunting, food/use, source, possession, event, case, perception, or support fields.", "Rule 335: next cadence."),
]

LEXEMES = [
    ("kaya-kaya", "noun", None, "NA", "dogs", "batch-377: exact plural dog head in bare past perception only; free-base/productive-reduplication/ownership/behavior/camp/source/event content closed."),
    ("murral", "noun", None, "NA", "tree kangaroo", "batch-377: exact Yalanji head in bare past perception only; jarrabina substitution/equivalence/habitat/climbing/hunting/food/source/event content closed."),
    ("jungarr", "noun", None, "NA", "marsupial native cat", "batch-377: conservative dictionary label in bare past perception only; taxonomic equivalence/property/predation/habitat/source/event content closed."),
    ("jayju", "noun", None, "NA", "kangaroo rat", "batch-377: bare past perception only; size/burrow/habitat/day-night/feeding/source/possession/event content closed."),
    ("ngumbi", "noun", None, "NA", "bandicoot", "batch-377: bare past perception only; size/spot/burrow/habitat/hunting/cooking/food/source/possession/event content closed."),
    ("mali", "noun", None, "NA", "small bat", "batch-377: bat noun in bare past perception only; former-possession homonym/flight/hanging/hollow/night/insect/source/possession/event content closed."),
    ("kukur", "noun", None, "NA", "rat", "batch-377: bare past perception only; potent case/camp/food/night/predation/source/possession/event content closed."),
    ("murramu", "noun", None, "NA", "dingo", "batch-377: exact bare head in past perception only; ngamu-murramu synonym/murramungku inflection/hunting/tracking/call/family/food/source/event content closed."),
    ("darrba", "noun", None, "NA", "grass wallaby", "batch-377: exact noun in bare past perception only; darra confusion/size/habitat/feeding/tracks/hunting/food/ceremony/source/event content closed."),
    ("yawa", "noun", None, "NA", "possum", "batch-377: exact noun in bare past perception only; yawarr palm/habitat/climbing/night/hunting/food/fur/source/possession/event content closed."),
    ("ngayu", "pronoun", None, "NA", "first singular nominative", "batch-377: bare nominative subject support only."),
    ("yundu", "pronoun", None, "NA", "second singular nominative", "batch-377: bare nominative subject support only."),
    ("nyulu", "pronoun", None, "NA", "third singular nominative", "batch-377: bare nominative subject support only."),
    ("bula", "pronoun", None, "NA", "third dual nominative", "batch-377: bare nominative subject support only."),
    ("jana", "pronoun", None, "NA", "third plural nominative", "batch-377: bare nominative subject support only."),
    ("yaluy", "demonstrative", None, "NA", "here", "batch-377: bare Yalanji local demonstrative support only."),
    ("yinyay", "demonstrative", None, "NA", "there", "batch-377: bare Yalanji local demonstrative support only."),
    ("nyajin", "verb-tr", "ny", "NA", "see; see.PST", "batch-377: 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-377-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-377-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 335 rows: bare mammal O morphology, bare selected nominative pronoun A, fixed Yalanji local/past support, exact dictionary mammal heads and conservative labels, literal English fidelity, and neutral elicitation register; every dialect, homonym, synonym, case, morphology, ecology, behavior, hunting, food/use, source, possession, and event field 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 kaya free-base/productive extension, jarrabina substitution, mali former-possession reading, kukur case, ngamu-murramu synonym statement, murramungku inflection, darra/yawarr confusion, rich prior-row event, target case, nonpast/purposive/reduplicated perception, 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 335 lessons covering source, homonym/case evidence, exact record boundaries, construction gap, deictic balance, coverage, lexical senses, morphology, syntax, 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 335 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-377-verify'").fetchone()[0]
    record_event(db, batch_label=LABEL, phase="close", event_type="close-success", actor="codex", detail=f"Closed Batch 377 / Rule 335: {accepted} accepted, {reviews} reviews, {lessons} lessons, {logs} lexeme logs; verified {before}->{after}; Kuku words {words_before}->{words_after}.", command="python3 batch_scripts/close_377.py", output_excerpt=f"closed batch-377 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-377: 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())
