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

NOTES=("COMPLEMENTARY REPTILE LEXEME-SET-B NON-SINGULAR PAST PERCEPTION AFTER RULE 340 (Rule 341). 50 rows over banamu, binju, dukul-mukul, jirabay, junbirr, kabuljaka, kulmba-kulmba, kurriyala, ngawurr-ngawun, and ngumbul. The selected orientation exactly complements Batch 382 / Rule 340. Duplicate records, binju polysemy, kurriyala fish/snake homonymy and source contexts, whole echo/reduplicated heads, properties, habitat, poison/danger, source, possession, case, and events remain closed. Two-here/three-there completes the paradigm without duplicating the lower-gap inverse.")

LESSONS=[
    ("source","Rule 341 retained the ten Rule 340 reptile-set-B heads, each at coverage 15 after Batch 382, for their exact complementary orientation.","Rule 341: complementary inventory."),
    ("source","Dictionary lines freshly 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 341: source lines."),
    ("source","Exact record counts remained 2/2/1/1/1/2/1/2/1/2; duplicate sets, binju polysemy and kurriyala fish/snake homonymy remained distinct.","Rule 341: record audit."),
    ("source","Patz junbirr-anka, kurriyala myth/material/ablative uses and ngawurr-ngawun bibliography title remained attestation/exclusion evidence only.","Rule 341: Patz boundary."),
    ("source","Patz fauna, selected pronoun, Yalanji local, past nyaji-ny and perception A/O evidence plus dictionary nyajin independently license the frame.","Rule 341: construction evidence."),
    ("process","The selected 50 cells were empty and all opposite cells mapped exactly one-for-one to Batch 382 / Rule 340.","Rule 341: complementary matrix."),
    ("process","Two-here/three-there changes the current gap 162->172; lower-gap inverse would produce 152 but duplicates Batch 382.","Rule 341: balance/non-duplication."),
    ("process","Every target had coverage 15 before banking; Rule 341 adds distributional complement, not a new sense.","Rule 341: target coverage."),
    ("process","Support before banking was ngali 643, ngaliny 585, yubal 595, yurra 580, nganjin 308, ngana 1115, yaluy 4412, yinyay 4574 and nyajin 2100.","Rule 341: support coverage."),
    ("source","Generic headword-plus-creature labels continue to minimize semantic commitment.","Rule 341: conservative labels."),
    ("lexicon","Banamu remained snake only; duplicate identity, freshwater habitat, danger, source, possession and events stayed closed.","Rule 341: banamu."),
    ("lexicon","Binju remained snake only; wrong marriage/law, poor making/cooking, quality, colour/body, size, poison/danger and record identity stayed closed.","Rule 341: binju."),
    ("lexicon","Dukul-mukul remained the exact whole lizard head; free components, size, head/body property and species stayed closed.","Rule 341: dukul-mukul."),
    ("lexicon","Jirabay remained lizard only; ground habitat, size/comparison and blue-tongue identity stayed closed.","Rule 341: jirabay."),
    ("lexicon","Junbirr remained bare lizard only; dative case, size, habitat, season and colour/head stayed closed.","Rule 341: junbirr."),
    ("lexicon","Kabuljaka remained whole snake head; duplicate identity, components, stripe/zebra, water habitat and python stayed closed.","Rule 341: kabuljaka."),
    ("lexicon","Kulmba-kulmba remained whole gecko head; free base, productive reduplication, size and house habitat stayed closed.","Rule 341: kulmba-kulmba."),
    ("lexicon","Kurriyala selected snake only; grunter fish, python, myth/death/place, belt material/use, fleeing and ablative case stayed closed.","Rule 341: kurriyala."),
    ("lexicon","Ngawurr-ngawun remained whole crocodile head; base/productive process, freshwater habitat and title import stayed closed.","Rule 341: ngawurr-ngawun."),
    ("lexicon","Ngumbul remained snake only; duplicate identity, sea habitat, species, danger and events stayed closed.","Rule 341: ngumbul."),
    ("morphology","All targets remained bare absolutive O with no case, derivation, property or event morphology.","Rule 341: bare O."),
    ("morphology","Dukul-mukul, kulmba-kulmba and ngawurr-ngawun remained exact whole heads; no productive process entered.","Rule 341: whole heads."),
    ("morphology","Selected non-singular pronouns remained bare nominative A; number/clusivity exact; ngana deferred, not banned.","Rule 341: pronouns."),
    ("morphology","Yaluy, yinyay and nyajin remained fixed; no case, dialect, nonpast, purposive or compound drift entered.","Rule 341: support."),
    ("syntax","Rows 1-10 used Ngali TARGET yinyay nyajin.","Rule 341: 1du.excl there."),
    ("syntax","Rows 11-20 used Ngaliny TARGET yaluy nyajin.","Rule 341: 1du.incl here."),
    ("syntax","Rows 21-30 used Yubal TARGET yinyay nyajin.","Rule 341: 2du there."),
    ("syntax","Rows 31-40 used Yurra TARGET yaluy nyajin.","Rule 341: 2pl here."),
    ("syntax","Rows 41-50 used Nganjin TARGET yinyay nyajin.","Rule 341: 1pl.excl there."),
    ("fidelity","English preserved number/clusivity, conservative label, complementary here/there and past seeing only.","Rule 341: fidelity."),
    ("fidelity","No record/polysemy/homonym/source-context/property/habitat/danger/material/behavior/title/case/event content entered.","Rule 341: exclusion fidelity."),
    ("register","Rows remained neutral elicitation clauses; culturally loaded material stayed exclusion metadata.","Rule 341: register."),
    ("process","All 50 sentences were explicit sequence-specific row calls; no runtime generator authored content.","Rule 341: authorship."),
    ("process","Rules 149-340 traps remained closed, including every Rule 340 record, sense, whole-head and source-context boundary.","Rule 341: cumulative traps."),
    ("handoff","Next batch may continue from 19,247; Rule 342 requires fresh source/gap audit and must not infer closed reptile senses or events.","Rule 341: handoff."),
]

