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

NOTES = (
    "LOW-COVERAGE REPTILE SINGULAR/THIRD-PERSON PAST PERCEPTION SWEEP AFTER RULE 318 (Rule 319). 50 rows. "
    "TARGETS: jalbil lizard, kalkarrumbarr lizard, kurmba-kurmba lizard, jimalili lizard, yuray snake, bakay "
    "snake, kungkun snake, bilbil-bilbil gecko, bajalji python, and noun jabil lizard. SUPPORT: bare nominative "
    "ngayu, yundu, nyulu, bula, jana, Yalanji yaluy/yinyay, and dictionary-attested past nyajin. Basic labels "
    "suppress source properties; bilbil-bilbil remains an indivisible dictionary reduplication; noun jabil remains "
    "separate from homophonous kick. No mythology/story, size/colour/habitat, species ambiguity, poison/danger, "
    "behavior, prior-row proposition, case, new word formation, nonpast/purposive/reduplicated perception, support "
    "inflection, or carried trap was opened."
)

LESSONS = [
    ("source", "Rule 319 selected ten direct-dictionary low-coverage reptile nouns: zero-use jalbil, kalkarrumbarr, kurmba-kurmba; one-use jimalili, yuray; two-use bakay, kungkun; three-use bilbil-bilbil; four-use bajalji; five-token-use jabil.", "Rule 319: low-coverage reptile inventory."),
    ("source", "Dictionary lines reread: bajalji 387-409, bakay 635-653, bilbil-bilbil 2529-2542, jabil 6929-6951, jalbil 7374-7386, jimalili 9284-9294, kalkarrumbarr 12679-12689, kungkun 15748-15768, kurmba-kurmba 16154-16169, yuray 31016-31033.", "Rule 319: dictionary source lines."),
    ("source", "All ten reptile heads were checked against Patz and none occurs as a lexical target. The dictionary supplies their bare forms; Patz supplies pronoun, case, tense, and perception-clause licensing.", "Rule 319: Patz lexical cross-check."),
    ("source", "Patz pronoun lines 2577-2586 supplied ngayu, yundu, nyulu, bula, jana; demonstrative lines 2834-2847 supplied Yalanji yaluy/yinyay; lines 2023, 2568-2571, and 3160-3162 supplied past nyaji-ny/-ny; lines 4256-4265 supplied perception A/O syntax; dictionary examples 23882-23883 and 23975-23976 supplied running-form nyajin.", "Rule 319: morphosyntactic source."),
    ("source", "Basic English creature labels were chosen to avoid asserting source colour, size, habitat, slipperiness, geography, or species distinctions. Bilbil-bilbil remained a whole attested head; jabil's noun sense was separated from homophonous transitive kick.", "Rule 319: label and homograph discipline."),
    ("source", "Source prose and earlier rows were restraint data: mythology, kin/marriage story, island splitting, legend, firestick teaching, habitat, danger, poison, chasing lore, eating, catching, feeding, sound, and behavior stayed closed.", "Rule 319: commentary and prior-row caution."),
    ("process", "Rule 319 was scoped as bare low-coverage reptile singular/third-person past visual perception, not mythology, ecology, danger, hunting, food, taxonomy, productive morphology, or event content.", "Rule 319: bounded reptile lexical-debt scope."),
    ("process", "All selected target forms passed intended-frame lint and all 50 exact planned surfaces returned no accepted, revised, or under-review collisions.", "Rule 319: form and duplicate preflight."),
    ("process", "Target token coverage before banking was jalbil 0, kalkarrumbarr 0, kurmba-kurmba 0, jimalili 1, yuray 1, bakay 2, kungkun 2, bilbil-bilbil 3, bajalji 4, jabil 5; jabil comprised four verb-sense and one noun-sense rows.", "Rule 319: target and sense coverage audit."),
    ("process", "Support coverage before banking was ngayu 1361, yundu 957, nyulu 632, bula 428, jana 1133, yaluy 3822, yinyay 4064, nyajin 1250.", "Rule 319: support coverage audit."),
    ("lexicon", "Jalbil was retained as visible lizard only; colour, size, mythological personhood, Snapper Island splitting, cooking story, and event propositions stayed closed.", "Rule 319: jalbil."),
    ("lexicon", "Kalkarrumbarr was retained as visible lizard only; size, measurement, legend, role, behavior, and event propositions stayed closed.", "Rule 319: kalkarrumbarr."),
    ("lexicon", "Kurmba-kurmba was retained as the whole lizard noun only; productive reduplication, slipperiness, mythological personhood, kinship/marriage, desire, place, story, and event stayed closed.", "Rule 319: kurmba-kurmba."),
    ("lexicon", "Jimalili was retained as visible lizard only; mountain habitat, teaching, people, firestick, etymology, cultural story, and event stayed closed.", "Rule 319: jimalili."),
    ("lexicon", "Yuray was retained as visible snake only; sea habitat, swimming, danger, touching, food, behavior, and event stayed closed.", "Rule 319: yuray."),
    ("lexicon", "Bakay was retained as visible snake only; water habitat, size, colour, swimming, fish seeking, lagoon/creek, danger, and event stayed closed.", "Rule 319: bakay."),
    ("lexicon", "Kungkun was retained at the shared snake hypernym; carpet-snake/python versus brown-tree-snake resolution, colour, tree/habitat, geography, danger, eating, behavior, and event stayed closed.", "Rule 319: kungkun."),
    ("lexicon", "Bilbil-bilbil was retained as the whole gecko noun only; productive reduplication and prior size, bark/shelter, night, sound, feeding, insect, friendship, habitat, and behavior stayed closed.", "Rule 319: bilbil-bilbil."),
    ("lexicon", "Bajalji was retained in its directly attested python reading only; poisonous-snake alternative, distribution/place, colour/head, chasing/baldness/hat lore, danger, hunting, teaching, habitat, food, and event stayed closed.", "Rule 319: bajalji."),
    ("lexicon", "Jabil was retained in its noun sense 'lizard' only; homophonous transitive kick and prior scrub-habitat, catching, warmth/rock/day, release, behavior, and event propositions stayed closed.", "Rule 319: jabil noun/verb separation."),
    ("morphology", "All Rule 319 reptile heads stayed bare absolutive objects with no case or derivation; dictionary hyphenation in bilbil-bilbil and kurmba-kurmba was preserved exactly.", "Rule 319: bare targets and source orthography."),
    ("morphology", "All subject forms stayed bare nominatives; no accusative, dative, locative, ablative, comitative, possessive, alternative, expanded, or non-selected pronoun was admitted.", "Rule 319: bare pronoun A forms."),
    ("morphology", "Yaluy, yinyay, and nyajin stayed fixed support; no demonstrative case, nonpast nyajil, purposive nyaji-nka, reduplicated watching, hearing compound, or perception compound was admitted.", "Rule 319: fixed support morphology."),
    ("morphology", "Bilbil-bilbil and kurmba-kurmba were copied as indivisible dictionary heads, while noun jabil was sense-disambiguated without changing its form; no new compound or productive reduplication was built.", "Rule 319: lexicalized form and homograph boundary."),
    ("syntax", "Rows 1-10 used Ngayu TARGET yinyay nyajin for first singular there past visual perception.", "Rule 319: 1sg there band."),
    ("syntax", "Rows 11-20 used Yundu TARGET yaluy nyajin for second singular here past visual perception.", "Rule 319: 2sg here band."),
    ("syntax", "Rows 21-30 used Nyulu TARGET yinyay nyajin for third singular there past visual perception.", "Rule 319: 3sg there band."),
    ("syntax", "Rows 31-40 used Bula TARGET yaluy nyajin for third dual here past visual perception.", "Rule 319: 3du here band."),
    ("syntax", "Rows 41-50 used Jana TARGET yinyay nyajin for third plural there past visual perception.", "Rule 319: 3pl there band."),
    ("fidelity", "English stayed literal past visual perception/reference prose: exact subject value, conservative lexical creature label, here/there, and saw only.", "Rule 319: literal English."),
    ("fidelity", "No dictionary commentary or prior corpus sentence was converted into colour, size, habitat, mythology/story, kinship, danger/poison, hunting, dietary, teaching, behavioral, or event claims.", "Rule 319: source and prior-row restraint."),
    ("register", "Rows remained plain elicitation-style past-perception clauses; no narrative, mythological, ecological, danger, hunting, food, teaching, or taxonomic register was introduced.", "Rule 319: register."),
    ("process", "Every Rule 319 sentence is an explicit row call with exact sequence-specific Kuku and English contracts; no runtime generator authored content.", "Rule 319: explicit-row authorship evidence."),
    ("process", "Rules 149-318 carry-forward traps stayed closed, including Rule 318 fish dialect/homograph/source-prose traps plus older mythology, place/story, case, productive word-formation, and support-inflection traps.", "Rule 319: cumulative trap closure."),
    ("handoff", "Next batch may continue from 18,147 if this closes; Rule 320 requires fresh source and coverage audit and must not infer closed reptile mythology/story, colour/size/habitat, species, danger/poison, behavior, homograph, case, word-formation, perception, or support fields.", "Rule 319: next cadence."),
]

