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

NOTES=("UNDERREPRESENTED REPTILE LEXEME-SET-B NON-SINGULAR PAST PERCEPTION AFTER RULE 339 (Rule 340). 50 rows over banamu, binju, dukul-mukul, jirabay, junbirr, kabuljaka, kulmba-kulmba, kurriyala, ngawurr-ngawun, and ngumbul. Bare ngali/ngaliny/yubal/yurra/nganjin A, bare target O, Yalanji locals, and past nyajin. Duplicate records, binju polysemy, kurriyala fish/snake homonymy and myth/material contexts, whole echo/reduplicated heads, properties, habitat, poison/danger, source, possession, case, and events remain closed. The full 100-cell grid was empty and selected three-here/two-there reduced the deictic gap 172->162.")

LESSONS=[
    ("source","Rule 340 selected ten exact dictionary reptile heads with exactly ten prior words_used rows each, all confined to the early Rule 175/176 mini-grids.","Rule 340: measured lexeme-set-B inventory."),
    ("source","Dictionary lines reread: banamu 1346-1370, binju 2979-3013, dukul-mukul 6360-6370, jirabay 9645-9655, junbirr 10826-10839, kabuljaka 11834-11856, kulmba-kulmba 15290-15305, kurriyala 16420-16442, ngawurr-ngawun 22956-22970, ngumbul 23585-23605.","Rule 340: source lines."),
    ("source","Exact record counts were banamu 2, binju 2, dukul-mukul 1, jirabay 1, junbirr 1, kabuljaka 2, kulmba-kulmba 1, kurriyala 2, ngawurr-ngawun 1, ngumbul 2; record sets and homonyms remained distinct.","Rule 340: structured record audit."),
    ("source","Patz search found junbirr-anka in dative case, kurriyala in creation-myth/material/ablative contexts, and ngawurr-ngawun in a bibliography title; these attest forms or exclusions, not reusable synthetic events.","Rule 340: Patz target cross-check."),
    ("source","Patz fauna, pronoun, Yalanji local, past nyaji-ny and perception A/O passages plus dictionary running nyajin independently license the construction.","Rule 340: construction evidence."),
    ("process","The complete five-pronoun x ten-target x two-deictic non-singular past matrix had 100 empty cells; both orientations were internally unique and collision-free.","Rule 340: construction gap."),
    ("process","Three-here/two-there changes the yaluy/yinyay gap from 172 to 162; inverse would produce 182.","Rule 340: deictic balance."),
    ("process","All targets had coverage 10 before banking; prior rows mixed bare deictics, singular nonpast, jana past and ngana nonpast rather than the selected non-singular past paradigm.","Rule 340: target coverage and prior-shape audit."),
    ("process","Support before banking was ngali 633, ngaliny 575, yubal 585, yurra 570, nganjin 298, deferred ngana 1115, yaluy 4382, yinyay 4554 and nyajin 2050.","Rule 340: support coverage."),
    ("source","Generic headword-plus-creature English labels minimize semantic commitment while retaining exact lexical identity.","Rule 340: conservative label policy."),
    ("lexicon","Banamu remained snake only; duplicate identity, freshwater habitat, movement, danger, source, possession and events stayed closed.","Rule 340: banamu."),
    ("lexicon","Binju remained snake only; wrong marriage/law, poor making/cooking, food/quality, colour/body, size, poison/danger and record identity stayed closed.","Rule 340: binju polysemy."),
    ("lexicon","Dukul-mukul remained the exact whole lizard head; free components, size, head/body property and species resolution stayed closed.","Rule 340: dukul-mukul."),
    ("lexicon","Jirabay remained lizard only; ground habitat, size/comparison and blue-tongue identity stayed closed.","Rule 340: jirabay."),
    ("lexicon","Junbirr remained bare lizard only; dative case, size, leaf/grass habitat, wet season and reddish-head properties stayed closed.","Rule 340: junbirr."),
    ("lexicon","Kabuljaka remained the exact whole snake head; duplicate identity, component generation, stripe/zebra property, water habitat and python identity stayed closed.","Rule 340: kabuljaka."),
    ("lexicon","Kulmba-kulmba remained the exact whole gecko head; free base, productive reduplication, size and house habitat stayed closed.","Rule 340: kulmba-kulmba."),
    ("lexicon","Kurriyala selected only the snake noun; grunter fish, python resolution, creation myth, death/burial/place, belt material/use, fleeing behavior and ablative case stayed closed.","Rule 340: kurriyala homonym and source contexts."),
    ("lexicon","Ngawurr-ngawun remained the exact whole crocodile head; free base, productive process, freshwater habitat and bibliography/title import stayed closed.","Rule 340: ngawurr-ngawun."),
    ("lexicon","Ngumbul remained snake only; duplicate identity, sea habitat, species resolution, danger, source, possession and events stayed closed.","Rule 340: ngumbul."),
    ("morphology","All targets remained bare absolutive O; no case, derivation, record alignment, property or event morphology entered.","Rule 340: bare O."),
    ("morphology","Dukul-mukul, kulmba-kulmba and ngawurr-ngawun remained exact whole hyphenated heads; no free component or productive process entered.","Rule 340: whole lexical heads."),
    ("morphology","Ngali, ngaliny, yubal, yurra and nganjin remained bare nominative A; number/clusivity stayed explicit and ngana remained deferred, not banned.","Rule 340: pronoun A."),
    ("morphology","Yaluy, yinyay and nyajin remained fixed; no target/pronoun/demonstrative case, Nyungkul support, nonpast, purposive, reduplicated perception or compound entered.","Rule 340: fixed support."),
    ("syntax","Rows 1-10 used Ngali TARGET yaluy nyajin.","Rule 340: 1du.excl here band."),
    ("syntax","Rows 11-20 used Ngaliny TARGET yinyay nyajin.","Rule 340: 1du.incl there band."),
    ("syntax","Rows 21-30 used Yubal TARGET yaluy nyajin.","Rule 340: 2du here band."),
    ("syntax","Rows 31-40 used Yurra TARGET yinyay nyajin.","Rule 340: 2pl there band."),
    ("syntax","Rows 41-50 used Nganjin TARGET yaluy nyajin.","Rule 340: 1pl.excl here band."),
    ("fidelity","English preserved participant number/clusivity, conservative headword-plus-creature label, here/there and past seeing only.","Rule 340: literal fidelity."),
    ("fidelity","No polysemous record, source narrative, property, habitat, danger, material/use, behavior, title, case or prior event entered English.","Rule 340: exclusion fidelity."),
    ("register","Rows remained neutral elicitation clauses; myth, cultural law, food quality and source narratives were documented only as exclusions.","Rule 340: register."),
    ("process","All 50 sentences were explicit sequence-specific row calls with exact contracts; no runtime generator authored content.","Rule 340: authorship."),
    ("process","Rules 149-339 traps remained closed, including Rule 339 orientation/clusivity and all Rule 340 polysemy, homonym, record, source-context and whole-head boundaries.","Rule 340: cumulative traps."),
    ("handoff","Next batch may continue from 19,197; Rule 341 requires a fresh source/gap audit and must not infer closed reptile polysemy, homonym, source contexts, properties or events.","Rule 340: handoff."),
]

