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

NOTES = (
    "BIRD NON-SINGULAR PAST-PERCEPTION CONSOLIDATION AFTER RULE 333 (Rule 334). 50 rows. TARGETS: jiwal-jiwal "
    "kingfisher, kalmbangarr black diver bird, karkunbay stockwhip bird, mirrki kidney bird, mulumu dove, "
    "karunkurr crested pigeon, munungkul ground pigeon, jurriyan satin bower bird, juku-juku bronzewing dove, "
    "dawa-dawa magpie. SUPPORT: bare nominative ngali, ngaliny, yubal, yurra, ngana; Yalanji yaluy/yinyay; "
    "dictionary-attested past nyajin. No target previously occurred in non-singular past perception. Both deictic "
    "orientations were collision-free; three-here/two-there reduces the support gap. Exact record and bird senses "
    "only; no variant equivalence, free base, productive morphology, homonym merger, body/colour, call/song, "
    "habitat, behavior, totem/moiety, ceremony, omen/death, source, possession, target case, singular/third-person "
    "subject, nonpast/purposive/reduplicated perception, support inflection, or event proposition was opened."
)

LESSONS = [
    ("source", "Rule 334 freshly revalidated the ten exact non-loan fauna-bird heads from Rule 333: jiwal-jiwal, kalmbangarr, karkunbay, mirrki, mulumu, karunkurr, munungkul, jurriyan, juku-juku, and dawa-dawa.", "Rule 334: consolidation inventory."),
    ("source", "Dictionary lines reread: dawa-dawa/dawadawa 5326-5354, jiwal-jiwal 9998-10011, juku-juku/jukujuku 10350-10379, jurriyam/jurriyan 11298-11318, kalmbangarr/kalmnbagarr 12791-12808, karkunbay 13524-13533, karunkurr 13815-13823, kurkumbay/kurkunbay 16124-16143, mirrki/mirrku 19792-19813, mulumu 20512-20524, and munungkul 20827-20835.", "Rule 334: dictionary source lines."),
    ("source", "Fresh exact Patz target/variant search again found only juku-juku at lines 1941 and 1976 in the unrelated reduplicated-tree sense; the homonym licenses no bird identity, morphology, or event.", "Rule 334: Patz homonym audit."),
    ("source", "Patz line 1476 includes fauna among noun referents, licensing bare visible-bird reference without importing body, call, habitat, behavior, cultural role, source, property, or event content.", "Rule 334: fauna noun source."),
    ("source", "Patz lines 2577-2584 source selected non-singular 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 334: construction source."),
    ("source", "No selected bird had any non-singular past-perception row. Both deictic orientations were collision-free; the three-yaluy/two-yinyay layout was selected because it reduces the support gap from 212 to 202 rather than increasing it to 222.", "Rule 334: construction-gap and deictic-balance audit."),
    ("process", "Rule 334 was scoped as non-singular participant-number consolidation in past visual perception, not variant equivalence, secondary sense, homonym, body/call, habitat, behavior, cultural role, source, possession, property, or event content.", "Rule 334: bounded construction scope."),
    ("process", "All 50 rows were explicit authored calls; exact static contracts, row-level linter probes, internal uniqueness, construction-gap proof, and both collision-free orientation matrices passed before banking.", "Rule 334: authorship and preflight."),
    ("process", "Target coverage before banking was jiwal-jiwal 10, kalmbangarr 10, karkunbay 10, mirrki 10, mulumu 10, karunkurr 11, munungkul 11, jurriyan 11, juku-juku 12, and dawa-dawa 13.", "Rule 334: target coverage audit."),
    ("process", "Support coverage before banking was ngali 593, ngaliny 535, yubal 545, yurra 530, ngana 1105, yaluy 4212, yinyay 4424, and nyajin 1750.", "Rule 334: support coverage audit."),
    ("lexicon", "Jiwal-jiwal remained the exact whole kingfisher head; free-base use, productive reduplication, tail/colour, flight, call, hunting, water habitat, source, possession, and events stayed closed.", "Rule 334: jiwal-jiwal."),
    ("lexicon", "Kalmbangarr remained exact complete-record black-diver-bird reference; kalmnbagarr normalization/equivalence, colour predication, diving, habitat, source, possession, and events stayed closed.", "Rule 334: kalmbangarr."),
    ("lexicon", "Karkunbay remained exact stockwhip-bird reference; kurkunbay/kurkumbay equivalence, butcherbird identity, call/sound, behavior, source, possession, and events stayed closed.", "Rule 334: karkunbay."),
    ("lexicon", "Mirrki remained exact kidney-bird reference; mirrku identity/equivalence, totem, dabu, moiety, ceremony, source, possession, and events stayed closed.", "Rule 334: mirrki."),
    ("lexicon", "Mulumu remained in the primary dove sense only; wood/material identity, sacred/corroboree use, ceremony, source, possession, and events stayed closed.", "Rule 334: mulumu."),
    ("lexicon", "Karunkurr remained crested pigeon only; crest/body, walking, feeding, seed, track, habitat, source, possession, and events stayed closed.", "Rule 334: karunkurr."),
    ("lexicon", "Munungkul remained ground pigeon only; ground/location predication, feeding, leaves, trees, habitat, source, possession, and events stayed closed.", "Rule 334: munungkul."),
    ("lexicon", "Jurriyan remained the exact final-n satin-bower-bird head; final-m jurriyam normalization/equivalence, feather/colour, collecting, bower behavior, source, possession, and events stayed closed.", "Rule 334: jurriyan."),
    ("lexicon", "Juku-juku remained only the exact dictionary bronzewing-dove head; free-base/productive reduplication, Patz tree homonym, jukujuku identity, omen, stranger, death, call, source, possession, and events stayed closed.", "Rule 334: juku-juku."),
    ("lexicon", "Dawa-dawa remained the exact hyphenated magpie head; free-base/productive reduplication, dawadawa identity/equivalence, call/song, time/news, country, source, possession, and events stayed closed.", "Rule 334: dawa-dawa."),
    ("morphology", "All Rule 334 bird heads stayed bare absolutive objects, with no case, number, possession, derivation, variant, habitat, event, property, source, or use morphology added.", "Rule 334: bare bird O."),
    ("morphology", "Jiwal-jiwal, juku-juku, and dawa-dawa remained exact whole hyphenated heads. No free base, productive reduplication, unhyphenated-form equivalence, spelling normalization, homonym merger, derivation, number reading, or identity claim was generated.", "Rule 334: lexicalized and variant-form restraint."),
    ("morphology", "All subject forms stayed bare non-singular nominatives: ngali, ngaliny, yubal, yurra, and ngana. No singular/third-person subject, accusative, dative, locative, ablative, comitative, possessive, or expanded pronoun was admitted.", "Rule 334: non-singular 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 334: fixed support morphology."),
    ("syntax", "Rows 1-10 used Ngali TARGET yaluy nyajin for first-dual-exclusive here past visual perception.", "Rule 334: 1du exclusive here band."),
    ("syntax", "Rows 11-20 used Ngaliny TARGET yinyay nyajin for first-dual-inclusive there past visual perception.", "Rule 334: 1du inclusive there band."),
    ("syntax", "Rows 21-30 used Yubal TARGET yaluy nyajin for second-dual here past visual perception.", "Rule 334: 2du here band."),
    ("syntax", "Rows 31-40 used Yurra TARGET yinyay nyajin for second-plural there past visual perception.", "Rule 334: 2pl there band."),
    ("syntax", "Rows 41-50 used Ngana TARGET yaluy nyajin for first-plural-inclusive here past visual perception.", "Rule 334: 1pl inclusive here band."),
    ("fidelity", "English stayed literal past visual-perception and participant-number prose: selected observer, exact conservative bird label, here or there, and saw only. Labels do not assert variant identity, morphology, body, call, habitat, behavior, cultural role, source, or events.", "Rule 334: literal English."),
    ("fidelity", "No dictionary cross-reference, nearby spelling, Patz tree homonym, secondary cultural sense, earlier rich row, or reduplication note was converted into equivalence, ecology, behavior, omen, ceremony, source, possession, property, or cultural-practice claims.", "Rule 334: source and prior-row restraint."),
    ("register", "Rows remained neutral elicitation-style bird-reference clauses. The consolidation adds participant-number contrasts only; totem/moiety, sacred-corroboree, omen/death, call/news/time, hunting, habitat, and event-heavy readings stayed closed.", "Rule 334: register and cultural restraint."),
    ("process", "Every Rule 334 sentence is an explicit sequence-specific row call with exact Kuku, English, analysis, evidence, and confidence contracts; no runtime generator authored content.", "Rule 334: explicit-row authorship evidence."),
    ("process", "Rules 149-333 carry-forward traps stayed closed, including bird variant identity, homonym, body/colour, flight/call/song, habitat, behavior, totem/moiety, ceremony, omen/death, source, possession, case, productive reduplication, and support-inflection traps.", "Rule 334: cumulative trap closure."),
    ("handoff", "Next batch may continue from 18,897 if this closes; Rule 335 requires a fresh source and coverage audit and must not infer closed bird variant-equivalence, morphology, homonym, body/call, habitat, behavior, cultural-role, source, possession, event, case, perception, or support fields.", "Rule 334: next cadence."),
]

