#!/usr/bin/env python3
"""Bank batch-305: Rule 263 complementary reptile/amphibian non-singular pronoun perception sweep."""

from __future__ import annotations

import datetime as dt
import json
import sqlite3

from bank_294 import (
    DENY_ENGLISH,
    DENY_KUKU as BASE_DENY_KUKU,
    TARGET_HEADS,
    english_has_denied,
    has_target_morphology,
    has_token,
    row,
)
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-305"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
PROCESS_LOG = "process_logs/batch-305-reptile-amphibian-complementary-nonsingular-pronoun-perception-after-rule262-process.md"
SUPPORT = {"ngali", "ngaliny", "yubal", "nganjin", "ngana", "yaluy", "yinyay", "nyajil"}
PRONOUN_SUPPORT = {"ngali", "ngaliny", "yubal", "nganjin", "ngana"}
EXTRA_DENY_KUKU = {
    "ngalingan", "ngalinyan", "yubalan", "nganjinan", "nganangan",
    "ngalininy", "ngalinyiny", "yubaliny", "nganjininy", "ngananiny",
    "ngalinka", "ngalinyanka", "yubalanka", "nganjinanka", "ngananka",
    "ngalinda", "ngalinyanda", "yubalanda", "nganjinanda", "ngananda",
    "ngalindamuny", "ngalinyandamuny", "yubalandamuny", "nganjinandamuny", "nganandamuny",
    "ngalinji", "ngalinyanji", "yubalanji", "nganjinanji", "ngananji",
    "ngalinga", "ngalinyanga", "yubalanga", "nganjinanga", "ngananga",
    "bala", "darrba", "jarrabina", "jayju", "jungarr", "kukur", "mali", "murramu", "ngumbi", "yawa",
    "balarr", "dijaraban", "kalburiji", "mawal", "munudumbun", "munyurri", "nakawarra", "ngalmnbu", "yarrka", "yiljun",
    "baymbay", "darkay", "kaduy", "karraway", "karruku", "kulil", "kuyalin", "marrkabina", "ngarrakaja", "nuwi",
}
DENY_KUKU = set(BASE_DENY_KUKU) | EXTRA_DENY_KUKU

EVIDENCE = {
    "bajuy": "Dictionary lines 559-567 give bajuy as noun 'lizard', definition 'slippery lizard', semantic domain fauna-reptile; Rule 263 selects lizard only. Patz grammar lines 2577-2603 source bare nominative ngali, ngaliny, yubal, nganjin, and ngana; lines 2682-2684 discuss inclusive/exclusive and second-person non-singular forms; lines 2838-2845 source yaluy/yinyay; and lines 3043-3049 source nyaji-l 'see'.",
    "bilngkumu": "Dictionary lines 2575-2585 give bilngkumu as noun 'crocodile' with salt-water source prose; Rule 263 selects crocodile only and leaves saltwater/habitat/danger rows closed. Patz grammar lines 2577-2603, 2682-2684, 2838-2845, and 3043-3049 source support.",
    "binanjal": "Dictionary lines 2726-2734 give binanjal as noun 'frill necked lizard', semantic domain fauna-reptile. Rule 263 selects the animal label only. Patz grammar lines 2577-2603, 2682-2684, 2838-2845, and 3043-3049 source support.",
    "bindimu": "Dictionary lines 2884-2901 give bindimu as black snake and a red-bellied black-snake alternate; Rule 263 selects black snake only and leaves alternate/colour-predicate expansion closed. Patz grammar lines 2577-2603, 2682-2684, 2838-2845, and 3043-3049 source support.",
    "bubal": "Dictionary lines 3397-3417 give bubal as species of tree snake and tree snake; Rule 263 selects tree snake only and leaves tree/habitat/biting prose closed. Patz grammar lines 2577-2603, 2682-2684, 2838-2845, and 3043-3049 source support.",
    "jijirrbay": "Dictionary lines 8955-8972 give jijirrbay as noun 'whip snake', semantic domain fauna-reptile. Rule 263 selects whip snake only. Patz grammar lines 2577-2603, 2682-2684, 2838-2845, and 3043-3049 source support.",
    "kabul": "Dictionary lines 11816-11833 give kabul as noun 'rock python', semantic domain fauna-reptile. Rule 263 selects rock python only and leaves rock/place/action prose closed. Patz grammar lines 2577-2603, 2682-2684, 2838-2845, and 3043-3049 source support.",
    "kalajarr": "Dictionary lines 12243-12251 give kalajarr as noun 'scrub goanna', semantic domain fauna-reptile. Rule 263 selects scrub goanna only and leaves scrub/habitat/food/action prose closed. Patz grammar lines 2577-2603, 2682-2684, 2838-2845, and 3043-3049 source support.",
    "kundurr": "Dictionary lines 15704-15720 give kundurr as noun 'death adder', semantic domain fauna-reptile. Rule 263 selects death adder as a lexical label only and leaves danger/poison/biting prose closed; kundurr-kundurr is not imported. Patz grammar lines 2577-2603, 2682-2684, 2838-2845, and 3043-3049 source support.",
    "yuday": "Dictionary lines 30662-30670 give yuday as noun 'frog' with large/edible source prose; Rule 263 selects frog only and leaves edible/rain/swamp/event rows closed. Patz grammar lines 2577-2603, 2682-2684, 2838-2845, and 3043-3049 source support.",
}