LEXEMES = [
    ("jalbil", "noun", None, "NA", "lizard", "batch-361: visible lizard only; colour, size, mythology, island/story, event closed."),
    ("kalkarrumbarr", "noun", None, "NA", "lizard", "batch-361: visible lizard only; size, measurement, legend, role, behavior, event closed."),
    ("kurmba-kurmba", "noun", None, "NA", "lizard", "batch-361: whole dictionary lizard head only; productive reduplication, slipperiness, mythology, kin/marriage, place/story, event closed."),
    ("jimalili", "noun", None, "NA", "lizard", "batch-361: visible lizard only; mountain habitat, teaching, people, firestick, story, event closed."),
    ("yuray", "noun", None, "NA", "snake", "batch-361: visible snake only; sea habitat, swimming, danger, touching, food, behavior, event closed."),
    ("bakay", "noun", None, "NA", "snake", "batch-361: visible snake only; water habitat, size, colour, swimming, fish seeking, lagoon/creek, danger, event closed."),
    ("kungkun", "noun", None, "NA", "snake", "batch-361: shared snake hypernym only; species resolution, colour/tree/habitat, geography, danger, eating, behavior, event closed."),
    ("bilbil-bilbil", "noun", None, "NA", "gecko", "batch-361: whole dictionary gecko head only; productive reduplication and prior size/habitat/night/sound/feeding/behavior closed."),
    ("bajalji", "noun", None, "NA", "python", "batch-361: directly attested python reading only; poison, distribution/place, colour/head, chasing lore, danger, hunting, teaching, habitat, food, event closed."),
    ("jabil", "noun", None, "NA", "lizard", "batch-361: noun lizard sense only; homophonous kick and prior habitat/catching/warmth/release/behavior/event closed."),
    ("ngayu", "pronoun", None, "NA", "first singular nominative", "batch-361: bare nominative subject support only."),
    ("yundu", "pronoun", None, "NA", "second singular nominative", "batch-361: bare nominative subject support only."),
    ("nyulu", "pronoun", None, "NA", "third singular nominative", "batch-361: bare nominative subject support only."),
    ("bula", "pronoun", None, "NA", "third dual nominative", "batch-361: bare nominative subject support only."),
    ("jana", "pronoun", None, "NA", "third plural nominative", "batch-361: bare nominative subject support only."),
    ("yaluy", "demonstrative", None, "NA", "here", "batch-361: bare Yalanji local demonstrative support only."),
    ("yinyay", "demonstrative", None, "NA", "there", "batch-361: bare Yalanji local demonstrative support only."),
    ("nyajin", "verb-tr", "l", "NA", "saw; see.PAST", "batch-361: dictionary-attested past visual perception surface corresponding to Patz nyaji-ny."),
]


