#!/usr/bin/env python3
"""Bank Batch 393: Rule 351 complementary bird-set-E singular/third past perception."""

from __future__ import annotations
import ast, datetime as dt, json, re, sqlite3
from pathlib import Path
from bank_392 import (
    DB, DENY_ENGLISH, DENY_KUKU, EXPECTED_HASHES, SUPPORT_EVIDENCE as BASE_SUPPORT_EVIDENCE,
    TARGET_CONFIDENCE, TARGET_EVIDENCE as BASE_TARGET_EVIDENCE, TARGET_GLOSSES, TARGET_LABELS,
    TARGET_ORDER, count_words, source_audit,
)
from process_ledger import ensure_schema, record_event

LABEL="batch-393";NOW=dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00","Z")
LOG="process_logs/batch-393-complementary-bird-set-e-singular-third-past-perception-after-rule350-process.md"
EXPECTED_TARGET_COVERAGE={"dakwurr-dakwun":5,"kurkunbay":10,"kurrujuwa":10,"mirrku":10,"baringkan":10,"barinkan":10,"bilu-warra":10,"dukunjulu":11,"jiwurrmal":10,"kujuway":10}
EXPECTED_SUPPORT_COVERAGE={"ngayu":1511,"yundu":1107,"nyulu":782,"bula":578,"jana":1283,"yaluy":4662,"yinyay":4824,"nyajin":2600}
FRAMES=[("ngayu","yinyay","I saw","there","1sg"),("yundu","yaluy","You saw","here","2sg"),("nyulu","yinyay","He saw","there","3sg"),("bula","yaluy","The two of them saw","here","3du"),("jana","yinyay","They saw","there","3pl")]
OPPOSITE={"yaluy":"yinyay","yinyay":"yaluy"}
TARGET_EVIDENCE={t:f"{BASE_TARGET_EVIDENCE[t]} Rule 351 changes deictic location only and preserves the corrected Rule 350 source and linter boundaries." for t in TARGET_ORDER}
SUPPORT_EVIDENCE=f"{BASE_SUPPORT_EVIDENCE} Rule 351 is the exact deictic complement of corrected Rule 350."

def row(seq,english,kuku,analysis,frame,words):
    t=words[1];return(seq,english,kuku,analysis,frame,3,json.dumps(words,ensure_ascii=False),json.dumps([],ensure_ascii=False),f"{TARGET_EVIDENCE[t]} {SUPPORT_EVIDENCE}",TARGET_CONFIDENCE[t])