LEXEMES=[
    ("banamu","noun",None,"NA","snake","batch-382: conservative snake only; duplicate/freshwater/habitat/danger/event closed."),
    ("binju","noun",None,"NA","snake","batch-382: snake only; marriage/law/cooking/quality/colour/poison/polysemy closed."),
    ("dukul-mukul","noun",None,"NA","lizard","batch-382: exact whole head; components/size/head property/species closed."),
    ("jirabay","noun",None,"NA","lizard","batch-382: lizard only; ground habitat/size/comparison/blue-tongue closed."),
    ("junbirr","noun",None,"NA","lizard","batch-382: bare lizard only; case/size/habitat/season/colour/head closed."),
    ("kabuljaka","noun",None,"NA","snake","batch-382: exact whole head; duplicate/components/stripe/water/python closed."),
    ("kulmba-kulmba","noun",None,"NA","gecko","batch-382: exact whole head; base/productive redup/size/house habitat closed."),
    ("kurriyala","noun",None,"NA","snake","batch-382: snake sense only; fish/python/myth/death/place/material/fleeing/case closed."),
    ("ngawurr-ngawun","noun",None,"NA","crocodile","batch-382: exact whole head; base/productive process/freshwater/title/event closed."),
    ("ngumbul","noun",None,"NA","snake","batch-382: conservative snake only; duplicate/sea/species/danger/event closed."),
    ("ngali","pronoun",None,"NA","first dual exclusive nominative","batch-382: bare A only; exclusive."),
    ("ngaliny","pronoun",None,"NA","first dual inclusive nominative","batch-382: bare A only; inclusive."),
    ("yubal","pronoun",None,"NA","second dual nominative","batch-382: bare A only."),
    ("yurra","pronoun",None,"NA","second plural nominative","batch-382: bare A only."),
    ("nganjin","pronoun",None,"NA","first plural exclusive nominative","batch-382: bare A only; ngana distinct/deferred."),
    ("yaluy","demonstrative",None,"NA","here","batch-382: Yalanji local support only."),
    ("yinyay","demonstrative",None,"NA","there","batch-382: Yalanji local support only."),
    ("nyajin","verb-tr","l","NA","see; see.PST","batch-382: l-conjugation root nyaji-l with past -ny; running surface nyajin."),
]