LEXEMES=[
    ("banamu","noun",None,"NA","snake","batch-383: conservative snake only; duplicate/freshwater/habitat/danger/event closed."),
    ("binju","noun",None,"NA","snake","batch-383: snake only; marriage/law/cooking/quality/colour/poison/polysemy closed."),
    ("dukul-mukul","noun",None,"NA","lizard","batch-383: exact whole head; components/size/head property/species closed."),
    ("jirabay","noun",None,"NA","lizard","batch-383: lizard only; ground habitat/size/comparison/blue-tongue closed."),
    ("junbirr","noun",None,"NA","lizard","batch-383: bare lizard only; case/size/habitat/season/colour/head closed."),
    ("kabuljaka","noun",None,"NA","snake","batch-383: exact whole head; duplicate/components/stripe/water/python closed."),
    ("kulmba-kulmba","noun",None,"NA","gecko","batch-383: exact whole head; base/productive redup/size/house habitat closed."),
    ("kurriyala","noun",None,"NA","snake","batch-383: snake sense only; fish/python/myth/death/place/material/fleeing/case closed."),
    ("ngawurr-ngawun","noun",None,"NA","crocodile","batch-383: exact whole head; base/productive process/freshwater/title/event closed."),
    ("ngumbul","noun",None,"NA","snake","batch-383: conservative snake only; duplicate/sea/species/danger/event closed."),
    ("ngali","pronoun",None,"NA","first dual exclusive nominative","batch-383: bare A only; exclusive."),
    ("ngaliny","pronoun",None,"NA","first dual inclusive nominative","batch-383: bare A only; inclusive."),
    ("yubal","pronoun",None,"NA","second dual nominative","batch-383: bare A only."),
    ("yurra","pronoun",None,"NA","second plural nominative","batch-383: bare A only."),
    ("nganjin","pronoun",None,"NA","first plural exclusive nominative","batch-383: bare A only; ngana distinct/deferred."),
    ("yaluy","demonstrative",None,"NA","here","batch-383: Yalanji local support only."),
    ("yinyay","demonstrative",None,"NA","there","batch-383: Yalanji local support only."),
    ("nyajin","verb-tr","l","NA","see; see.PST","batch-383: 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-383-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-383-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 judgments passed; exact Batch 382 complement, number/clusivity, conservative labels and source-bounded senses retained."),
        ("review","review-detail","Batch 382 duplication, record/polysemy/homonym/component/source-context/property/habitat/danger/material/behavior/title/event, case and support drift remained closed."),
        ("review","lesson-inventory",f"Inserted {len(LESSONS)} Rule 341 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 341 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-383-verify'").fetchone()[0]
    record_event(db,batch_label=LABEL,phase="close",event_type="close-success",actor="codex",detail=f"Closed Rule 341: accepted={accepted}, reviews={reviews}, lessons={lessons}, logs={logs}; verified {before}->{after}; words {wb}->{wa}.",command="python3 batch_scripts/close_383.py",artifact_path=PROCESS_LOG,created_at=NOW)
    db.commit();print(f"closed batch-383: accepted={accepted} reviews={reviews} lessons={lessons} logs={logs} verified {before}->{after} words {wb}->{wa}");return 0

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