ROWS = [
    row(1, "We two, not you, see the lizard here.", "Ngali bajuy yaluy nyajil.", "ngali bajuy yaluy nyajil | 1du.EXCL.NOM lizard here see.NPST", "r263_1du_excl_target_here_see_bajuy", ["ngali", "bajuy", "yaluy", "nyajil"], EVIDENCE["bajuy"]),
    row(2, "We two, not you, see the crocodile here.", "Ngali bilngkumu yaluy nyajil.", "ngali bilngkumu yaluy nyajil | 1du.EXCL.NOM crocodile here see.NPST", "r263_1du_excl_target_here_see_bilngkumu", ["ngali", "bilngkumu", "yaluy", "nyajil"], EVIDENCE["bilngkumu"]),
    row(3, "We two, not you, see the frill necked lizard here.", "Ngali binanjal yaluy nyajil.", "ngali binanjal yaluy nyajil | 1du.EXCL.NOM frill.necked.lizard here see.NPST", "r263_1du_excl_target_here_see_binanjal", ["ngali", "binanjal", "yaluy", "nyajil"], EVIDENCE["binanjal"]),
    row(4, "We two, not you, see the black snake here.", "Ngali bindimu yaluy nyajil.", "ngali bindimu yaluy nyajil | 1du.EXCL.NOM black.snake here see.NPST", "r263_1du_excl_target_here_see_bindimu", ["ngali", "bindimu", "yaluy", "nyajil"], EVIDENCE["bindimu"]),
    row(5, "We two, not you, see the tree snake here.", "Ngali bubal yaluy nyajil.", "ngali bubal yaluy nyajil | 1du.EXCL.NOM tree.snake here see.NPST", "r263_1du_excl_target_here_see_bubal", ["ngali", "bubal", "yaluy", "nyajil"], EVIDENCE["bubal"]),
    row(6, "We two, not you, see the whip snake here.", "Ngali jijirrbay yaluy nyajil.", "ngali jijirrbay yaluy nyajil | 1du.EXCL.NOM whip.snake here see.NPST", "r263_1du_excl_target_here_see_jijirrbay", ["ngali", "jijirrbay", "yaluy", "nyajil"], EVIDENCE["jijirrbay"]),
    row(7, "We two, not you, see the rock python here.", "Ngali kabul yaluy nyajil.", "ngali kabul yaluy nyajil | 1du.EXCL.NOM rock.python here see.NPST", "r263_1du_excl_target_here_see_kabul", ["ngali", "kabul", "yaluy", "nyajil"], EVIDENCE["kabul"]),
    row(8, "We two, not you, see the scrub goanna here.", "Ngali kalajarr yaluy nyajil.", "ngali kalajarr yaluy nyajil | 1du.EXCL.NOM scrub.goanna here see.NPST", "r263_1du_excl_target_here_see_kalajarr", ["ngali", "kalajarr", "yaluy", "nyajil"], EVIDENCE["kalajarr"]),
    row(9, "We two, not you, see the death adder here.", "Ngali kundurr yaluy nyajil.", "ngali kundurr yaluy nyajil | 1du.EXCL.NOM death.adder here see.NPST", "r263_1du_excl_target_here_see_kundurr", ["ngali", "kundurr", "yaluy", "nyajil"], EVIDENCE["kundurr"]),
    row(10, "We two, not you, see the frog here.", "Ngali yuday yaluy nyajil.", "ngali yuday yaluy nyajil | 1du.EXCL.NOM frog here see.NPST", "r263_1du_excl_target_here_see_yuday", ["ngali", "yuday", "yaluy", "nyajil"], EVIDENCE["yuday"]),
    row(11, "You and I see the lizard there.", "Ngaliny bajuy yinyay nyajil.", "ngaliny bajuy yinyay nyajil | 1du.INCL.NOM lizard there see.NPST", "r263_1du_incl_target_there_see_bajuy", ["ngaliny", "bajuy", "yinyay", "nyajil"], EVIDENCE["bajuy"]),
    row(12, "You and I see the crocodile there.", "Ngaliny bilngkumu yinyay nyajil.", "ngaliny bilngkumu yinyay nyajil | 1du.INCL.NOM crocodile there see.NPST", "r263_1du_incl_target_there_see_bilngkumu", ["ngaliny", "bilngkumu", "yinyay", "nyajil"], EVIDENCE["bilngkumu"]),
    row(13, "You and I see the frill necked lizard there.", "Ngaliny binanjal yinyay nyajil.", "ngaliny binanjal yinyay nyajil | 1du.INCL.NOM frill.necked.lizard there see.NPST", "r263_1du_incl_target_there_see_binanjal", ["ngaliny", "binanjal", "yinyay", "nyajil"], EVIDENCE["binanjal"]),
    row(14, "You and I see the black snake there.", "Ngaliny bindimu yinyay nyajil.", "ngaliny bindimu yinyay nyajil | 1du.INCL.NOM black.snake there see.NPST", "r263_1du_incl_target_there_see_bindimu", ["ngaliny", "bindimu", "yinyay", "nyajil"], EVIDENCE["bindimu"]),
    row(15, "You and I see the tree snake there.", "Ngaliny bubal yinyay nyajil.", "ngaliny bubal yinyay nyajil | 1du.INCL.NOM tree.snake there see.NPST", "r263_1du_incl_target_there_see_bubal", ["ngaliny", "bubal", "yinyay", "nyajil"], EVIDENCE["bubal"]),
    row(16, "You and I see the whip snake there.", "Ngaliny jijirrbay yinyay nyajil.", "ngaliny jijirrbay yinyay nyajil | 1du.INCL.NOM whip.snake there see.NPST", "r263_1du_incl_target_there_see_jijirrbay", ["ngaliny", "jijirrbay", "yinyay", "nyajil"], EVIDENCE["jijirrbay"]),
    row(17, "You and I see the rock python there.", "Ngaliny kabul yinyay nyajil.", "ngaliny kabul yinyay nyajil | 1du.INCL.NOM rock.python there see.NPST", "r263_1du_incl_target_there_see_kabul", ["ngaliny", "kabul", "yinyay", "nyajil"], EVIDENCE["kabul"]),
    row(18, "You and I see the scrub goanna there.", "Ngaliny kalajarr yinyay nyajil.", "ngaliny kalajarr yinyay nyajil | 1du.INCL.NOM scrub.goanna there see.NPST", "r263_1du_incl_target_there_see_kalajarr", ["ngaliny", "kalajarr", "yinyay", "nyajil"], EVIDENCE["kalajarr"]),
    row(19, "You and I see the death adder there.", "Ngaliny kundurr yinyay nyajil.", "ngaliny kundurr yinyay nyajil | 1du.INCL.NOM death.adder there see.NPST", "r263_1du_incl_target_there_see_kundurr", ["ngaliny", "kundurr", "yinyay", "nyajil"], EVIDENCE["kundurr"]),
    row(20, "You and I see the frog there.", "Ngaliny yuday yinyay nyajil.", "ngaliny yuday yinyay nyajil | 1du.INCL.NOM frog there see.NPST", "r263_1du_incl_target_there_see_yuday", ["ngaliny", "yuday", "yinyay", "nyajil"], EVIDENCE["yuday"]),
    row(21, "You two see the lizard here.", "Yubal bajuy yaluy nyajil.", "yubal bajuy yaluy nyajil | 2du.NOM lizard here see.NPST", "r263_2du_target_here_see_bajuy", ["yubal", "bajuy", "yaluy", "nyajil"], EVIDENCE["bajuy"]),
    row(22, "You two see the crocodile here.", "Yubal bilngkumu yaluy nyajil.", "yubal bilngkumu yaluy nyajil | 2du.NOM crocodile here see.NPST", "r263_2du_target_here_see_bilngkumu", ["yubal", "bilngkumu", "yaluy", "nyajil"], EVIDENCE["bilngkumu"]),
    row(23, "You two see the frill necked lizard here.", "Yubal binanjal yaluy nyajil.", "yubal binanjal yaluy nyajil | 2du.NOM frill.necked.lizard here see.NPST", "r263_2du_target_here_see_binanjal", ["yubal", "binanjal", "yaluy", "nyajil"], EVIDENCE["binanjal"]),
    row(24, "You two see the black snake here.", "Yubal bindimu yaluy nyajil.", "yubal bindimu yaluy nyajil | 2du.NOM black.snake here see.NPST", "r263_2du_target_here_see_bindimu", ["yubal", "bindimu", "yaluy", "nyajil"], EVIDENCE["bindimu"]),
    row(25, "You two see the tree snake here.", "Yubal bubal yaluy nyajil.", "yubal bubal yaluy nyajil | 2du.NOM tree.snake here see.NPST", "r263_2du_target_here_see_bubal", ["yubal", "bubal", "yaluy", "nyajil"], EVIDENCE["bubal"]),
    row(26, "You two see the whip snake here.", "Yubal jijirrbay yaluy nyajil.", "yubal jijirrbay yaluy nyajil | 2du.NOM whip.snake here see.NPST", "r263_2du_target_here_see_jijirrbay", ["yubal", "jijirrbay", "yaluy", "nyajil"], EVIDENCE["jijirrbay"]),
    row(27, "You two see the rock python here.", "Yubal kabul yaluy nyajil.", "yubal kabul yaluy nyajil | 2du.NOM rock.python here see.NPST", "r263_2du_target_here_see_kabul", ["yubal", "kabul", "yaluy", "nyajil"], EVIDENCE["kabul"]),
    row(28, "You two see the scrub goanna here.", "Yubal kalajarr yaluy nyajil.", "yubal kalajarr yaluy nyajil | 2du.NOM scrub.goanna here see.NPST", "r263_2du_target_here_see_kalajarr", ["yubal", "kalajarr", "yaluy", "nyajil"], EVIDENCE["kalajarr"]),
    row(29, "You two see the death adder here.", "Yubal kundurr yaluy nyajil.", "yubal kundurr yaluy nyajil | 2du.NOM death.adder here see.NPST", "r263_2du_target_here_see_kundurr", ["yubal", "kundurr", "yaluy", "nyajil"], EVIDENCE["kundurr"]),
    row(30, "You two see the frog here.", "Yubal yuday yaluy nyajil.", "yubal yuday yaluy nyajil | 2du.NOM frog here see.NPST", "r263_2du_target_here_see_yuday", ["yubal", "yuday", "yaluy", "nyajil"], EVIDENCE["yuday"]),
    row(31, "We all, not you, see the lizard there.", "Nganjin bajuy yinyay nyajil.", "nganjin bajuy yinyay nyajil | 1pl.EXCL.NOM lizard there see.NPST", "r263_1pl_excl_target_there_see_bajuy", ["nganjin", "bajuy", "yinyay", "nyajil"], EVIDENCE["bajuy"]),
    row(32, "We all, not you, see the crocodile there.", "Nganjin bilngkumu yinyay nyajil.", "nganjin bilngkumu yinyay nyajil | 1pl.EXCL.NOM crocodile there see.NPST", "r263_1pl_excl_target_there_see_bilngkumu", ["nganjin", "bilngkumu", "yinyay", "nyajil"], EVIDENCE["bilngkumu"]),
    row(33, "We all, not you, see the frill necked lizard there.", "Nganjin binanjal yinyay nyajil.", "nganjin binanjal yinyay nyajil | 1pl.EXCL.NOM frill.necked.lizard there see.NPST", "r263_1pl_excl_target_there_see_binanjal", ["nganjin", "binanjal", "yinyay", "nyajil"], EVIDENCE["binanjal"]),
    row(34, "We all, not you, see the black snake there.", "Nganjin bindimu yinyay nyajil.", "nganjin bindimu yinyay nyajil | 1pl.EXCL.NOM black.snake there see.NPST", "r263_1pl_excl_target_there_see_bindimu", ["nganjin", "bindimu", "yinyay", "nyajil"], EVIDENCE["bindimu"]),
    row(35, "We all, not you, see the tree snake there.", "Nganjin bubal yinyay nyajil.", "nganjin bubal yinyay nyajil | 1pl.EXCL.NOM tree.snake there see.NPST", "r263_1pl_excl_target_there_see_bubal", ["nganjin", "bubal", "yinyay", "nyajil"], EVIDENCE["bubal"]),
    row(36, "We all, not you, see the whip snake there.", "Nganjin jijirrbay yinyay nyajil.", "nganjin jijirrbay yinyay nyajil | 1pl.EXCL.NOM whip.snake there see.NPST", "r263_1pl_excl_target_there_see_jijirrbay", ["nganjin", "jijirrbay", "yinyay", "nyajil"], EVIDENCE["jijirrbay"]),
    row(37, "We all, not you, see the rock python there.", "Nganjin kabul yinyay nyajil.", "nganjin kabul yinyay nyajil | 1pl.EXCL.NOM rock.python there see.NPST", "r263_1pl_excl_target_there_see_kabul", ["nganjin", "kabul", "yinyay", "nyajil"], EVIDENCE["kabul"]),
    row(38, "We all, not you, see the scrub goanna there.", "Nganjin kalajarr yinyay nyajil.", "nganjin kalajarr yinyay nyajil | 1pl.EXCL.NOM scrub.goanna there see.NPST", "r263_1pl_excl_target_there_see_kalajarr", ["nganjin", "kalajarr", "yinyay", "nyajil"], EVIDENCE["kalajarr"]),
    row(39, "We all, not you, see the death adder there.", "Nganjin kundurr yinyay nyajil.", "nganjin kundurr yinyay nyajil | 1pl.EXCL.NOM death.adder there see.NPST", "r263_1pl_excl_target_there_see_kundurr", ["nganjin", "kundurr", "yinyay", "nyajil"], EVIDENCE["kundurr"]),
    row(40, "We all, not you, see the frog there.", "Nganjin yuday yinyay nyajil.", "nganjin yuday yinyay nyajil | 1pl.EXCL.NOM frog there see.NPST", "r263_1pl_excl_target_there_see_yuday", ["nganjin", "yuday", "yinyay", "nyajil"], EVIDENCE["yuday"]),
    row(41, "We see the lizard here.", "Ngana bajuy yaluy nyajil.", "ngana bajuy yaluy nyajil | 1pl.INC.NOM lizard here see.NPST", "r263_1pl_incl_target_here_see_bajuy", ["ngana", "bajuy", "yaluy", "nyajil"], EVIDENCE["bajuy"]),
    row(42, "We see the crocodile here.", "Ngana bilngkumu yaluy nyajil.", "ngana bilngkumu yaluy nyajil | 1pl.INC.NOM crocodile here see.NPST", "r263_1pl_incl_target_here_see_bilngkumu", ["ngana", "bilngkumu", "yaluy", "nyajil"], EVIDENCE["bilngkumu"]),
    row(43, "We see the frill necked lizard here.", "Ngana binanjal yaluy nyajil.", "ngana binanjal yaluy nyajil | 1pl.INC.NOM frill.necked.lizard here see.NPST", "r263_1pl_incl_target_here_see_binanjal", ["ngana", "binanjal", "yaluy", "nyajil"], EVIDENCE["binanjal"]),
    row(44, "We see the black snake here.", "Ngana bindimu yaluy nyajil.", "ngana bindimu yaluy nyajil | 1pl.INC.NOM black.snake here see.NPST", "r263_1pl_incl_target_here_see_bindimu", ["ngana", "bindimu", "yaluy", "nyajil"], EVIDENCE["bindimu"]),
    row(45, "We see the tree snake here.", "Ngana bubal yaluy nyajil.", "ngana bubal yaluy nyajil | 1pl.INC.NOM tree.snake here see.NPST", "r263_1pl_incl_target_here_see_bubal", ["ngana", "bubal", "yaluy", "nyajil"], EVIDENCE["bubal"]),
    row(46, "We see the whip snake here.", "Ngana jijirrbay yaluy nyajil.", "ngana jijirrbay yaluy nyajil | 1pl.INC.NOM whip.snake here see.NPST", "r263_1pl_incl_target_here_see_jijirrbay", ["ngana", "jijirrbay", "yaluy", "nyajil"], EVIDENCE["jijirrbay"]),
    row(47, "We see the rock python here.", "Ngana kabul yaluy nyajil.", "ngana kabul yaluy nyajil | 1pl.INC.NOM rock.python here see.NPST", "r263_1pl_incl_target_here_see_kabul", ["ngana", "kabul", "yaluy", "nyajil"], EVIDENCE["kabul"]),
    row(48, "We see the scrub goanna here.", "Ngana kalajarr yaluy nyajil.", "ngana kalajarr yaluy nyajil | 1pl.INC.NOM scrub.goanna here see.NPST", "r263_1pl_incl_target_here_see_kalajarr", ["ngana", "kalajarr", "yaluy", "nyajil"], EVIDENCE["kalajarr"]),
    row(49, "We see the death adder here.", "Ngana kundurr yaluy nyajil.", "ngana kundurr yaluy nyajil | 1pl.INC.NOM death.adder here see.NPST", "r263_1pl_incl_target_here_see_kundurr", ["ngana", "kundurr", "yaluy", "nyajil"], EVIDENCE["kundurr"]),
    row(50, "We see the frog here.", "Ngana yuday yaluy nyajil.", "ngana yuday yaluy nyajil | 1pl.INC.NOM frog here see.NPST", "r263_1pl_incl_target_here_see_yuday", ["ngana", "yuday", "yaluy", "nyajil"], EVIDENCE["yuday"]),
]