def main()->int:
    if len(LESSONS)!=35: raise SystemExit(f"lessons {len(LESSONS)}")
    if len(LEXEMES)!=18: raise SystemExit(f"lexemes {len(LEXEMES)}")
    db=sqlite3.connect(DB);db.execute("PRAGMA foreign_keys=ON");db.execute("BEGIN");ensure_schema(db)
    r=db.execute("SELECT id FROM batches WHERE label=?",(LABEL,)).fetchone()
    if not r: raise SystemExit("not banked")
    bid=r[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,ur,ac)!=(50,50,0): raise SystemExit(f"precheck {total}/{ur}/{ac}")
    if db.execute("SELECT COUNT(*) FROM reviews WHERE sentence_id IN(SELECT id FROM sentences WHERE batch_id=?)",(bid,)).fetchone()[0] or db.execute("SELECT COUNT(*) FROM lessons WHERE batch_id=?",(bid,)).fetchone()[0] or db.execute("SELECT COUNT(*) FROM lexeme_log WHERE action='batch-382-verify'").fetchone()[0]: raise SystemExit("close artifacts exist")
    total_rows=db.execute("SELECT COUNT(*) FROM sentences WHERE status!='rejected'").fetchone()[0];before,wb=db.execute("SELECT COUNT(*),SUM(LENGTH(kuku)-LENGTH(REPLACE(kuku,' ',''))+1) FROM sentences WHERE status IN('accepted','revised')").fetchone();ids=[x[0] for x 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,l,"pass",None,None,"codex-main-five-lens",NOW) for sid in ids for l 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,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,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-382-verify",note,NOW))
    ev=[
        ("lint","under-review-lint-green",f"Whole-corpus lint scanned {total_rows} rows with zero issues; verified remained {before}."),
        ("review","five-lens-pass","All 250 morphology, lexicon, syntax, fidelity and register judgments passed; exact number/clusivity, conservative generic labels and source-bounded senses retained."),
        ("review","review-detail","Duplicate identity, binju polysemy, kurriyala fish/myth/material contexts, component generation, source properties/habitat/danger/behavior/title/events, case and support drift remained closed."),
        ("review","lesson-inventory",f"Inserted {len(LESSONS)} Rule 340 lessons."),
        ("review","lexeme-source-log",f"Inserted {len(LEXEMES)} target/support lexeme logs."),
    ]
    for phase,etype,detail in ev:record_event(db,batch_label=LABEL,phase=phase,event_type=etype,actor="codex",detail=detail,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 340 accepted","operator-guide-2026-07-10",bid))
    after,wa=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-382-verify'").fetchone()[0]
    record_event(db,batch_label=LABEL,phase="close",event_type="close-success",actor="codex",detail=f"Closed Rule 340: accepted={accepted}, reviews={reviews}, lessons={lessons}, logs={logs}; verified {before}->{after}; words {wb}->{wa}.",command="python3 batch_scripts/close_382.py",artifact_path=PROCESS_LOG,created_at=NOW)
    db.commit();print(f"closed batch-382: accepted={accepted} reviews={reviews} lessons={lessons} logs={logs} verified {before}->{after} words {wb}->{wa}");return 0

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