def main() -> int:
    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, under, accepted = 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 under != 50 or accepted:
        raise SystemExit(f"close precheck failed total={total} under={under} accepted={accepted}")
    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("DELETE FROM reviews WHERE sentence_id=?", [(sid,) for sid in ids])
    db.execute("DELETE FROM lessons WHERE batch_id=?", (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, category, lesson, guide_change, NOW) for category, lesson, guide_change in LESSONS],
    )
    for head, pos, conj, case, gloss, note in LEXEMES:
        senses = json.dumps([{"sense": gloss, "definition": note, "status": "attested"}], ensure_ascii=False)
        attestation = 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, attestation, None, None, None, note, None, 0, "verified", NOW, note, LABEL),
        )
        db.execute(
            "INSERT INTO lexeme_log(headword,action,detail,created_at) VALUES(?,?,?,?)",
            (head, "batch-361-verify", note, NOW),
        )
    record_event(db, batch_label=LABEL, phase="lint", event_type="under-review-lint-green", actor="codex", detail=f"After banking, 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 319 rows: bare reptile O morphology, nominative pronoun A, fixed Yalanji local/past support, conservative creature senses, exact English fidelity, and elicitation register; mythology, properties, habitat, species ambiguity, danger/poison, homograph, source-prose, and prior-row behavior 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 colour/size/habitat, mythological person/story/legend, kinship/marriage, island/place, firestick teaching, species resolution, poison/danger, chasing lore, hunting/capture, eating/food, sound/feeding, kick-verb, case, new compound/reduplication, nonpast/purposive/reduplicated perception, or support-inflection 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 319 lessons covering source, exclusions, coverage/sense debt, lexical boundaries, morphology, syntax, fidelity, register, explicit 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.", 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 319 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()
    acc = 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-361-verify'").fetchone()[0]
    record_event(db, batch_label=LABEL, phase="close", event_type="close-success", actor="codex", detail=f"Closed Batch 361 / Rule 319: {acc} accepted, {reviews} reviews, {lessons} lessons, {logs} lexeme logs; verified {before}->{after}; Kuku words {words_before}->{words_after}.", command="python3 batch_scripts/close_361.py", output_excerpt=f"closed batch-361 accepted={acc} 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-361: accepted={acc}, reviews={reviews}, lessons={lessons}, lexeme_logs={logs}, verified {before}->{after}, kuku_words {words_before}->{words_after}")
    return 0


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