def scan_static() -> list[str]:
    issues: list[str] = []
    if len(ROWS) != 50:
        issues.append(f"{LABEL}: expected 50 rows, found {len(ROWS)}")
    seen_ku: set[str] = set()
    for expected, row_data in enumerate(ROWS, start=1):
        seq, english, kuku, analysis, frame, _tier, words_used, loans_used, evidence, confidence = row_data
        label = f"{LABEL}.{seq:02d}"
        low = kuku.lower()
        english_low = english.lower()
        words = json.loads(words_used)
        if seq != expected:
            issues.append(f"{label}: sequence mismatch; expected {expected}")
        if not english[:1].isupper() or english[-1:] not in ".!?":
            issues.append(f"{label}: English punctuation/capitalization failure")
        if " | " not in analysis:
            issues.append(f"{label}: analysis missing gloss separator")
        if not frame.startswith("r263_"):
            issues.append(f"{label}: Rule 263 frame must start with r263_")
        if low in seen_ku:
            issues.append(f"{label}: duplicate Kuku surface within batch")
        seen_ku.add(low)
        if json.loads(loans_used):
            issues.append(f"{label}: no loans are admitted in Rule 263")
        for denied in DENY_KUKU:
            if has_token(low, denied):
                issues.append(f"{label}: denied carry-forward token {denied!r}")
        targets = [head for head in TARGET_HEADS if has_token(low, head)]
        if len(targets) != 1:
            issues.append(f"{label}: expected exactly one Rule 263 target reptile/amphibian noun, found {targets}")
        for head in targets:
            selected = TARGET_HEADS[head]
            dotted = selected.replace("-", ".").replace(" ", ".")
            if head not in words:
                issues.append(f"{label}: target head {head} missing from words_used")
            if selected not in english_low:
                issues.append(f"{label}: English must include selected sense {selected!r}")
            if selected not in analysis and dotted not in analysis:
                issues.append(f"{label}: analysis must gloss {head} as {selected}")
            if has_target_morphology(low, head):
                issues.append(f"{label}: target head {head} has forbidden morphology")
        for support in SUPPORT:
            if has_token(low, support) and support not in words:
                issues.append(f"{label}: support {support} missing from words_used")
        pronouns = [pronoun for pronoun in PRONOUN_SUPPORT if has_token(low, pronoun)]
        if len(pronouns) != 1:
            issues.append(f"{label}: rows require exactly one bare nominative non-singular pronoun, found {pronouns}")
        if 1 <= seq <= 10 and (not low.startswith("ngali ") or not low.endswith(" yaluy nyajil.") or len(low.split()) != 4):
            issues.append(f"{label}: rows 1-10 require Ngali TARGET yaluy nyajil")
        if 11 <= seq <= 20 and (not low.startswith("ngaliny ") or not low.endswith(" yinyay nyajil.") or len(low.split()) != 4):
            issues.append(f"{label}: rows 11-20 require Ngaliny TARGET yinyay nyajil")
        if 21 <= seq <= 30 and (not low.startswith("yubal ") or not low.endswith(" yaluy nyajil.") or len(low.split()) != 4):
            issues.append(f"{label}: rows 21-30 require Yubal TARGET yaluy nyajil")
        if 31 <= seq <= 40 and (not low.startswith("nganjin ") or not low.endswith(" yinyay nyajil.") or len(low.split()) != 4):
            issues.append(f"{label}: rows 31-40 require Nganjin TARGET yinyay nyajil")
        if 41 <= seq <= 50 and (not low.startswith("ngana ") or not low.endswith(" yaluy nyajil.") or len(low.split()) != 4):
            issues.append(f"{label}: rows 41-50 require Ngana TARGET yaluy nyajil")
        if any(english_has_denied(english_low, bad) for bad in DENY_ENGLISH):
            issues.append(f"{label}: denied reptile/amphibian behavior/use/habitat/story/body-part/source-prose field in English")
        if not evidence or not confidence:
            issues.append(f"{label}: missing evidence/confidence")
    return issues