ROWS=[
row(1,"I saw the dakwurr-dakwun hammer bird there.","Ngayu dakwurr-dakwun yinyay nyajin.","ngayu dakwurr-dakwun yinyay nyajin | 1sg.NOM dakwurr-dakwun.hammer-bird there see.PST","r351_1sg_there_bird_e_saw_dakwurr_dakwun",["ngayu","dakwurr-dakwun","yinyay","nyajin"]),
row(2,"I saw the kurkunbay butcherbird there.","Ngayu kurkunbay yinyay nyajin.","ngayu kurkunbay yinyay nyajin | 1sg.NOM kurkunbay.butcherbird there see.PST","r351_1sg_there_bird_e_saw_kurkunbay",["ngayu","kurkunbay","yinyay","nyajin"]),
row(3,"I saw the kurrujuwa sentry bird there.","Ngayu kurrujuwa yinyay nyajin.","ngayu kurrujuwa yinyay nyajin | 1sg.NOM kurrujuwa.sentry-bird there see.PST","r351_1sg_there_bird_e_saw_kurrujuwa",["ngayu","kurrujuwa","yinyay","nyajin"]),
row(4,"I saw the mirrku kidney bird there.","Ngayu mirrku yinyay nyajin.","ngayu mirrku yinyay nyajin | 1sg.NOM mirrku.kidney-bird there see.PST","r351_1sg_there_bird_e_saw_mirrku",["ngayu","mirrku","yinyay","nyajin"]),
row(5,"I saw the baringkan small bird there.","Ngayu baringkan yinyay nyajin.","ngayu baringkan yinyay nyajin | 1sg.NOM baringkan.small-bird there see.PST","r351_1sg_there_bird_e_saw_baringkan",["ngayu","baringkan","yinyay","nyajin"]),
row(6,"I saw the barinkan scrub bird there.","Ngayu barinkan yinyay nyajin.","ngayu barinkan yinyay nyajin | 1sg.NOM barinkan.scrub-bird there see.PST","r351_1sg_there_bird_e_saw_barinkan",["ngayu","barinkan","yinyay","nyajin"]),
row(7,"I saw the bilu-warra spoonbill there.","Ngayu bilu-warra yinyay nyajin.","ngayu bilu-warra yinyay nyajin | 1sg.NOM bilu-warra.spoonbill there see.PST","r351_1sg_there_bird_e_saw_bilu_warra",["ngayu","bilu-warra","yinyay","nyajin"]),
row(8,"I saw the dukunjulu golden whistler there.","Ngayu dukunjulu yinyay nyajin.","ngayu dukunjulu yinyay nyajin | 1sg.NOM dukunjulu.golden-whistler there see.PST","r351_1sg_there_bird_e_saw_dukunjulu",["ngayu","dukunjulu","yinyay","nyajin"]),
row(9,"I saw the jiwurrmal pheasant cuckoo there.","Ngayu jiwurrmal yinyay nyajin.","ngayu jiwurrmal yinyay nyajin | 1sg.NOM jiwurrmal.pheasant-cuckoo there see.PST","r351_1sg_there_bird_e_saw_jiwurrmal",["ngayu","jiwurrmal","yinyay","nyajin"]),
row(10,"I saw the kujuway pigeon there.","Ngayu kujuway yinyay nyajin.","ngayu kujuway yinyay nyajin | 1sg.NOM kujuway.pigeon there see.PST","r351_1sg_there_bird_e_saw_kujuway",["ngayu","kujuway","yinyay","nyajin"]),
row(11,"You saw the dakwurr-dakwun hammer bird here.","Yundu dakwurr-dakwun yaluy nyajin.","yundu dakwurr-dakwun yaluy nyajin | 2sg.NOM dakwurr-dakwun.hammer-bird here see.PST","r351_2sg_here_bird_e_saw_dakwurr_dakwun",["yundu","dakwurr-dakwun","yaluy","nyajin"]),
row(12,"You saw the kurkunbay butcherbird here.","Yundu kurkunbay yaluy nyajin.","yundu kurkunbay yaluy nyajin | 2sg.NOM kurkunbay.butcherbird here see.PST","r351_2sg_here_bird_e_saw_kurkunbay",["yundu","kurkunbay","yaluy","nyajin"]),
row(13,"You saw the kurrujuwa sentry bird here.","Yundu kurrujuwa yaluy nyajin.","yundu kurrujuwa yaluy nyajin | 2sg.NOM kurrujuwa.sentry-bird here see.PST","r351_2sg_here_bird_e_saw_kurrujuwa",["yundu","kurrujuwa","yaluy","nyajin"]),
row(14,"You saw the mirrku kidney bird here.","Yundu mirrku yaluy nyajin.","yundu mirrku yaluy nyajin | 2sg.NOM mirrku.kidney-bird here see.PST","r351_2sg_here_bird_e_saw_mirrku",["yundu","mirrku","yaluy","nyajin"]),
row(15,"You saw the baringkan small bird here.","Yundu baringkan yaluy nyajin.","yundu baringkan yaluy nyajin | 2sg.NOM baringkan.small-bird here see.PST","r351_2sg_here_bird_e_saw_baringkan",["yundu","baringkan","yaluy","nyajin"]),
row(16,"You saw the barinkan scrub bird here.","Yundu barinkan yaluy nyajin.","yundu barinkan yaluy nyajin | 2sg.NOM barinkan.scrub-bird here see.PST","r351_2sg_here_bird_e_saw_barinkan",["yundu","barinkan","yaluy","nyajin"]),
row(17,"You saw the bilu-warra spoonbill here.","Yundu bilu-warra yaluy nyajin.","yundu bilu-warra yaluy nyajin | 2sg.NOM bilu-warra.spoonbill here see.PST","r351_2sg_here_bird_e_saw_bilu_warra",["yundu","bilu-warra","yaluy","nyajin"]),
row(18,"You saw the dukunjulu golden whistler here.","Yundu dukunjulu yaluy nyajin.","yundu dukunjulu yaluy nyajin | 2sg.NOM dukunjulu.golden-whistler here see.PST","r351_2sg_here_bird_e_saw_dukunjulu",["yundu","dukunjulu","yaluy","nyajin"]),
row(19,"You saw the jiwurrmal pheasant cuckoo here.","Yundu jiwurrmal yaluy nyajin.","yundu jiwurrmal yaluy nyajin | 2sg.NOM jiwurrmal.pheasant-cuckoo here see.PST","r351_2sg_here_bird_e_saw_jiwurrmal",["yundu","jiwurrmal","yaluy","nyajin"]),
row(20,"You saw the kujuway pigeon here.","Yundu kujuway yaluy nyajin.","yundu kujuway yaluy nyajin | 2sg.NOM kujuway.pigeon here see.PST","r351_2sg_here_bird_e_saw_kujuway",["yundu","kujuway","yaluy","nyajin"]),
row(21,"He saw the dakwurr-dakwun hammer bird there.","Nyulu dakwurr-dakwun yinyay nyajin.","nyulu dakwurr-dakwun yinyay nyajin | 3sg.NOM dakwurr-dakwun.hammer-bird there see.PST","r351_3sg_there_bird_e_saw_dakwurr_dakwun",["nyulu","dakwurr-dakwun","yinyay","nyajin"]),
row(22,"He saw the kurkunbay butcherbird there.","Nyulu kurkunbay yinyay nyajin.","nyulu kurkunbay yinyay nyajin | 3sg.NOM kurkunbay.butcherbird there see.PST","r351_3sg_there_bird_e_saw_kurkunbay",["nyulu","kurkunbay","yinyay","nyajin"]),
row(23,"He saw the kurrujuwa sentry bird there.","Nyulu kurrujuwa yinyay nyajin.","nyulu kurrujuwa yinyay nyajin | 3sg.NOM kurrujuwa.sentry-bird there see.PST","r351_3sg_there_bird_e_saw_kurrujuwa",["nyulu","kurrujuwa","yinyay","nyajin"]),
row(24,"He saw the mirrku kidney bird there.","Nyulu mirrku yinyay nyajin.","nyulu mirrku yinyay nyajin | 3sg.NOM mirrku.kidney-bird there see.PST","r351_3sg_there_bird_e_saw_mirrku",["nyulu","mirrku","yinyay","nyajin"]),
row(25,"He saw the baringkan small bird there.","Nyulu baringkan yinyay nyajin.","nyulu baringkan yinyay nyajin | 3sg.NOM baringkan.small-bird there see.PST","r351_3sg_there_bird_e_saw_baringkan",["nyulu","baringkan","yinyay","nyajin"]),
row(26,"He saw the barinkan scrub bird there.","Nyulu barinkan yinyay nyajin.","nyulu barinkan yinyay nyajin | 3sg.NOM barinkan.scrub-bird there see.PST","r351_3sg_there_bird_e_saw_barinkan",["nyulu","barinkan","yinyay","nyajin"]),
row(27,"He saw the bilu-warra spoonbill there.","Nyulu bilu-warra yinyay nyajin.","nyulu bilu-warra yinyay nyajin | 3sg.NOM bilu-warra.spoonbill there see.PST","r351_3sg_there_bird_e_saw_bilu_warra",["nyulu","bilu-warra","yinyay","nyajin"]),
row(28,"He saw the dukunjulu golden whistler there.","Nyulu dukunjulu yinyay nyajin.","nyulu dukunjulu yinyay nyajin | 3sg.NOM dukunjulu.golden-whistler there see.PST","r351_3sg_there_bird_e_saw_dukunjulu",["nyulu","dukunjulu","yinyay","nyajin"]),
row(29,"He saw the jiwurrmal pheasant cuckoo there.","Nyulu jiwurrmal yinyay nyajin.","nyulu jiwurrmal yinyay nyajin | 3sg.NOM jiwurrmal.pheasant-cuckoo there see.PST","r351_3sg_there_bird_e_saw_jiwurrmal",["nyulu","jiwurrmal","yinyay","nyajin"]),
row(30,"He saw the kujuway pigeon there.","Nyulu kujuway yinyay nyajin.","nyulu kujuway yinyay nyajin | 3sg.NOM kujuway.pigeon there see.PST","r351_3sg_there_bird_e_saw_kujuway",["nyulu","kujuway","yinyay","nyajin"]),
row(31,"The two of them saw the dakwurr-dakwun hammer bird here.","Bula dakwurr-dakwun yaluy nyajin.","bula dakwurr-dakwun yaluy nyajin | 3du.NOM dakwurr-dakwun.hammer-bird here see.PST","r351_3du_here_bird_e_saw_dakwurr_dakwun",["bula","dakwurr-dakwun","yaluy","nyajin"]),
row(32,"The two of them saw the kurkunbay butcherbird here.","Bula kurkunbay yaluy nyajin.","bula kurkunbay yaluy nyajin | 3du.NOM kurkunbay.butcherbird here see.PST","r351_3du_here_bird_e_saw_kurkunbay",["bula","kurkunbay","yaluy","nyajin"]),
row(33,"The two of them saw the kurrujuwa sentry bird here.","Bula kurrujuwa yaluy nyajin.","bula kurrujuwa yaluy nyajin | 3du.NOM kurrujuwa.sentry-bird here see.PST","r351_3du_here_bird_e_saw_kurrujuwa",["bula","kurrujuwa","yaluy","nyajin"]),
row(34,"The two of them saw the mirrku kidney bird here.","Bula mirrku yaluy nyajin.","bula mirrku yaluy nyajin | 3du.NOM mirrku.kidney-bird here see.PST","r351_3du_here_bird_e_saw_mirrku",["bula","mirrku","yaluy","nyajin"]),
row(35,"The two of them saw the baringkan small bird here.","Bula baringkan yaluy nyajin.","bula baringkan yaluy nyajin | 3du.NOM baringkan.small-bird here see.PST","r351_3du_here_bird_e_saw_baringkan",["bula","baringkan","yaluy","nyajin"]),
row(36,"The two of them saw the barinkan scrub bird here.","Bula barinkan yaluy nyajin.","bula barinkan yaluy nyajin | 3du.NOM barinkan.scrub-bird here see.PST","r351_3du_here_bird_e_saw_barinkan",["bula","barinkan","yaluy","nyajin"]),
row(37,"The two of them saw the bilu-warra spoonbill here.","Bula bilu-warra yaluy nyajin.","bula bilu-warra yaluy nyajin | 3du.NOM bilu-warra.spoonbill here see.PST","r351_3du_here_bird_e_saw_bilu_warra",["bula","bilu-warra","yaluy","nyajin"]),
row(38,"The two of them saw the dukunjulu golden whistler here.","Bula dukunjulu yaluy nyajin.","bula dukunjulu yaluy nyajin | 3du.NOM dukunjulu.golden-whistler here see.PST","r351_3du_here_bird_e_saw_dukunjulu",["bula","dukunjulu","yaluy","nyajin"]),
row(39,"The two of them saw the jiwurrmal pheasant cuckoo here.","Bula jiwurrmal yaluy nyajin.","bula jiwurrmal yaluy nyajin | 3du.NOM jiwurrmal.pheasant-cuckoo here see.PST","r351_3du_here_bird_e_saw_jiwurrmal",["bula","jiwurrmal","yaluy","nyajin"]),
row(40,"The two of them saw the kujuway pigeon here.","Bula kujuway yaluy nyajin.","bula kujuway yaluy nyajin | 3du.NOM kujuway.pigeon here see.PST","r351_3du_here_bird_e_saw_kujuway",["bula","kujuway","yaluy","nyajin"]),
row(41,"They saw the dakwurr-dakwun hammer bird there.","Jana dakwurr-dakwun yinyay nyajin.","jana dakwurr-dakwun yinyay nyajin | 3pl.NOM dakwurr-dakwun.hammer-bird there see.PST","r351_3pl_there_bird_e_saw_dakwurr_dakwun",["jana","dakwurr-dakwun","yinyay","nyajin"]),
row(42,"They saw the kurkunbay butcherbird there.","Jana kurkunbay yinyay nyajin.","jana kurkunbay yinyay nyajin | 3pl.NOM kurkunbay.butcherbird there see.PST","r351_3pl_there_bird_e_saw_kurkunbay",["jana","kurkunbay","yinyay","nyajin"]),
row(43,"They saw the kurrujuwa sentry bird there.","Jana kurrujuwa yinyay nyajin.","jana kurrujuwa yinyay nyajin | 3pl.NOM kurrujuwa.sentry-bird there see.PST","r351_3pl_there_bird_e_saw_kurrujuwa",["jana","kurrujuwa","yinyay","nyajin"]),
row(44,"They saw the mirrku kidney bird there.","Jana mirrku yinyay nyajin.","jana mirrku yinyay nyajin | 3pl.NOM mirrku.kidney-bird there see.PST","r351_3pl_there_bird_e_saw_mirrku",["jana","mirrku","yinyay","nyajin"]),
row(45,"They saw the baringkan small bird there.","Jana baringkan yinyay nyajin.","jana baringkan yinyay nyajin | 3pl.NOM baringkan.small-bird there see.PST","r351_3pl_there_bird_e_saw_baringkan",["jana","baringkan","yinyay","nyajin"]),
row(46,"They saw the barinkan scrub bird there.","Jana barinkan yinyay nyajin.","jana barinkan yinyay nyajin | 3pl.NOM barinkan.scrub-bird there see.PST","r351_3pl_there_bird_e_saw_barinkan",["jana","barinkan","yinyay","nyajin"]),
row(47,"They saw the bilu-warra spoonbill there.","Jana bilu-warra yinyay nyajin.","jana bilu-warra yinyay nyajin | 3pl.NOM bilu-warra.spoonbill there see.PST","r351_3pl_there_bird_e_saw_bilu_warra",["jana","bilu-warra","yinyay","nyajin"]),
row(48,"They saw the dukunjulu golden whistler there.","Jana dukunjulu yinyay nyajin.","jana dukunjulu yinyay nyajin | 3pl.NOM dukunjulu.golden-whistler there see.PST","r351_3pl_there_bird_e_saw_dukunjulu",["jana","dukunjulu","yinyay","nyajin"]),
row(49,"They saw the jiwurrmal pheasant cuckoo there.","Jana jiwurrmal yinyay nyajin.","jana jiwurrmal yinyay nyajin | 3pl.NOM jiwurrmal.pheasant-cuckoo there see.PST","r351_3pl_there_bird_e_saw_jiwurrmal",["jana","jiwurrmal","yinyay","nyajin"]),
row(50,"They saw the kujuway pigeon there.","Jana kujuway yinyay nyajin.","jana kujuway yinyay nyajin | 3pl.NOM kujuway.pigeon there see.PST","r351_3pl_there_bird_e_saw_kujuway",["jana","kujuway","yinyay","nyajin"]),]