LEXEMES = [
    ("jiwal-jiwal", "noun", None, "NA", "kingfisher", "batch-376: non-singular past-perception consolidation only; base/productive-reduplication/tail/colour/flight/call/hunting/habitat/source/possession/event content closed."),
    ("kalmbangarr", "noun", None, "NA", "black diver bird", "batch-376: exact head in non-singular perception only; kalmnbagarr normalization/equivalence/colour/diving/habitat/source/possession/event content closed."),
    ("karkunbay", "noun", None, "NA", "stockwhip bird", "batch-376: exact head in non-singular perception only; kurkunbay/kurkumbay equivalence/butcherbird/call/behavior/source/possession/event content closed."),
    ("mirrki", "noun", None, "NA", "kidney bird", "batch-376: exact head in non-singular perception only; mirrku equivalence/totem/dabu/moiety/ceremony/source/possession/event content closed."),
    ("mulumu", "noun", None, "NA", "dove", "batch-376: primary dove sense in non-singular perception only; wood/material/sacred/corroboree/ceremony/source/possession/event content closed."),
    ("karunkurr", "noun", None, "NA", "crested pigeon", "batch-376: non-singular perception only; crest/body/walking/feeding/seed/track/habitat/source/possession/event content closed."),
    ("munungkul", "noun", None, "NA", "ground pigeon", "batch-376: non-singular perception only; ground/location/feeding/leaves/trees/habitat/source/possession/event content closed."),
    ("jurriyan", "noun", None, "NA", "satin bower bird", "batch-376: exact final-n head in non-singular perception only; jurriyam normalization/equivalence/feather/colour/collecting/bower/source/possession/event content closed."),
    ("juku-juku", "noun", None, "NA", "bronzewing dove", "batch-376: exact dictionary bird head in non-singular perception only; base/productive-reduplication/tree homonym/jukujuku equivalence/omen/stranger/death/call/source/possession/event content closed."),
    ("dawa-dawa", "noun", None, "NA", "magpie", "batch-376: exact hyphenated head in non-singular perception only; base/productive-reduplication/dawadawa equivalence/call/song/time/news/country/source/possession/event content closed."),
    ("ngali", "pronoun", None, "NA", "first dual exclusive nominative", "batch-376: bare nominative subject support only."),
    ("ngaliny", "pronoun", None, "NA", "first dual inclusive nominative", "batch-376: bare nominative subject support only."),
    ("yubal", "pronoun", None, "NA", "second dual nominative", "batch-376: bare nominative subject support only."),
    ("yurra", "pronoun", None, "NA", "second plural nominative", "batch-376: bare nominative subject support only."),
    ("ngana", "pronoun", None, "NA", "first plural inclusive nominative", "batch-376: bare nominative subject support only."),
    ("yaluy", "demonstrative", None, "NA", "here", "batch-376: bare Yalanji local demonstrative support only."),
    ("yinyay", "demonstrative", None, "NA", "there", "batch-376: bare Yalanji local demonstrative support only."),
    ("nyajin", "verb-tr", "ny", "NA", "see; see.PST", "batch-376: 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-376-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-376-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 334 rows: bare bird O morphology, bare nominative non-singular pronoun A, fixed Yalanji local/past support, exact dictionary bird heads and conservative labels, literal participant-number English fidelity, and neutral elicitation register; every variant-equivalence, secondary-sense, homonym, cultural-role, morphology, habitat, behavior, 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 near-record identity, mulumu wood/corroboree, mirrki totem/moiety, juku-juku tree/omen/death, call/song, target case, singular/third-person subject, 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 334 lessons covering source, Patz homonym, exact record boundaries, construction gap, deictic balance, coverage, lexical senses, morphology, syntax, fidelity, cultural 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 334 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-376-verify'").fetchone()[0]
    record_event(db, batch_label=LABEL, phase="close", event_type="close-success", actor="codex", detail=f"Closed Batch 376 / Rule 334: {accepted} accepted, {reviews} reviews, {lessons} lessons, {logs} lexeme logs; verified {before}->{after}; Kuku words {words_before}->{words_after}.", command="python3 batch_scripts/close_376.py", output_excerpt=f"closed batch-376 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-376: 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())