def main() -> int:
    issues = scan_static()
    if issues:
        print("pre-bank scan failed:")
        for issue in issues:
            print(f"  - {issue}")
        return 1

    db = sqlite3.connect(DB)
    db.execute("PRAGMA foreign_keys = ON")
    db.execute("BEGIN")
    ensure_schema(db)
    existing = db.execute("SELECT id FROM batches WHERE label=?", (LABEL,)).fetchone()
    if existing:
        batch_id = existing[0]
        accepted = db.execute(
            "SELECT COUNT(*) FROM sentences WHERE batch_id=? AND status IN ('accepted','revised')",
            (batch_id,),
        ).fetchone()[0]
        if accepted:
            raise SystemExit(f"{LABEL} already has accepted/revised rows; refusing to overwrite")
        db.execute("DELETE FROM reviews WHERE sentence_id IN (SELECT id FROM sentences WHERE batch_id=?)", (batch_id,))
        db.execute("DELETE FROM lessons WHERE batch_id=?", (batch_id,))
        db.execute("DELETE FROM sentences WHERE batch_id=?", (batch_id,))
        db.execute("UPDATE batches SET notes=?, created_at=? WHERE id=?", ("rebanked under_review", NOW, batch_id))
    else:
        db.execute(
            "INSERT INTO batches(label, cheatsheet_version, guide_version, notes, created_at) VALUES(?,?,?,?,?)",
            (LABEL, "Rule 263 draft", "operator-guide-2026-07-09", "draft under review", NOW),
        )
        batch_id = db.execute("SELECT id FROM batches WHERE label=?", (LABEL,)).fetchone()[0]

    collisions: list[str] = []
    for seq, _english, kuku, *_rest in ROWS:
        found = db.execute(
            """
            SELECT b.label, s.seq, s.status
            FROM sentences s JOIN batches b ON b.id=s.batch_id
            WHERE lower(s.kuku)=lower(?) AND s.status IN ('accepted','revised','under_review')
            """,
            (kuku,),
        ).fetchall()
        if found:
            collisions.append(f"{seq}: {kuku} -> {found}")
    if collisions:
        raise SystemExit("collision scan failed:\n" + "\n".join(collisions))

    db.executemany(
        """
        INSERT INTO sentences(
          batch_id, seq, english, kuku, analysis, frame, tier, words_used,
          loans_used, evidence, status, confidence, created_at
        )
        VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)
        """,
        [
            (
                batch_id,
                seq,
                english,
                kuku,
                analysis,
                frame,
                tier,
                words_used,
                loans_used,
                evidence,
                "under_review",
                confidence,
                NOW,
            )
            for seq, english, kuku, analysis, frame, tier, words_used, loans_used, evidence, confidence in ROWS
        ],
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="source",
        event_type="source-readback",
        actor="claude-main",
        detail="Rule 263 source pass checked dictionary lines for bajuy lizard, bilngkumu crocodile, binanjal frill necked lizard, bindimu black snake, bubal tree snake, jijirrbay whip snake, kabul rock python, kalajarr scrub goanna, kundurr death adder, and yuday frog; Patz grammar lines 2577-2603 for bare nominative ngali, ngaliny, yubal, nganjin, and ngana; lines 2682-2684 for inclusive/exclusive and second-person non-singular discussion; lines 2838-2845 for yaluy/yinyay; and lines 3043-3049 for nyaji-l.",
        artifact_path=PROCESS_LOG,
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="planning",
        event_type="debt-sweep-scope",
        actor="claude-main",
        detail="Selected Rule 263 complementary reptile/amphibian non-singular pronoun perception sweep after Rule 262: same ten checked Rule 252/261 reptile/amphibian labels in zero-collision nominative-pronoun perception bands using ngali, ngaliny, yubal, nganjin, and ngana with the here/there pairing complementary to Rule 262. All reptile behavior/use/habitat/story/body-part/source-prose, target-case, pronoun-case, demonstrative-case, and perception-compound semantics remain closed.",
        artifact_path=PROCESS_LOG,
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="preflight",
        event_type="coverage-audit",
        actor="claude-main",
        detail="Pre-batch token-aware target coverage among accepted/revised rows after Rule 262: bajuy 28, bilngkumu 74, binanjal 24, bindimu 25, bubal 22, jijirrbay 21, kabul 27, kalajarr 24, kundurr 23, and yuday 26. Support coverage: ngali 189, ngaliny 124, yubal 135, nganjin 141, ngana 889, yaluy 2423, yinyay 2676, nyajil 2967.",
        artifact_path=PROCESS_LOG,
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="preflight",
        event_type="duplicate-preflight",
        actor="claude-main",
        detail="Exact duplicate preflight over the final 50 Rule 263 Kuku surfaces returned zero accepted, revised, or under-review collisions before banking.",
        command="sqlite3 synthetic.db planned surface collision query",
        output_excerpt="0 rows",
        artifact_path=PROCESS_LOG,
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="preflight",
        event_type="static-guard-pass",
        actor="claude-main",
        detail="Static guard passed: 50 rows, one checked target per row, one bare nominative non-singular pronoun per row, correct complementary yaluy/yinyay band, no loans, no denied Kuku tokens, no denied English behavior/use/habitat/story/body-part/source-prose fields, no target morphology, no support inflection.",
        command="python3 batch_scripts/bank_305.py scan_static",
        output_excerpt="static guard passed before insert",
        artifact_path="batch_scripts/bank_305.py",
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="bank",
        event_type="bank-success",
        actor="claude-main",
        detail="Banked 50 hand-authored Rule 263 complementary reptile/amphibian non-singular pronoun perception rows as under_review.",
        command="python3 batch_scripts/bank_305.py",
        artifact_path="batch_scripts/bank_305.py",
        created_at=NOW,
    )
    db.commit()
    count = db.execute("SELECT COUNT(*) FROM sentences WHERE batch_id=?", (batch_id,)).fetchone()[0]
    print(f"banked {LABEL}: {count} rows under_review")
    return 0


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