def literal_guard():
    m=ast.parse(Path(__file__).read_text());a=[n for n in m.body if isinstance(n,ast.Assign) and any(isinstance(t,ast.Name) and t.id=="ROWS" for t in n.targets)];issues=[]
    if len(a)!=1 or not isinstance(a[0].value,ast.List):return["ROWS not literal list"]
    if len(a[0].value.elts)!=50:issues.append("literal count")
    for i,e in enumerate(a[0].value.elts,1):
        if not isinstance(e,ast.Call) or not isinstance(e.func,ast.Name) or e.func.id!="row" or e.keywords:issues.append(f"{i}:direct call");continue
        try:v=[ast.literal_eval(x) for x in e.args]
        except Exception:issues.append(f"{i}:nonliteral");continue
        if len(v)!=6 or v[0]!=i:issues.append(f"{i}:args")
    return issues
def scan_static():
    issues=literal_guard()
    if len(ROWS)!=50 or [r[0] for r in ROWS]!=list(range(1,51)):issues.append("count/seq")
    if len({r[1] for r in ROWS})!=50 or len({r[2] for r in ROWS})!=50:issues.append("duplicates")
    for seq,en,ku,an,fr,_tier,wjson,ljson,ev,conf in ROWS:
        p,d,prefix,loc,person=FRAMES[(seq-1)//10];t=TARGET_ORDER[(seq-1)%10];w=json.loads(wjson)
        denied=[x for x in DENY_KUKU if re.search(rf"(^|\s){re.escape(x)}([\s\.]|$)",ku.lower())];drift=[x for x in DENY_ENGLISH if re.search(rf"\b{re.escape(x)}\b",en.lower())]
        if json.loads(ljson) or denied or drift:issues.append(f"{seq}:loan/deny/drift {denied}/{drift}")
        if ku!=f"{p.capitalize()} {t} {d} nyajin.":issues.append(f"{seq}:ku")
        if en!=f"{prefix} the {TARGET_LABELS[t]} {loc}.":issues.append(f"{seq}:en")
        if an!=f"{p} {t} {d} nyajin | {person}.NOM {TARGET_GLOSSES[t]} {loc} see.PST":issues.append(f"{seq}:an")
        if w!=[p,t,d,"nyajin"] or ku.lower().rstrip(".")!=" ".join(w):issues.append(f"{seq}:words")
        if not fr.startswith("r351_") or TARGET_EVIDENCE[t] not in ev or SUPPORT_EVIDENCE not in ev or conf!=TARGET_CONFIDENCE[t]:issues.append(f"{seq}:meta")
    return issues
def main():
    records,hits=source_audit();issues=scan_static()
    if issues:raise SystemExit("\n".join(issues))
    db=sqlite3.connect(DB);db.execute("PRAGMA foreign_keys=ON");db.execute("BEGIN");ensure_schema(db)
    if db.execute("SELECT 1 FROM batches WHERE label=?",(LABEL,)).fetchone() or db.execute("SELECT COUNT(*) FROM sentences WHERE status='under_review'").fetchone()[0]:raise SystemExit("open/existing")
    tc=count_words(db,TARGET_ORDER);sc=count_words(db,list(EXPECTED_SUPPORT_COVERAGE))
    if tc!=EXPECTED_TARGET_COVERAGE or sc!=EXPECTED_SUPPORT_COVERAGE:raise SystemExit(f"coverage {tc}/{sc}")
    for seq,_en,ku,_an,_fr,_tier,wjson,_loans,_ev,_conf in ROWS:
        w=json.loads(wjson);cand=db.execute("SELECT b.label,s.seq FROM sentences s JOIN batches b ON b.id=s.batch_id WHERE lower(s.kuku)=lower(?) AND s.status!='rejected'",(ku,)).fetchall();opp=f"{w[0].capitalize()} {w[1]} {OPPOSITE[w[2]]} nyajin.";oh=db.execute("SELECT b.label,s.seq FROM sentences s JOIN batches b ON b.id=s.batch_id WHERE lower(s.kuku)=lower(?) AND s.status!='rejected'",(opp,)).fetchall()
        if cand or oh!=[("batch-392",seq)]:raise SystemExit(f"map {seq} {cand}/{oh}")
    verified,words=db.execute("SELECT COUNT(*),SUM(LENGTH(kuku)-LENGTH(REPLACE(kuku,' ',''))+1) FROM sentences WHERE status IN('accepted','revised')").fetchone()
    if (verified,words)!=(19697,134147):raise SystemExit(f"baseline {verified}/{words}")
    notes="COMPLEMENTARY BIRD SET-E SINGULAR/THIRD PAST PERCEPTION AFTER RULE 350 (Rule 351). Corrected target set only; 50 empty candidates, opposites exactly Batch 392; linter-rejected drafts remain excluded; gap 162->172."
    bid=db.execute("INSERT INTO batches(label,cheatsheet_version,guide_version,notes,created_at) VALUES(?,?,?,?,?)",(LABEL,"Rule 351 under review","operator-guide-2026-07-10",notes,NOW)).lastrowid
    db.executemany("""INSERT INTO sentences(batch_id,seq,english,kuku,analysis,frame,tier,words_used,loans_used,evidence,status,confidence,rights_status,author,created_at,updated_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",[(bid,seq,en,ku,an,fr,tier,w,l,ev,"under_review",conf,"project_approved_synthetic_pending_elder_verification","codex-main",NOW,NOW) for seq,en,ku,an,fr,tier,w,l,ev,conf in ROWS])
    events=[("source","source-audit-pass",f"Corrected card/Patz audit passed: {records}/{hits}; hashes={EXPECTED_HASHES}."),("planning","sense-preservation-audit","All Rule 350 corrected target and exclusion rulings retained; three rejected draft heads excluded."),("planning","complement-map-audit","50 candidates absent; opposites exactly Batch 392 seq1-50."),("planning","balance-audit","Gap 162->172; lower-gap inverse duplicates Batch 392."),("preflight","coverage-audit",f"targets={tc}; support={sc}."),("preflight","duplicate-preflight","50 English/Kuku surfaces unique and absent."),("preflight","static-guard-pass","AST 50 literal calls; source/sense/frame/lint contracts passed.")]
    for ph,et,d in events:record_event(db,batch_label=LABEL,phase=ph,event_type=et,actor="codex",detail=d,artifact_path=LOG,created_at=NOW)
    record_event(db,batch_label=LABEL,phase="bank",event_type="bank-success",actor="codex",detail=f"Banked 50 Rule 351 rows under_review; verified {verified}; words {words}.",command="python3 batch_scripts/bank_393.py",output_excerpt="50 under_review",artifact_path=LOG,created_at=NOW);db.commit();print("banked batch-393: 50 rows under_review");return 0
if __name__=="__main__":raise SystemExit(main())
