#!/usr/bin/env python3
"""
===============================================================================
OPTIMIZED ITERATIVE SEGMENTED SIEVE CUBIC FROBENIUS + $620 CHALLENGE HUNTER
CONTINUOUS POLY-2 LEARNING + GAP-SPIRAL ACCELERATED SKIPPING
RAM-FIRST / LOW-I-O LEARNING EDITION -- v6
===============================================================================

IMPORTANT
---------

The exact mathematical sieve remains authoritative.

The learned accelerator is heuristic and may skip a candidate that would
otherwise survive.  Therefore:

    --shortcut-search
        = exhaustive mathematical search

    --learned-shortcut-search
        = heuristic accelerated search

The $620 verifier remains authoritative whenever a candidate reaches it.

WHAT CHANGED IN v6
-------------------

v4 and v5 both modeled the accelerator as aggregate statistics over
residue/bucket classes (an O'Brien-Fleming boundary, then a per-cell SPRT).
Both were real fixes to real problems in their turn, and both were more
machine than was actually asked for. The instruction was direct: "start
with an aggressive skip RIGHT AWAY using the first gap of hit found, the
full distance between those two integers, then follow a conservative
spiral." That's not a class-statistics model -- it's a mechanism that
acts on the raw stream of hits directly:

    1. Track the position of the most recent Tier-0 hit (a cubic
       Frobenius survivor). No aggregate class, no pooled sample.

    2. The moment a SECOND hit is found, the gap between them -- the
       actual, observed, local distance -- is used immediately, at full
       strength: skip that entire distance forward. No waiting for
       statistical confidence to build up first.

    3. Each subsequent time this happens, the fraction of the newly
       observed gap that gets skipped contracts by a factor of phi (the
       golden ratio) -- 1.0, then 1/phi, then 1/phi^2 -- the same
       constant underlying this whole framework's phi-lattice substrate
       (phi^2 = phi + 1), rather than an arbitrary decay rate. The
       contraction is floored at 1/phi^2 instead of decaying to zero, so
       the mechanism settles into a stable, permanently-conservative
       orbit rather than eventually going inert. That floor is the one
       detail the instruction left open; everything else here is literal.

    4. A verified higher-tier hit (Poly-2 pass or $620 winner) triggers
       an immediate stand-down: any active skip is cancelled and skipping
       pauses for a short cooldown before the spiral resumes at its floor.

This is deliberately simpler than v4/v5. One running position in the
p-stream, globally, not 32 residue classes and 256 bucket classes each
carrying their own statistical state. The whole point of using a real,
directly-observed gap instead of an aggregate class rate is that it
doesn't need hundreds of pooled observations before it can act -- two
hits are enough.

Honesty about what this trades away: a single observed gap is a
high-variance estimate (inter-hit spacing among rare, roughly
Poisson-like events varies a lot by chance), so the first aggressive
skip is a real gamble on one data point, by design, per the instruction.
The golden-ratio contraction is what keeps that gamble from compounding
-- each subsequent skip trusts a smaller fraction of what it sees, so a
single unlucky first gap doesn't propagate into an ever-larger blind
spot. This mode remains explicitly heuristic; --shortcut-search remains
the authoritative exhaustive fallback.

The learning log schema is additive. v6 adds [GAP ARM], [GAP CHECKPOINT],
and [GAP TIER HIT] events; older v4/v5 logs (LEARN CHECKPOINT, LEARN TIER
HIT, etc.) are simply not read by this version's recovery, which is the
correct/safe default -- v6 starts its own gap tracking fresh rather than
guessing at continuity from a differently-shaped model's state.
"""

import sys
import time
import math
import os
from typing import List, Tuple, Dict, Any, Optional, Iterator, Set


# =============================================================================
# CONFIGURATION
# =============================================================================

START = 5
LIMIT = 999_999_999

DISPLAY_INTERVAL = 0.50
SEGMENT_SIZE = 524288

SHORTCUT_LOG_LINES = 10
LINEAR_LOG_LINES = 8


# =============================================================================
# POLY-2 LEARNING
# =============================================================================

POLY2_WINDOW_SIZE = 20
POLY2_SUSPEND_AFTER = 20
POLY2_REPROBE_AFTER = 2000
POLY2_MIN_LEARNING_ATTEMPTS = 20


# =============================================================================
# q MODULAR SCREEN
# =============================================================================

Q_SCREEN_PRIMES = (
    7, 11, 13, 17, 19, 23, 29, 31,
    37, 41, 43, 47
)


# =============================================================================
# PERSISTENT LEARNING
# =============================================================================

LOG_FILENAME = "cubic_frobenius_620_learning_v3.log"

LEARN_CHECKPOINT_EVERY = 50_000


# =============================================================================
# TERMINAL COLORS
# =============================================================================

GREEN = "\033[92m"
RED = "\033[91m"
YELLOW = "\033[93m"
CYAN = "\033[96m"
MAGENTA = "\033[95m"
RESET = "\033[0m"

CLEAR_LINE = "\033[K"
MOVE_UP = "\033[A"


# =============================================================================
# PERSISTENT LEARNING LOGGER
# =============================================================================

class LearningLogger:

    def __init__(
        self,
        filename: str = LOG_FILENAME
    ):
        script_dir = os.path.dirname(
            os.path.abspath(__file__)
        )

        self.path = os.path.join(
            script_dir,
            filename
        )

        self.handle = open(
            self.path,
            "a",
            encoding="utf-8",
            buffering=1
        )

        self.closed = False

    def write(
        self,
        event: str,
        n: Optional[int] = None,
        p: Optional[int] = None,
        q: Optional[int] = None,
        attempt: Optional[int] = None,
        passes: Optional[int] = None,
        saved: Optional[int] = None,
        failures: Optional[int] = None,
        reason: Optional[str] = None,
        signature: Optional[str] = None,
        observations: Optional[int] = None,
        useful: Optional[int] = None,
        bucket: Optional[int] = None,
        score: Optional[float] = None,
        skip_count: Optional[int] = None,
        start_bucket: Optional[int] = None,
        end_bucket: Optional[int] = None,
        probes: Optional[int] = None,
        total_observations: Optional[int] = None,
        baseline: Optional[float] = None,
        threshold: Optional[float] = None,
        tier: Optional[str] = None,
        info_fraction: Optional[float] = None,
        z_score: Optional[float] = None,
        z_boundary: Optional[float] = None,
        chi2: Optional[float] = None,
        chi2_crit: Optional[float] = None,
        llr: Optional[float] = None
    ) -> None:

        if self.closed:
            return

        timestamp = time.strftime(
            "%Y-%m-%d %H:%M:%S"
        )

        fields = []

        values = (
            ("n", n),
            ("p", p),
            ("q", q),
            ("attempt", attempt),
            ("passes", passes),
            ("failures", failures),
            ("saved", saved),
            ("reason", reason),
            ("signature", signature),
            ("observations", observations),
            ("useful", useful),
            ("bucket", bucket),
            ("score", score),
            ("skip_count", skip_count),
            ("start_bucket", start_bucket),
            ("end_bucket", end_bucket),
            ("probes", probes),
            ("total_observations", total_observations),
            ("baseline", baseline),
            ("threshold", threshold),
            ("tier", tier),
            ("info_fraction", info_fraction),
            ("z_score", z_score),
            ("z_boundary", z_boundary),
            ("chi2", chi2),
            ("chi2_crit", chi2_crit),
            ("llr", llr)
        )

        for key, value in values:

            if value is not None:
                fields.append(
                    f"{key}={value}"
                )

        self.handle.write(
            f"{timestamp} | "
            f"[{event}] "
            f"{' | '.join(fields)}\n"
        )

    def flush(self) -> None:

        if self.closed:
            return

        try:
            self.handle.flush()
        except Exception:
            pass

    def close(self) -> None:

        if self.closed:
            return

        try:
            self.handle.flush()
            self.handle.close()
        except Exception:
            pass

        self.closed = True

    def __enter__(self):
        return self

    def __exit__(
        self,
        exc_type,
        exc,
        tb
    ):
        self.close()


# =============================================================================
# SMALL PRIME CACHE
# =============================================================================

SMALL_PRIME_POOL = [
    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
    67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137,
    139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211,
    223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
    293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379,
    383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461,
    463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563,
    569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643,
    647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739,
    743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
    839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937,
    941, 947, 953, 967, 971, 977, 983, 991, 997
]


# =============================================================================
# INTEGER HELPERS
# =============================================================================

def ext_gcd_int(
    a: int,
    b: int
) -> Tuple[int, int, int]:

    x0, x1 = 1, 0
    y0, y1 = 0, 1

    while b != 0:

        q, a, b = a // b, b, a % b

        x0, x1 = x1, x0 - q * x1
        y0, y1 = y1, y0 - q * y1

    return a, x0, y0


def mod_inv_int(
    a: int,
    m: int
) -> int:

    g, x, _ = ext_gcd_int(
        a,
        m
    )

    if g != 1:
        raise ValueError(g)

    return x % m


# =============================================================================
# POLYNOMIAL ARITHMETIC
# =============================================================================

def poly_clean(
    p: List[int]
) -> List[int]:

    while p and p[-1] == 0:
        p.pop()

    return p


def poly_add(
    a: List[int],
    b: List[int],
    n: int
) -> List[int]:

    res = [0] * max(
        len(a),
        len(b)
    )

    for i in range(
        len(res)
    ):

        ca = a[i] if i < len(a) else 0
        cb = b[i] if i < len(b) else 0

        res[i] = (
            ca + cb
        ) % n

    return poly_clean(res)


def poly_sub(
    a: List[int],
    b: List[int],
    n: int
) -> List[int]:

    res = [0] * max(
        len(a),
        len(b)
    )

    for i in range(
        len(res)
    ):

        ca = a[i] if i < len(a) else 0
        cb = b[i] if i < len(b) else 0

        res[i] = (
            ca - cb
        ) % n

    return poly_clean(res)


def poly_mul(
    a: List[int],
    b: List[int],
    n: int
) -> List[int]:

    if not a or not b:
        return []

    res = [0] * (
        len(a) +
        len(b) -
        1
    )

    for i, ca in enumerate(a):

        if ca == 0:
            continue

        for j, cb in enumerate(b):

            if cb == 0:
                continue

            res[i + j] = (
                res[i + j] +
                ca * cb
            ) % n

    return poly_clean(res)


def poly_make_monic(
    p: List[int],
    n: int
) -> List[int]:

    p = poly_clean(
        p[:]
    )

    if not p:
        return p

    lead = p[-1]

    if lead == 1:
        return p

    inv = mod_inv_int(
        lead,
        n
    )

    return [
        (c * inv) % n
        for c in p
    ]


def poly_divmod(
    num: List[int],
    den: List[int],
    n: int
) -> Tuple[List[int], List[int]]:

    num = poly_clean(
        num[:]
    )

    den = poly_clean(
        den[:]
    )

    if not den:
        raise ZeroDivisionError(
            "Polynomial division by zero."
        )

    if not num:
        return [], []

    if len(num) < len(den):
        return [], num

    quot = [0] * (
        len(num) -
        len(den) +
        1
    )

    lead_inv = mod_inv_int(
        den[-1],
        n
    )

    while (
        num
        and
        len(num) >= len(den)
    ):

        deg_diff = (
            len(num) -
            len(den)
        )

        q_coeff = (
            num[-1] *
            lead_inv
        ) % n

        quot[
            deg_diff
        ] = q_coeff

        if q_coeff:

            for i, dc in enumerate(
                den
            ):

                num[
                    deg_diff + i
                ] = (
                    num[
                        deg_diff + i
                    ] -
                    q_coeff * dc
                ) % n

        poly_clean(
            num
        )

    return (
        poly_clean(quot),
        poly_clean(num)
    )


def poly_gcd(
    a: List[int],
    b: List[int],
    n: int
) -> List[int]:

    a = poly_clean(
        a[:]
    )

    b = poly_clean(
        b[:]
    )

    while b:

        _, r = poly_divmod(
            a,
            b,
            n
        )

        a, b = b, r

    if not a:
        return []

    return poly_make_monic(
        a,
        n
    )


def poly_powmod(
    base: List[int],
    exp: int,
    mod_poly: List[int],
    n: int
) -> List[int]:

    res = [1]

    curr = poly_clean(
        base[:]
    )

    while exp > 0:

        if exp & 1:

            res = poly_mul(
                res,
                curr,
                n
            )

            _, res = poly_divmod(
                res,
                mod_poly,
                n
            )

        exp >>= 1

        if exp:

            curr = poly_mul(
                curr,
                curr,
                n
            )

            _, curr = poly_divmod(
                curr,
                mod_poly,
                n
            )

    return res


def poly_eval_composition(
    outer: List[int],
    inner: List[int],
    mod_poly: List[int],
    n: int
) -> List[int]:

    res: List[int] = []

    curr_power = [1]

    for coeff in outer:

        if coeff != 0:

            term = [
                (c * coeff) % n
                for c in curr_power
            ]

            res = poly_add(
                res,
                term,
                n
            )

        curr_power = poly_mul(
            curr_power,
            inner,
            n
        )

        _, curr_power = poly_divmod(
            curr_power,
            mod_poly,
            n
        )

    if res:

        _, res = poly_divmod(
            res,
            mod_poly,
            n
        )

    return poly_clean(res)


# =============================================================================
# FROBENIUS AUDITOR
# =============================================================================

class FrobeniusAuditor:

    def __init__(
        self,
        n: int,
        poly_coeffs: List[int]
    ):

        self.n = n

        self.f0 = poly_clean([
            c % n
            for c in poly_coeffs
        ])

        self.deg = (
            len(self.f0) - 1
        )

    def execute_audit(
        self
    ) -> Dict[str, Any]:

        report = {
            "candidate": self.n,
            "polynomial": self.f0[:],
            "degree": self.deg,
            "preamble_passed": False,
            "factorization_passed": False,
            "frobenius_passed": False,
            "composite_factor_found": None,
            "stage_failures": [],
            "factors_discovered": {}
        }

        check_val = 44

        g = math.gcd(
            self.n,
            check_val
        )

        if g > 1 and g != self.n:

            report[
                "composite_factor_found"
            ] = g

            report[
                "stage_failures"
            ].append(
                "PREAMBLE_GCD_FAULT"
            )

            return report

        report[
            "preamble_passed"
        ] = True

        curr_f = self.f0[:]

        factors: Dict[
            int,
            List[int]
        ] = {}

        try:

            x_pow_n = poly_powmod(
                [0, 1],
                self.n,
                self.f0,
                self.n
            )

            current_x_pow = x_pow_n[:]

            for i in range(
                1,
                self.deg + 1
            ):

                if len(curr_f) <= 1:
                    break

                g_x = poly_sub(
                    current_x_pow,
                    [0, 1],
                    self.n
                )

                _, g_x_reduced = poly_divmod(
                    g_x,
                    curr_f,
                    self.n
                )

                F_i = poly_gcd(
                    g_x_reduced,
                    curr_f,
                    self.n
                )

                if len(F_i) > 1:

                    factors[i] = F_i

                    _, curr_f = poly_divmod(
                        curr_f,
                        F_i,
                        self.n
                    )

                if i < self.deg:

                    current_x_pow = poly_eval_composition(
                        current_x_pow,
                        x_pow_n,
                        self.f0,
                        self.n
                    )

            if len(curr_f) > 1:

                existing = factors.get(
                    self.deg,
                    []
                )

                factors[
                    self.deg
                ] = poly_add(
                    existing,
                    curr_f,
                    self.n
                )

        except ValueError as exc:

            factor = int(
                exc.args[0]
            )

            report[
                "composite_factor_found"
            ] = factor

            report[
                "stage_failures"
            ].append(
                "FACTORIZATION_MODULAR_COLLAPSE"
            )

            return report

        report[
            "factors_discovered"
        ] = {
            degree: coeffs
            for degree, coeffs in factors.items()
            if len(coeffs) > 1
        }

        total_deg = sum(
            len(poly) - 1
            for poly in factors.values()
        )

        if total_deg != self.deg:

            report[
                "stage_failures"
            ].append(
                "INVALID_DEGREE_FIELDS"
            )

            return report

        report[
            "factorization_passed"
        ] = True

        frobenius_verified = True

        try:

            for degree, F_i in factors.items():

                if len(F_i) <= 1:
                    continue

                _, x_n_reduced = poly_divmod(
                    x_pow_n,
                    F_i,
                    self.n
                )

                composition_result = poly_clean(
                    poly_eval_composition(
                        F_i,
                        x_n_reduced,
                        F_i,
                        self.n
                    )
                )

                if len(
                    composition_result
                ) > 0:

                    frobenius_verified = False

                    report[
                        "stage_failures"
                    ].append(
                        "FROBENIUS_MAPPING_DEVIATION_DEG_"
                        f"{degree}"
                    )

        except ValueError as exc:

            factor = int(
                exc.args[0]
            )

            report[
                "composite_factor_found"
            ] = factor

            report[
                "stage_failures"
            ].append(
                "FROBENIUS_STAGE_COLLAPSE"
            )

            return report

        if frobenius_verified:
            report[
                "frobenius_passed"
            ] = True

        return report


# =============================================================================
# FAST PRIMALITY
# =============================================================================

def is_prime_fast(
    n: int
) -> bool:

    if n < 2:
        return False

    for p in SMALL_PRIME_POOL:

        if n % p == 0:
            return n == p

    d = n - 1
    s = 0

    while (
        d & 1
    ) == 0:

        d >>= 1
        s += 1

    if n < 18446744073709551616:

        bases = (
            2,
            325,
            9375,
            28178,
            450775,
            9780504,
            1795265022
        )

    else:

        bases = (
            2,
            3,
            5,
            7,
            11,
            13,
            17,
            19,
            23,
            29,
            31,
            37
        )

    for a in bases:

        a %= n

        if a == 0:
            continue

        x = pow(
            a,
            d,
            n
        )

        if (
            x == 1
            or
            x == n - 1
        ):
            continue

        for _ in range(
            s - 1
        ):

            x = (
                x * x
            ) % n

            if x == n - 1:
                break

        else:
            return False

    return True


# =============================================================================
# q MODULAR SCREEN
# =============================================================================

def q_small_prime_screen(
    p: int,
    q: int
) -> bool:

    for r in Q_SCREEN_PRIMES:

        if (
            q != r
            and
            q % r == 0
        ):
            return False

    return True


# =============================================================================
# SEGMENTED PRIME GENERATOR
# =============================================================================

def base_primes_upto(
    limit: int
) -> List[int]:

    if limit < 2:
        return []

    sieve = (
        bytearray(b"\x01") *
        (limit + 1)
    )

    sieve[
        0:2
    ] = b"\x00\x00"

    root = math.isqrt(
        limit
    )

    for p in range(
        2,
        root + 1
    ):

        if sieve[p]:

            start = p * p

            count = (
                (limit - start) //
                p
            ) + 1

            sieve[
                start:
                limit + 1:
                p
            ] = (
                b"\x00" *
                count
            )

    return [
        i
        for i, value in enumerate(sieve)
        if value
    ]


def prime_yield_generator(
    start_bound: int,
    end_bound: int
) -> Iterator[int]:

    if end_bound < start_bound:
        return

    base_limit = math.isqrt(
        end_bound
    )

    small_primes = base_primes_upto(
        base_limit
    )

    low = max(
        2,
        start_bound
    )

    while low <= end_bound:

        high = min(
            low +
            SEGMENT_SIZE -
            1,
            end_bound
        )

        seg_len = (
            high -
            low +
            1
        )

        sieve_block = (
            bytearray(b"\x01") *
            seg_len
        )

        for p in small_primes:

            if p * p > high:
                break

            start_idx = max(
                p * p,
                (
                    (low + p - 1) //
                    p
                ) * p
            )

            if start_idx > high:
                continue

            offset = (
                start_idx -
                low
            )

            count = (
                (high - start_idx) //
                p
            ) + 1

            sieve_block[
                offset:
                offset +
                count * p:
                p
            ] = (
                b"\x00" *
                count
            )

        for i, value in enumerate(
            sieve_block
        ):

            if value:

                actual_num = (
                    low + i
                )

                if actual_num > 1:
                    yield actual_num

        low += SEGMENT_SIZE


# =============================================================================
# FIBONACCI / LUCAS
# =============================================================================

def fibonacci_pair_mod_iterative(
    k: int,
    modulus: int
) -> Tuple[int, int]:

    if modulus <= 0:
        raise ValueError(
            "modulus must be positive"
        )

    if k == 0:
        return (
            0,
            1 % modulus
        )

    a = 0
    b = 1

    for bit_index in range(
        k.bit_length() - 1,
        -1,
        -1
    ):

        c = (
            a *
            (
                (2 * b - a) %
                modulus
            )
        ) % modulus

        d = (
            a * a +
            b * b
        ) % modulus

        if (
            (k >> bit_index) & 1
        ):

            a = d

            b = (
                c + d
            ) % modulus

        else:

            a = c
            b = d

    return a, b


def fibonacci_and_lucas_mod_n(
    n: int
) -> Tuple[int, int]:

    f_k, f_k_plus_1 = (
        fibonacci_pair_mod_iterative(
            n + 1,
            n
        )
    )

    v_k = (
        2 * f_k_plus_1 -
        f_k
    ) % n

    return (
        f_k,
        v_k
    )


# =============================================================================
# SMALL FACTOR RECOVERY
# =============================================================================

def factor_small(
    n: int
) -> Optional[int]:

    if n % 2 == 0:
        return 2

    if n % 3 == 0:
        return 3

    d = 5
    step = 2

    while d * d <= n:

        if n % d == 0:
            return d

        d += step
        step = 6 - step

    return None


# =============================================================================
# $620 VERIFICATION
# =============================================================================

def verify_620(
    n: int
) -> Dict[str, Any]:

    prime = is_prime_fast(
        n
    )

    composite = not prime

    mod5 = n % 5

    residue_ok = (
        mod5 in (2, 3)
    )

    base2_residue = None
    base2_ok = False

    fib_residue = None
    lucas_residue = None
    fib_ok = False

    if residue_ok:

        base2_residue = pow(
            2,
            n - 1,
            n
        )

        base2_ok = (
            base2_residue == 1
        )

        if base2_ok:

            (
                fib_residue,
                lucas_residue
            ) = fibonacci_and_lucas_mod_n(
                n
            )

            fib_ok = (
                fib_residue == 0
            )

    return {
        "candidate": n,
        "prime": prime,
        "composite": composite,
        "n_mod_5": mod5,
        "residue_ok": residue_ok,
        "base2_residue": base2_residue,
        "base2_ok": base2_ok,
        "fibonacci_residue": fib_residue,
        "lucas_residue": lucas_residue,
        "fibonacci_ok": fib_ok,
        "620_candidate": (
            composite
            and
            residue_ok
            and
            base2_ok
            and
            fib_ok
        )
    }


# =============================================================================
# FACTOR FORM
# =============================================================================

def factor_form_coefficients(
    ratio_strat: str
) -> Tuple[int, int]:

    if ratio_strat == "3p-2":
        return 3, -2

    if ratio_strat == "2p+1":
        return 2, 1

    if ratio_strat == "7p-6":
        return 7, -6

    raise ValueError(
        "Unknown ratio strategy."
    )


def candidate_mod5_classes(
    ratio_strat: str
) -> List[int]:

    a, b = factor_form_coefficients(
        ratio_strat
    )

    valid = []

    for r in range(
        1,
        5
    ):

        q_mod = (
            a * r + b
        ) % 5

        n_mod = (
            r * q_mod
        ) % 5

        if n_mod in (
            2,
            3
        ):
            valid.append(r)

    return valid


def strategy_is_mod5_impossible(
    ratio_strat: str
) -> bool:

    return (
        len(
            candidate_mod5_classes(
                ratio_strat
            )
        ) == 0
    )


def max_p_for_strategy(
    limit_upper: int,
    ratio_strat: str
) -> int:

    if limit_upper <= 0:
        return 0

    a, b = factor_form_coefficients(
        ratio_strat
    )

    discriminant = (
        b * b +
        4 * a * limit_upper
    )

    max_p = max(
        2,
        (
            math.isqrt(
                max(
                    0,
                    discriminant
                )
            ) - b
        ) // (
            2 * a
        ) + 2
    )

    while (
        max_p > 0
        and
        max_p * (
            a * max_p + b
        ) >= limit_upper
    ):

        max_p -= 1

    while (
        (max_p + 1) > 0
        and
        (max_p + 1) * (
            a * (max_p + 1) + b
        ) < limit_upper
    ):

        max_p += 1

    return max_p


# =============================================================================
# LOG FIELD RECOVERY
# =============================================================================

def parse_log_fields(
    line: str
) -> Dict[str, Any]:

    result: Dict[str, Any] = {}

    if "|" not in line:
        return result

    parts = [
        x.strip()
        for x in line.split("|")
    ]

    for part in parts:

        # The [EVENT] tag shares a pipe-segment with whichever field
        # write() happens to emit first (fixed field order, filtered for
        # None), e.g. "[LEARN CHECKPOINT] signature=R:37". Strip any
        # leading bracketed tag so that field's key parses correctly --
        # without this, the first field on every event line silently
        # fails to match and is dropped.
        if part.startswith("["):

            close = part.find("]")

            if close != -1:

                part = part[close + 1:].strip()

        if "=" not in part:
            continue

        key, value = part.split(
            "=",
            1
        )

        key = key.strip()
        value = value.strip()

        if key in (
            "attempt",
            "passes",
            "failures",
            "saved",
            "n",
            "p",
            "q",
            "observations",
            "useful",
            "bucket",
            "skip_count",
            "start_bucket",
            "end_bucket",
            "probes",
            "total_observations"
        ):

            try:
                result[key] = int(value)
            except ValueError:
                pass

        elif key in (
            "score",
            "baseline",
            "threshold",
            "info_fraction",
            "z_score",
            "z_boundary",
            "chi2",
            "chi2_crit",
            "llr"
        ):

            try:
                result[key] = float(value)
            except ValueError:
                pass

        elif key in (
            "reason",
            "signature",
            "tier"
        ):

            result[key] = value

    return result


# =============================================================================
# POLY-2 LOG RECOVERY
# =============================================================================

def recover_poly2_learning(
    path: str
) -> Dict[str, Any]:

    state = {
        "attempts": 0,
        "passes": 0,
        "failures": 0,
        "saved": 0,
        "window": [],
        "suspended": False,
        "saved_since_probe": 0
    }

    if not os.path.exists(path):
        return state

    try:

        with open(
            path,
            "r",
            encoding="utf-8"
        ) as handle:

            for line in handle:

                if not any(
                    token in line
                    for token in (
                        "[POLY2 ATTEMPT]",
                        "[POLY2 PASS]",
                        "[POLY2 SAVED]"
                    )
                ):
                    continue

                fields = parse_log_fields(
                    line
                )

                if "attempt" in fields:
                    state["attempts"] = fields["attempt"]

                if "passes" in fields:
                    state["passes"] = fields["passes"]

                if "failures" in fields:
                    state["failures"] = fields["failures"]

                if "saved" in fields:
                    state["saved"] = fields["saved"]

                if "[POLY2 PASS]" in line:

                    state["window"].append(True)
                    state["suspended"] = False
                    state["saved_since_probe"] = 0

                elif "[POLY2 ATTEMPT]" in line:

                    state["window"].append(False)

                elif "[POLY2 SAVED]" in line:

                    reason = fields.get(
                        "reason",
                        ""
                    )

                    if reason == "SUSPEND":

                        state["suspended"] = True
                        state["saved_since_probe"] = 0

                    elif reason == "SUSPENDED":

                        state["suspended"] = True

                if len(
                    state["window"]
                ) > POLY2_WINDOW_SIZE:

                    state["window"].pop(0)

    except OSError:

        return state

    if (
        state["attempts"] >=
        POLY2_MIN_LEARNING_ATTEMPTS
        and
        len(state["window"]) >=
        POLY2_WINDOW_SIZE
        and
        not any(state["window"])
    ):

        state["suspended"] = True

    return state


# =============================================================================
# POLY-2 LEARNER
# =============================================================================

class Poly2Learner:

    def __init__(
        self,
        logger: LearningLogger
    ):

        recovered = recover_poly2_learning(
            logger.path
        )

        self.logger = logger

        self.attempts = recovered["attempts"]
        self.passes = recovered["passes"]
        self.failures = recovered["failures"]
        self.saved = recovered["saved"]
        self.window = recovered["window"]

        self.suspended = recovered["suspended"]

        self.saved_since_probe = (
            recovered["saved_since_probe"]
        )

        self.state = (
            "SUSPENDED"
            if self.suspended
            else
            "ACTIVE"
        )

    @property
    def pass_rate(
        self
    ) -> float:

        if not self.attempts:
            return 0.0

        return (
            self.passes /
            self.attempts
        )

    def _append_observation(
        self,
        passed: bool
    ) -> None:

        self.window.append(
            passed
        )

        if len(
            self.window
        ) > POLY2_WINDOW_SIZE:

            self.window.pop(0)

    def attempt(
        self,
        n: int,
        p: int,
        q: int,
        force_probe: bool = False
    ) -> Tuple[bool, str]:

        self.attempts += 1

        audit = FrobeniusAuditor(
            n,
            [-1, -1, 0, 1]
        ).execute_audit()

        passed = bool(
            audit["frobenius_passed"]
        )

        if passed:

            self.passes += 1

            self._append_observation(
                True
            )

            self.state = "ACTIVE"
            self.suspended = False
            self.saved_since_probe = 0

            self.logger.write(
                "POLY2 PASS",
                n=n,
                p=p,
                q=q,
                attempt=self.attempts,
                passes=self.passes,
                failures=self.failures,
                saved=self.saved,
                reason=(
                    "REPROBE_PASS"
                    if force_probe
                    else
                    "NORMAL_PASS"
                )
            )

            return True, "PASS"

        self.failures += 1

        self._append_observation(
            False
        )

        self.logger.write(
            "POLY2 ATTEMPT",
            n=n,
            p=p,
            q=q,
            attempt=self.attempts,
            passes=self.passes,
            failures=self.failures,
            saved=self.saved
        )

        if (
            not self.suspended
            and
            self.attempts >=
            POLY2_MIN_LEARNING_ATTEMPTS
            and
            len(self.window) >=
            POLY2_WINDOW_SIZE
            and
            not any(self.window)
        ):

            self.suspended = True
            self.state = "SUSPENDED"
            self.saved_since_probe = 0

            self.logger.write(
                "POLY2 SAVED",
                n=n,
                p=p,
                q=q,
                attempt=self.attempts,
                passes=self.passes,
                failures=self.failures,
                saved=self.saved,
                reason="SUSPEND"
            )

        return False, "FAIL"

    def save_one(
        self,
        n: int,
        p: int,
        q: int
    ) -> None:

        self.saved += 1
        self.saved_since_probe += 1

        if self.saved_since_probe == 1:

            self.logger.write(
                "POLY2 SAVED",
                n=n,
                p=p,
                q=q,
                attempt=self.attempts,
                passes=self.passes,
                failures=self.failures,
                saved=self.saved,
                reason="SUSPENDED"
            )

    def should_probe(
        self
    ) -> bool:

        return (
            self.suspended
            and
            self.saved_since_probe >=
            POLY2_REPROBE_AFTER
        )

    def begin_probe(
        self
    ) -> None:

        self.state = "PROBING"

    def status_text(
        self
    ) -> str:

        if self.state == "PROBING":

            return (
                f"PROBING "
                f"(Saved {self.saved:,})"
            )

        if self.suspended:

            return (
                f"SUSPENDED "
                f"(Saved {self.saved:,})"
            )

        return (
            f"ACTIVE "
            f"(Saved {self.saved:,})"
        )


# =============================================================================
# GAP-SPIRAL LEARNED ACCELERATOR
# =============================================================================

class GapSpiralController:

    """
    Statistical acceleration layer -- v6.

    v5's SPRT-per-class design was correct but the wrong shape for what
    was actually asked for: "start with an aggressive skip RIGHT AWAY
    using the first gap of hit found, the full distance between those two
    integers, then follow a conservative spiral." That's not an aggregate
    class-statistics model at all -- it's a direct, local mechanism
    operating on the raw stream of Tier-0 hits as they're found:

        1. Track the position of the most recent Tier-0 hit (a cubic
           Frobenius survivor).

        2. The moment a SECOND hit is found, the distance between them
           is real, observed, local evidence about how far apart hits
           tend to fall right now. Use it immediately, at FULL strength
           -- skip that entire distance forward from the second hit.
           No aggregate sample, no family test, no waiting.

        3. Each time this happens again, the fraction of the newly
           observed gap that gets skipped contracts by a factor of phi
           (the golden ratio) -- 1.0, then 1/phi, then 1/phi^2 -- which
           is where this framework's own foundational constant (phi^2 =
           phi + 1, the same identity underlying the phi-lattice
           substrate) does the damping instead of an arbitrary decay
           rate. The contraction is floored at 1/phi^2 (~38.2% of each
           newly observed gap) rather than decaying to zero, so the
           mechanism settles into a stable, permanently-conservative
           orbit instead of eventually going inert -- "spiral," not
           "decay to a point." That floor is the one detail the
           instruction didn't pin down; everything else here is literal.

        4. A verified higher-tier hit (Poly-2 pass or $620 winner) is
           stronger evidence than a Tier-0 survivor and triggers an
           immediate stand-down: any active skip is cancelled and skipping
           is paused entirely for a short cooldown before the spiral
           resumes at its floor.

    This is deliberately NOT a residue/bucket-class statistical model.
    It operates on one running position in the p-stream, globally, which
    is what makes it simple enough to act on a single observed gap instead
    of needing hundreds or thousands of pooled observations first.
    """

    def __init__(
        self,
        logger: LearningLogger,
        max_p: int
    ):

        self.logger = logger
        self.max_p = max(1, max_p)

        self.last_hit_p: Optional[int] = None
        self.cycle_index = 0

        self.active_skip_start: Optional[int] = None
        self.active_skip_end: Optional[int] = None

        self.cooldown_remaining = 0

        self.total_observations = 0
        self.total_useful = 0

        self.total_skipped = 0
        self.arm_events = 0
        self.tier_hit_counts: Dict[str, int] = {}

        self.last_gap = 0
        self.last_fraction = 0.0
        self.last_skip_size = 0

        self._recover()

    # -------------------------------------------------------------------------
    # Golden ratio, derived from its defining identity (phi^2 = phi + 1),
    # not a numeric literal.
    # -------------------------------------------------------------------------

    PHI = (1.0 + math.sqrt(5.0)) / 2.0

    # Cycle index at which the spiral's contraction bottoms out. Floored
    # at 1/phi^2 rather than decaying toward zero -- see class docstring.
    SPIRAL_FLOOR_CYCLE = 2

    # Hits-worth of pause after a verified higher-tier hit, before the
    # spiral resumes (at its floor -- not back at full aggression).
    TIER_HIT_COOLDOWN_HITS = 5

    # -------------------------------------------------------------------------
    # Persistent recovery
    # -------------------------------------------------------------------------

    def _recover(
        self
    ) -> None:

        path = self.logger.path

        if not os.path.exists(path):
            return

        try:

            with open(
                path,
                "r",
                encoding="utf-8"
            ) as handle:

                for line in handle:

                    if "[GAP CHECKPOINT]" in line:

                        fields = parse_log_fields(
                            line
                        )

                        if "p" in fields:
                            self.last_hit_p = fields["p"]

                        if "skip_count" in fields:
                            self.cycle_index = fields["skip_count"]

                        if "total_observations" in fields:
                            self.total_observations = fields[
                                "total_observations"
                            ]

                        if "useful" in fields:
                            self.total_useful = fields["useful"]

                    elif "[GAP TIER HIT]" in line:

                        fields = parse_log_fields(
                            line
                        )

                        tier = fields.get(
                            "tier",
                            "UNKNOWN"
                        )

                        self.tier_hit_counts[tier] = (
                            self.tier_hit_counts.get(tier, 0) + 1
                        )

        except OSError:
            pass

    def checkpoint(
        self
    ) -> None:

        self.logger.write(
            "GAP CHECKPOINT",
            p=self.last_hit_p,
            skip_count=self.cycle_index,
            total_observations=self.total_observations,
            useful=self.total_useful,
            reason="PERIODIC"
        )

        self.logger.flush()

    # -------------------------------------------------------------------------
    # Current spiral fraction
    # -------------------------------------------------------------------------

    @property
    def current_fraction(
        self
    ) -> float:

        return self.PHI ** (
            -min(
                self.cycle_index,
                self.SPIRAL_FLOOR_CYCLE
            )
        )

    # -------------------------------------------------------------------------
    # Per-candidate decision
    # -------------------------------------------------------------------------

    def decide_skip(
        self,
        p: int
    ) -> Tuple[bool, str]:

        if (
            self.active_skip_start is not None
            and
            self.active_skip_end is not None
        ):

            if p <= self.active_skip_end:

                self.total_skipped += 1

                return True, "GAP_SPIRAL_SKIP"

            self.active_skip_start = None
            self.active_skip_end = None

        return False, "EVALUATE"

    # -------------------------------------------------------------------------
    # Observation (every real Tier-0 evaluation)
    # -------------------------------------------------------------------------

    def observe(
        self,
        p: int,
        useful: bool
    ) -> None:

        self.total_observations += 1

        if useful:

            self.total_useful += 1

        if self.cooldown_remaining > 0:

            self.cooldown_remaining -= 1

            if useful:
                self.last_hit_p = p

            if self.total_observations % LEARN_CHECKPOINT_EVERY == 0:
                self.checkpoint()

            return

        if useful:

            if self.last_hit_p is not None:

                gap = p - self.last_hit_p

                if gap > 0:

                    fraction = self.current_fraction

                    skip_size = round(
                        fraction * gap
                    )

                    self.last_gap = gap
                    self.last_fraction = fraction
                    self.last_skip_size = skip_size

                    if skip_size > 0:

                        self.active_skip_start = p + 1
                        self.active_skip_end = p + skip_size

                        self.arm_events += 1

                        self.logger.write(
                            "GAP ARM",
                            p=p,
                            skip_count=skip_size,
                            score=fraction,
                            observations=gap,
                            start_bucket=self.active_skip_start,
                            end_bucket=self.active_skip_end,
                            reason=f"CYCLE_{self.cycle_index}"
                        )

                    self.cycle_index += 1

            self.last_hit_p = p

        if self.total_observations % LEARN_CHECKPOINT_EVERY == 0:

            self.checkpoint()

    # -------------------------------------------------------------------------
    # Tier-hit override (Poly-2 pass or $620 winner)
    # -------------------------------------------------------------------------

    def record_tier_hit(
        self,
        p: int,
        tier: str
    ) -> None:

        self.tier_hit_counts[tier] = (
            self.tier_hit_counts.get(tier, 0) + 1
        )

        self.active_skip_start = None
        self.active_skip_end = None
        self.cooldown_remaining = self.TIER_HIT_COOLDOWN_HITS

        self.logger.write(
            "GAP TIER HIT",
            p=p,
            tier=tier,
            observations=self.tier_hit_counts[tier],
            reason="COOLDOWN_TRIGGERED"
        )

        if (
            tier == "$620"
            and
            self.tier_hit_counts[tier] == 2
        ):

            self.logger.write(
                "LEARN MILESTONE",
                p=p,
                reason="GOLD_STANDARD_TWO_DATA_POINTS"
            )

    # -------------------------------------------------------------------------
    # Status / summary
    # -------------------------------------------------------------------------

    @property
    def global_yield(
        self
    ) -> float:

        if self.total_observations <= 0:
            return 0.0

        return (
            self.total_useful /
            self.total_observations
        )

    def status_text(
        self
    ) -> str:

        if self.cooldown_remaining > 0:

            return (
                f"COOLDOWN "
                f"({self.cooldown_remaining} hits left)"
            )

        if (
            self.active_skip_start is not None
            and
            self.active_skip_end is not None
        ):

            return (
                f"SKIPPING "
                f"{self.active_skip_start:,}-"
                f"{self.active_skip_end:,} "
                f"(cycle {self.cycle_index}, "
                f"{self.current_fraction * 100:.1f}%)"
            )

        return (
            f"WATCHING "
            f"(cycle {self.cycle_index}, "
            f"next fraction {self.current_fraction * 100:.1f}%, "
            f"yield={self.global_yield * 100:.3f}%)"
        )

    def summary(
        self
    ) -> Dict[str, Any]:

        return {
            "total_observations": self.total_observations,
            "total_useful": self.total_useful,
            "global_yield": self.global_yield,
            "total_skipped": self.total_skipped,
            "arm_events": self.arm_events,
            "cycle_index": self.cycle_index,
            "current_fraction": self.current_fraction,
            "last_gap": self.last_gap,
            "last_skip_size": self.last_skip_size,
            "tier_hits": dict(self.tier_hit_counts)
        }


# =============================================================================
# TERMINAL DASHBOARD
# =============================================================================

class TerminalDashboard:

    def __init__(
        self,
        title_text: str,
        log_window_size: int = 8
    ):

        self.title_text = title_text
        self.log_size = log_window_size
        self.logs: List[str] = []
        self.first_render = True

        self.total_lines = (
            self.log_size + 39
        )

    def add_log(
        self,
        text: str
    ) -> None:

        self.logs.append(
            text
        )

        if len(
            self.logs
        ) > self.log_size:

            self.logs.pop(0)

    @staticmethod
    def _rate(
        count: int,
        elapsed: float
    ) -> str:

        if elapsed <= 0:
            return "0.00/s"

        return (
            f"{count / elapsed:,.2f}/s"
        )

    @staticmethod
    def _percent(
        current: int,
        maximum: int
    ) -> str:

        if maximum <= 0:
            return "0.000%"

        return (
            f"{current / maximum * 100.0:,.3f}%"
        )

    def refresh(
        self,
        elapsed: float,
        pairs: int,
        cubic_survivors: int,
        poly2_status: str,
        sieve_status: str,
        hits: int,
        seed_p: int,
        strat_text: str,
        max_p: int,
        current_q: Optional[int] = None,
        current_candidate: Optional[int] = None,
        phase: str = "SEARCHING",
        q_tested: int = 0,
        q_rejected: int = 0,
        q_screen_rejected: int = 0,
        residue_rejected: int = 0,
        fermat_rejected: int = 0,
        quadratic_attempts: int = 0,
        quadratic_survivors: int = 0,
        quadratic_rejected: int = 0,
        poly1_attempts: int = 0,
        poly1_rejected: int = 0,
        poly2_attempts: int = 0,
        poly2_passed: int = 0,
        poly2_saved: int = 0,
        poly2_failures: int = 0,
        poly2_rate: float = 0.0,
        learned_status: str = "OFF",
        learned_cycle_index: int = 0,
        learned_fraction: float = 0.0,
        learned_last_gap: int = 0,
        learned_last_skip_size: int = 0,
        learned_total_skipped: int = 0,
        learned_arm_events: int = 0,
        learned_observations: int = 0,
        learned_yield: float = 0.0,
        learned_tier_hits: str = "-"
    ) -> None:

        if not self.first_render:

            sys.stdout.write(
                MOVE_UP *
                self.total_lines
            )

        else:

            print(
                "\n" *
                (self.total_lines - 1)
            )

            sys.stdout.write(
                MOVE_UP *
                (self.total_lines - 1)
            )

            self.first_render = False

        for i in range(
            self.log_size
        ):

            sys.stdout.write(
                CLEAR_LINE
            )

            if i < len(
                self.logs
            ):

                print(
                    self.logs[i]
                )

            else:

                print()

        seed_text = (
            f"p = {seed_p:,}"
            if seed_p is not None
            else
            "-"
        )

        q_text = (
            f"q = {current_q:,}"
            if current_q is not None
            else
            "-"
        )

        candidate_text = (
            f"n = {current_candidate:,}"
            if current_candidate is not None
            else
            "-"
        )

        progress_text = (
            self._percent(
                seed_p,
                max_p
            )
            if seed_p is not None
            else
            "0.000%"
        )

        width = 83

        print(
            "╔" +
            "═" * width +
            "╗"
        )

        print(
            f"║ {CYAN}"
            f"{self.title_text:^{width - 2}}"
            f"{RESET} ║"
        )

        print(
            "╠" +
            "═" * width +
            "╣"
        )

        def row(
            label: str,
            value: str,
            color: str = ""
        ):

            content = (
                f"{label:<34}"
                f"{value:>47}"
            )

            print(
                f"║ {color}{content}{RESET} ║"
            )

        row(
            "Elapsed Runtime",
            f"{elapsed:,.3f} s"
        )

        row(
            "Search Phase",
            phase,
            YELLOW
        )

        row(
            "Factor Strategy",
            strat_text,
            CYAN
        )

        row(
            "Prime Seed",
            seed_text
        )

        row(
            "q",
            q_text
        )

        row(
            "Candidate n",
            candidate_text
        )

        row(
            "p Search Progress",
            f"{progress_text} / max p = {max_p:,}"
        )

        row(
            "Candidate Pairs Tested",
            f"{pairs:,} "
            f"({self._rate(pairs, elapsed)})"
        )

        row(
            "q Modular-Sieve Rejects",
            f"{q_screen_rejected:,}"
        )

        row(
            "q Primality Tests",
            f"{q_tested:,}"
        )

        row(
            "q Rejected",
            f"{q_rejected:,}"
        )

        row(
            "Mod-5 Rejected",
            f"{residue_rejected:,}"
        )

        row(
            "Factor-Reduced Fermat Rejects",
            f"{fermat_rejected:,}"
        )

        row(
            "Quadratic Closure Attempts",
            f"{quadratic_attempts:,}"
        )

        row(
            "Quadratic Closure Survivors",
            f"{quadratic_survivors:,}",
            GREEN
            if quadratic_survivors
            else
            ""
        )

        row(
            "Quadratic Closure Rejections",
            f"{quadratic_rejected:,}"
        )

        row(
            "Cubic Polynomial Attempts",
            f"{poly1_attempts:,}"
        )

        row(
            "Cubic Survivors",
            f"{cubic_survivors:,}",
            GREEN
            if cubic_survivors
            else
            ""
        )

        row(
            "Cubic Rejections",
            f"{poly1_rejected:,}"
        )

        row(
            "Poly-2 Attempts",
            f"{poly2_attempts:,}"
        )

        row(
            "Poly-2 Passes",
            f"{poly2_passed:,}"
        )

        row(
            "Poly-2 Failures",
            f"{poly2_failures:,}"
        )

        row(
            "Poly-2 Pass Rate",
            f"{poly2_rate * 100.0:,.3f}%"
        )

        row(
            "Poly-2 Saved",
            f"{poly2_saved:,}"
        )

        row(
            "Poly-2 State",
            poly2_status,
            RED
            if "SUSPENDED" in poly2_status
            else
            GREEN
        )

        row(
            "Learned Accelerator",
            learned_status,
            MAGENTA
            if "SKIPPING" in learned_status
            else
            CYAN
        )

        row(
            "Learned Spiral Cycle / Fraction",
            f"{learned_cycle_index} / {learned_fraction * 100:.1f}%"
        )

        row(
            "Learned Last Gap / Skip Size",
            f"{learned_last_gap:,} / {learned_last_skip_size:,}"
        )

        row(
            "Learned Arm Events",
            f"{learned_arm_events:,}"
        )

        row(
            "Learned Candidates Skipped",
            f"{learned_total_skipped:,}"
        )

        row(
            "Learned Tier Hits (Poly2/$620)",
            learned_tier_hits
        )

        row(
            "Learned Observations",
            f"{learned_observations:,}"
        )

        row(
            "Learned Cubic Yield",
            f"{learned_yield * 100.0:,.3f}%"
        )

        row(
            "Validated $620 Hits",
            f"{hits:,}",
            GREEN
            if hits
            else
            ""
        )

        print(
            "╚" +
            "═" * width +
            "╝"
        )

        sys.stdout.flush()


# =============================================================================
# $620 REPORT
# =============================================================================

def print_620_report_to_string(
    n: int,
    poly2_state: str,
    silverware: Dict[str, Any],
    witness: Optional[int] = None
) -> str:

    if witness is None:
        witness = factor_small(
            n
        )

    if (
        witness
        and
        not silverware["prime"]
    ):

        witness_str = (
            f" [{witness}x"
            f"{n // witness}]"
        )

    else:

        witness_str = ""

    status = (
        f"{GREEN}WINNER{RESET}"
        if silverware["620_candidate"]
        else
        "REJECTED"
    )

    return (
        f"[Hit] n={n:,} | "
        f"P2={poly2_state} | "
        f"V={silverware['lucas_residue']} | "
        f"Status: {status}"
        f"{witness_str}"
    )



# =============================================================================
# QUADRATIC FIBONACCI/LUCAS CLOSURE
# =============================================================================

def quadratic_closure_audit(
    n: int
) -> Dict[str, Any]:
    """
    Exact v25 quadratic closure.

    Axis A: L_n == 1 (mod n)
    Axis B: F_n follows the discriminant-5 Frobenius branch
    Axis C: A^n matches the corresponding full 2x2 Frobenius matrix

    Axis C is retained as a structural audit. For odd n it is algebraically
    determined by Axes A and B, so it is not counted as an independent test.
    """

    result: Dict[str, Any] = {
        "candidate": n,
        "n_mod_5": n % 5,
        "fibonacci": None,
        "lucas": None,
        "axis_a": False,
        "axis_b": False,
        "axis_c": False,
        "matrix": None,
        "expected_matrix": None,
        "passed": False,
        "reason": ""
    }

    if n < 2:
        result["reason"] = "n<2"
        return result

    f_n, f_np1 = fibonacci_pair_mod_iterative(n, n)
    lucas_n = (2 * f_np1 - f_n) % n
    f_nm1 = (f_np1 - f_n) % n

    result["fibonacci"] = f_n
    result["lucas"] = lucas_n

    axis_a = (
        lucas_n == 1 % n
    )
    result["axis_a"] = axis_a

    mod5 = n % 5

    if n == 5:
        expected_f = 0
    elif mod5 in (1, 4):
        expected_f = 1 % n
    elif mod5 in (2, 3):
        expected_f = (-1) % n
    else:
        expected_f = None

    axis_b = (
        expected_f is not None
        and
        f_n == expected_f
    )
    result["axis_b"] = axis_b

    actual_matrix = (
        (f_np1, f_n),
        (f_n, f_nm1)
    )

    if n == 5:
        expected_matrix = (
            (3 % n, 0),
            (0, 3 % n)
        )
    elif mod5 in (1, 4):
        expected_matrix = (
            (1 % n, 1 % n),
            (1 % n, 0)
        )
    elif mod5 in (2, 3):
        expected_matrix = (
            (0, (-1) % n),
            ((-1) % n, 1 % n)
        )
    else:
        expected_matrix = None

    axis_c = (
        expected_matrix is not None
        and
        actual_matrix == expected_matrix
    )

    result["matrix"] = actual_matrix
    result["expected_matrix"] = expected_matrix
    result["axis_c"] = axis_c
    result["passed"] = axis_a and axis_b and axis_c

    if result["passed"]:
        result["reason"] = "A+B+C"
    elif not axis_a:
        result["reason"] = "AXIS_A"
    elif not axis_b:
        result["reason"] = "AXIS_B"
    else:
        result["reason"] = "AXIS_C"

    return result


def quadratic_closure_gate(
    n: int
) -> bool:
    return bool(
        quadratic_closure_audit(n)["passed"]
    )


# =============================================================================
# EXPLICIT INSPECTION
# =============================================================================

def inspect_candidates(
    values: List[int]
) -> None:

    for n in values:

        print(
            "\n" +
            "=" * 79
        )

        print(
            f"UNIFIED INTERPRETIVE LOG TRACE: {n}"
        )

        print(
            "=" * 79
        )

        six20 = verify_620(
            n
        )

        auditor = FrobeniusAuditor(
            n,
            [-1, -1, -1, 1]
        )

        audit_res = (
            auditor.execute_audit()
        )

        print(
            "Primality Classification   : "
            f"{'PRIME' if six20['prime'] else 'COMPOSITE'}"
        )

        print(
            "Modulus Congruence (n%5)   : "
            f"{six20['n_mod_5']} "
            "(Target is 2 or 3)"
        )

        print(
            "±2 mod 5 Boundary Status   : "
            f"{'PASS' if six20['residue_ok'] else 'FAIL'}"
        )

        print(
            "2^(n-1) Modulo Remainder   : "
            f"{six20['base2_residue']}"
        )

        print(
            "Base-2 Fermat Test Result  : "
            f"{'PASS' if six20['base2_ok'] else 'FAIL'}"
        )

        print(
            "F_(n+1) Modulo Remainder   : "
            f"{six20['fibonacci_residue']}"
        )

        print(
            "V_(n+1) Lucas Remainder    : "
            f"{six20['lucas_residue']}"
        )

        print(
            "*** $620 STATUS             : "
            f"{'[!!!] WINNING CANDIDATE' if six20['620_candidate'] else 'REJECTED'}"
        )

        print(
            "\nQUADRATIC FIBONACCI/LUCAS CLOSURE"
        )

        print(
            "-" * 31
        )

        quadratic = quadratic_closure_audit(n)

        print(
            "Axis A: L_n ≡ 1 (mod n) : "
            f"{'PASS' if quadratic['axis_a'] else 'FAIL'}"
        )

        print(
            "Axis B: F_n branch       : "
            f"{'PASS' if quadratic['axis_b'] else 'FAIL'}"
        )

        print(
            "Axis C: A^n matrix       : "
            f"{'PASS' if quadratic['axis_c'] else 'FAIL'}"
        )

        print(
            "F_n modulo n              : "
            f"{quadratic['fibonacci']}"
        )

        print(
            "L_n modulo n              : "
            f"{quadratic['lucas']}"
        )

        print(
            "Quadratic closure status  : "
            f"{'PASSED' if quadratic['passed'] else 'REJECTED'}"
        )

        print(
            "\nGRANTHAM EXTENSION LAYER AUDIT"
        )

        print(
            "-" * 31
        )

        print(
            "Stage 1 Core Preamble       : "
            f"{'PASSED' if audit_res['preamble_passed'] else 'FAILED'}"
        )

        print(
            "Stage 2 Structural Splitting: "
            f"{'PASSED' if audit_res['factorization_passed'] else 'FAILED'}"
        )

        print(
            "Stage 3 Frobenius Mapping  : "
            f"{'PASSED' if audit_res['frobenius_passed'] else 'FAILED'}"
        )

        if audit_res[
            "composite_factor_found"
        ]:

            print(
                "Factor exposed by collapse : "
                f"{audit_res['composite_factor_found']}"
            )

        if audit_res[
            "stage_failures"
        ]:

            print(
                "Audit diagnostics:"
            )

            for failure in audit_res[
                "stage_failures"
            ]:

                print(
                    f"  - {failure}"
                )


# =============================================================================
# CORE SHORTCUT SEARCH
# =============================================================================

def _learned_tier_hits_text(
    learned: "GapSpiralController"
) -> str:

    if not learned.tier_hit_counts:
        return "-"

    parts = [
        f"{tier}={count}"
        for tier, count in sorted(
            learned.tier_hit_counts.items()
        )
    ]

    return ", ".join(parts)


def search_shortcut_space(
    limit_upper: int,
    ratio_strat: str = "3p-2",
    learned_mode: bool = False
) -> List[int]:

    valid_strategies = {
        "3p-2",
        "2p+1",
        "7p-6"
    }

    if ratio_strat not in valid_strategies:

        raise ValueError(
            "Unknown ratio strategy. "
            "Use 3p-2, 2p+1, or 7p-6."
        )

    max_p = max_p_for_strategy(
        limit_upper,
        ratio_strat
    )

    logger = LearningLogger()

    poly2 = Poly2Learner(
        logger
    )

    learned = GapSpiralController(
        logger,
        max_p
    )

    title = (
        "GAP-SPIRAL "
        "SHORTCUT PIPELINE"
        if learned_mode
        else
        "EXACT MATHEMATICAL SHORTCUT PIPELINE"
    )

    print()

    print(
        f"{CYAN}Learning log:{RESET} "
        f"{logger.path}"
    )

    if learned_mode:

        print(
            f"{YELLOW}"
            "WARNING: LEARNED MODE IS HEURISTIC. "
            "It may skip a mathematically valid candidate."
            f"{RESET}"
        )

        print(
            f"{YELLOW}"
            "The first gap between two Tier-0 hits is used immediately, "
            "at full distance. Each subsequent gap is used at a fraction "
            "that contracts by 1/phi per cycle, floored at 1/phi^2."
            f"{RESET}"
        )

        print(
            f"{YELLOW}"
            "phi = "
            f"{GapSpiralController.PHI:.6f}; "
            "floor cycle = "
            f"{GapSpiralController.SPIRAL_FLOOR_CYCLE} "
            f"(floor fraction = {GapSpiralController.PHI ** -GapSpiralController.SPIRAL_FLOOR_CYCLE * 100:.1f}%); "
            "tier-hit cooldown = "
            f"{GapSpiralController.TIER_HIT_COOLDOWN_HITS} hits."
            f"{RESET}"
        )

    print()

    ui = TerminalDashboard(
        title,
        log_window_size=SHORTCUT_LOG_LINES
    )

    t0 = time.monotonic()

    checked_pairs = 0

    q_tested = 0
    q_rejected = 0
    q_screen_rejected = 0

    residue_rejected = 0
    fermat_rejected = 0

    quadratic_attempts = 0
    quadratic_survivors = 0
    quadratic_rejected = 0

    poly1_attempts = 0
    poly1_survivors = 0
    poly1_rejected = 0

    learned_skipped = 0

    true_620_hits: List[int] = []

    exact_classes = candidate_mod5_classes(
        ratio_strat
    )

    if exact_classes:

        if len(exact_classes) == 1:

            sieve_status_str = (
                "EXACT "
                f"[p ≡ {exact_classes[0]} mod 5]"
            )

        else:

            sieve_status_str = (
                "EXACT "
                f"[p mod 5 ∈ {exact_classes}]"
            )

    else:

        sieve_status_str = (
            "EXACT [NO p>5 CLASS]"
        )

    current_p = 0
    current_q: Optional[int] = None
    current_candidate: Optional[int] = None

    last_display = 0.0

    def dashboard_learned_kwargs() -> Dict[str, Any]:

        return {
            "learned_status": (
                learned.status_text()
                if learned_mode
                else
                "OFF"
            ),
            "learned_cycle_index": learned.cycle_index,
            "learned_fraction": learned.current_fraction,
            "learned_last_gap": learned.last_gap,
            "learned_last_skip_size": learned.last_skip_size,
            "learned_total_skipped": learned.total_skipped,
            "learned_arm_events": learned.arm_events,
            "learned_observations": learned.total_observations,
            "learned_yield": learned.global_yield,
            "learned_tier_hits": _learned_tier_hits_text(learned)
        }

    ui.add_log(
        f"[Init] Limit = {limit_upper:,}"
    )

    ui.add_log(
        f"[Init] Ratio = {ratio_strat}"
    )

    ui.add_log(
        f"[Init] Max p = {max_p:,}"
    )

    ui.add_log(
        f"[Init] Poly-2 = {poly2.status_text()}"
    )

    if learned_mode:

        ui.add_log(
            "[Init] Learned accelerator = ENABLED (v6 gap-spiral)"
        )

        ui.add_log(
            f"[Init] Recovered "
            f"{learned.total_observations:,} observations, "
            f"cycle_index={learned.cycle_index}, "
            f"last_hit_p={learned.last_hit_p}"
        )

    else:

        ui.add_log(
            "[Init] Learned accelerator = DISABLED"
        )

    ui.refresh(
        0.0,
        checked_pairs,
        poly1_survivors,
        poly2.status_text(),
        sieve_status_str,
        0,
        current_p,
        ratio_strat,
        max_p,
        phase="INITIALIZING",
        poly2_attempts=poly2.attempts,
        poly2_passed=poly2.passes,
        poly2_saved=poly2.saved,
        poly2_failures=poly2.failures,
        poly2_rate=poly2.pass_rate,
        **dashboard_learned_kwargs()
    )

    last_display = time.monotonic()

    if strategy_is_mod5_impossible(
        ratio_strat
    ):

        ui.add_log(
            f"{YELLOW}"
            f"[Exact Skip] "
            f"{ratio_strat} has no valid p mod 5 class."
            f"{RESET}"
        )

        elapsed = (
            time.monotonic() -
            t0
        )

        ui.refresh(
            elapsed,
            0,
            0,
            poly2.status_text(),
            sieve_status_str,
            0,
            5,
            ratio_strat,
            max_p,
            phase="EXACTLY EMPTY",
            **dashboard_learned_kwargs()
        )

        logger.close()

        print()
        print(
            "SHORTCUT SEARCH COMPLETE"
        )
        print(
            f"Strategy                 : {ratio_strat}"
        )
        print(
            "Mathematical candidate space: EMPTY"
        )

        return []

    a, b = factor_form_coefficients(
        ratio_strat
    )

    prime_stream = prime_yield_generator(
        11904045228711,
        max_p
    )

    try:

        for p in prime_stream:

            current_p = p

            if p == 3:
                continue

            # -----------------------------------------------------------------
            # EXACT mathematical residue sieve
            # -----------------------------------------------------------------

            if (
                p > 5
                and
                p % 5 not in exact_classes
            ):
                continue

            # -----------------------------------------------------------------
            # LEARNED GAP-SPIRAL ACCELERATOR
            #
            # decide_skip() just checks whether p falls inside the
            # currently active skip range (armed from the most recent
            # observed hit-to-hit gap). A False return means this
            # candidate proceeds to the real Tier-0 test below exactly as
            # if no skip policy existed -- which is also how new gaps get
            # observed in the first place.
            # -----------------------------------------------------------------

            if learned_mode:

                skip, reason = learned.decide_skip(
                    p
                )

                if skip:

                    learned_skipped += 1

                    continue

            # -----------------------------------------------------------------
            # Exact factor pair
            # -----------------------------------------------------------------

            q = (
                a * p + b
            )

            current_q = q

            candidate = (
                p * q
            )

            current_candidate = candidate

            if candidate >= limit_upper:
                break

            checked_pairs += 1

            now = time.monotonic()

            if (
                now - last_display >=
                DISPLAY_INTERVAL
            ):

                ui.refresh(
                    now - t0,
                    checked_pairs,
                    poly1_survivors,
                    poly2.status_text(),
                    sieve_status_str,
                    len(true_620_hits),
                    p,
                    ratio_strat,
                    max_p,
                    current_q=q,
                    current_candidate=candidate,
                    phase="TESTING q",
                    q_tested=q_tested,
                    q_rejected=q_rejected,
                    q_screen_rejected=q_screen_rejected,
                    residue_rejected=residue_rejected,
                    fermat_rejected=fermat_rejected,
                    quadratic_attempts=quadratic_attempts,
                    quadratic_survivors=quadratic_survivors,
                    quadratic_rejected=quadratic_rejected,
                    poly1_attempts=poly1_attempts,
                    poly1_rejected=poly1_rejected,
                    poly2_attempts=poly2.attempts,
                    poly2_passed=poly2.passes,
                    poly2_saved=poly2.saved,
                    poly2_failures=poly2.failures,
                    poly2_rate=poly2.pass_rate,
                    **dashboard_learned_kwargs()
                )

                last_display = now

            # -----------------------------------------------------------------
            # q modular sieve
            # -----------------------------------------------------------------

            if not q_small_prime_screen(
                p,
                q
            ):

                q_screen_rejected += 1

                continue

            # -----------------------------------------------------------------
            # q primality
            # -----------------------------------------------------------------

            q_tested += 1

            if not is_prime_fast(
                q
            ):

                q_rejected += 1

                continue

            # -----------------------------------------------------------------
            # Candidate mod 5
            # -----------------------------------------------------------------

            if candidate % 5 not in (
                2,
                3
            ):

                residue_rejected += 1

                continue

            # -----------------------------------------------------------------
            # Fermat modulo p
            # -----------------------------------------------------------------

            phase = "FERMAT p"

            exponent_p = (
                candidate - 1
            ) % (
                p - 1
            )

            if pow(
                2,
                exponent_p,
                p
            ) != 1:

                fermat_rejected += 1

                continue

            # -----------------------------------------------------------------
            # Fermat modulo q
            # -----------------------------------------------------------------

            phase = "FERMAT q"

            exponent_q = (
                candidate - 1
            ) % (
                q - 1
            )

            if pow(
                2,
                exponent_q,
                q
            ) != 1:

                fermat_rejected += 1

                continue

            # -----------------------------------------------------------------
            # Quadratic Fibonacci/Lucas closure
            # -----------------------------------------------------------------

            phase = "QUADRATIC CLOSURE"

            quadratic_attempts += 1

            quadratic = quadratic_closure_audit(
                candidate
            )

            if not quadratic["passed"]:

                quadratic_rejected += 1

                continue

            quadratic_survivors += 1

            ui.add_log(
                f"[Quadratic Survivor] "
                f"n={candidate:,} "
                f"F={quadratic['fibonacci']} "
                f"L={quadratic['lucas']}"
            )

            # -----------------------------------------------------------------
            # Cubic Frobenius
            #
            # THIS is the statistical observation point.
            # -----------------------------------------------------------------

            phase = "CUBIC FROBENIUS"

            poly1_attempts += 1

            audit_tribonacci = FrobeniusAuditor(
                candidate,
                [-1, -1, -1, 1]
            ).execute_audit()

            cubic_passed = bool(
                audit_tribonacci[
                    "frobenius_passed"
                ]
            )

            if learned_mode:

                arm_events_before = learned.arm_events

                learned.observe(
                    p,
                    cubic_passed
                )

                if learned.arm_events > arm_events_before:

                    ui.add_log(
                        f"{MAGENTA}"
                        f"[Gap Arm] "
                        f"gap={learned.last_gap:,} "
                        f"fraction={learned.last_fraction * 100:.1f}% "
                        f"skip={learned.last_skip_size:,} "
                        f"cycle={learned.cycle_index}"
                        f"{RESET}"
                    )

            if not cubic_passed:

                poly1_rejected += 1

                continue

            poly1_survivors += 1

            ui.add_log(
                f"[Cubic Survivor] "
                f"n={candidate:,} "
                f"p={p:,} "
                f"q={q:,}"
            )

            # -----------------------------------------------------------------
            # Poly-2 learning
            # -----------------------------------------------------------------

            poly2_passed = False
            poly2_state_flag = "PRUNED"

            if poly2.suspended:

                if poly2.should_probe():

                    poly2.begin_probe()

                    ui.add_log(
                        f"{MAGENTA}"
                        f"[Poly-2 REPROBE] "
                        f"n={candidate:,}"
                        f"{RESET}"
                    )

                    phase = "POLY-2 REPROBE"

                    (
                        poly2_passed,
                        poly2_state_flag
                    ) = poly2.attempt(
                        candidate,
                        p,
                        q,
                        force_probe=True
                    )

                else:

                    poly2.save_one(
                        candidate,
                        p,
                        q
                    )

                    poly2_state_flag = "PRUNED"

            else:

                phase = "POLY-2"

                (
                    poly2_passed,
                    poly2_state_flag
                ) = poly2.attempt(
                    candidate,
                    p,
                    q
                )

            if learned_mode and poly2_passed:

                learned.record_tier_hit(
                    p,
                    "POLY2"
                )

            # -----------------------------------------------------------------
            # Authoritative $620 verification
            # -----------------------------------------------------------------

            phase = "$620 VERIFICATION"

            six20 = verify_620(
                candidate
            )

            log_line = print_620_report_to_string(
                candidate,
                poly2_state_flag,
                six20,
                witness=p
            )

            ui.add_log(
                log_line
            )

            if six20[
                "620_candidate"
            ]:

                true_620_hits.append(
                    candidate
                )

                logger.write(
                    "$620 WINNER",
                    n=candidate,
                    p=p,
                    q=q,
                    attempt=poly2.attempts,
                    passes=poly2.passes,
                    failures=poly2.failures,
                    saved=poly2.saved,
                    reason="VALIDATED"
                )

                if learned_mode:

                    learned.record_tier_hit(
                        p,
                        "$620"
                    )

                ui.add_log(
                    f"{GREEN}"
                    f"[!!! $620 WINNER !!!] "
                    f"n={candidate:,} "
                    f"= {p:,} × {q:,}"
                    f"{RESET}"
                )

            now = time.monotonic()

            ui.refresh(
                now - t0,
                checked_pairs,
                poly1_survivors,
                poly2.status_text(),
                sieve_status_str,
                len(true_620_hits),
                p,
                ratio_strat,
                max_p,
                current_q=q,
                current_candidate=candidate,
                phase="SEARCHING",
                q_tested=q_tested,
                q_rejected=q_rejected,
                q_screen_rejected=q_screen_rejected,
                residue_rejected=residue_rejected,
                fermat_rejected=fermat_rejected,
                quadratic_attempts=quadratic_attempts,
                quadratic_survivors=quadratic_survivors,
                quadratic_rejected=quadratic_rejected,
                poly1_attempts=poly1_attempts,
                poly1_rejected=poly1_rejected,
                poly2_attempts=poly2.attempts,
                poly2_passed=poly2.passes,
                poly2_saved=poly2.saved,
                poly2_failures=poly2.failures,
                poly2_rate=poly2.pass_rate,
                **dashboard_learned_kwargs()
            )

            last_display = now

    finally:

        if learned_mode:
            learned.checkpoint()

        logger.close()

    elapsed = (
        time.monotonic() -
        t0
    )

    ui.add_log(
        f"[Complete] "
        f"p explored through {current_p:,}"
    )

    ui.add_log(
        f"[Complete] "
        f"Elapsed {elapsed:,.3f} s"
    )

    ui.add_log(
        f"[Complete] "
        f"Validated winners = "
        f"{len(true_620_hits):,}"
    )

    ui.refresh(
        elapsed,
        checked_pairs,
        poly1_survivors,
        poly2.status_text(),
        sieve_status_str,
        len(true_620_hits),
        current_p,
        ratio_strat,
        max_p,
        current_q=current_q,
        current_candidate=current_candidate,
        phase="COMPLETE",
        q_tested=q_tested,
        q_rejected=q_rejected,
        q_screen_rejected=q_screen_rejected,
        residue_rejected=residue_rejected,
        fermat_rejected=fermat_rejected,
        poly1_attempts=poly1_attempts,
        poly1_rejected=poly1_rejected,
        poly2_attempts=poly2.attempts,
        poly2_passed=poly2.passes,
        poly2_saved=poly2.saved,
        poly2_failures=poly2.failures,
        poly2_rate=poly2.pass_rate,
        **dashboard_learned_kwargs()
    )

    print()

    print(
        f"{CYAN}"
        "SHORTCUT SEARCH COMPLETE"
        f"{RESET}"
    )

    print(
        f"Mode                     : "
        f"{'HEURISTIC LEARNED (v6, gap-spiral)' if learned_mode else 'EXHAUSTIVE'}"
    )

    print(
        f"Strategy                 : "
        f"{ratio_strat}"
    )

    print(
        f"Limit                    : "
        f"{limit_upper:,}"
    )

    print(
        f"Maximum p                : "
        f"{max_p:,}"
    )

    print(
        f"Last p                   : "
        f"{current_p:,}"
    )

    print(
        f"Candidate pairs           : "
        f"{checked_pairs:,}"
    )

    print(
        f"q modular rejects         : "
        f"{q_screen_rejected:,}"
    )

    print(
        f"q primality tests        : "
        f"{q_tested:,}"
    )

    print(
        f"q rejected               : "
        f"{q_rejected:,}"
    )

    print(
        f"Mod-5 rejected           : "
        f"{residue_rejected:,}"
    )

    print(
        f"Fermat rejected           : "
        f"{fermat_rejected:,}"
    )

    print(
        f"Quadratic closure attempts : "
        f"{quadratic_attempts:,}"
    )

    print(
        f"Quadratic closure survivors: "
        f"{quadratic_survivors:,}"
    )

    print(
        f"Quadratic closure rejected : "
        f"{quadratic_rejected:,}"
    )

    print(
        f"Cubic attempts           : "
        f"{poly1_attempts:,}"
    )

    print(
        f"Cubic survivors          : "
        f"{poly1_survivors:,}"
    )

    print(
        f"Poly-2 attempts          : "
        f"{poly2.attempts:,}"
    )

    print(
        f"Poly-2 passes            : "
        f"{poly2.passes:,}"
    )

    print(
        f"Poly-2 failures          : "
        f"{poly2.failures:,}"
    )

    print(
        f"Poly-2 saved evaluations : "
        f"{poly2.saved:,}"
    )

    print(
        f"Poly-2 state             : "
        f"{poly2.status_text()}"
    )

    if learned_mode:

        ls = learned.summary()

        print(
            f"Learned arm events       : "
            f"{ls['arm_events']:,}"
        )

        print(
            f"Learned candidates skipped: "
            f"{ls['total_skipped']:,}"
        )

        print(
            f"Learned spiral cycle      : "
            f"{ls['cycle_index']}"
        )

        print(
            f"Learned current fraction  : "
            f"{ls['current_fraction'] * 100.0:.1f}%"
        )

        print(
            f"Learned last gap / skip   : "
            f"{ls['last_gap']:,} / {ls['last_skip_size']:,}"
        )

        print(
            f"Learned observations     : "
            f"{ls['total_observations']:,}"
        )

        print(
            f"Learned useful           : "
            f"{ls['total_useful']:,}"
        )

        print(
            f"Learned cubic yield      : "
            f"{ls['global_yield'] * 100.0:,.3f}%"
        )

        print(
            f"Tier hits                : "
            f"{ls['tier_hits'] if ls['tier_hits'] else '-'}"
        )

    print(
        f"Validated $620 winners   : "
        f"{len(true_620_hits):,}"
    )

    print(
        f"Learning log             : "
        f"{logger.path}"
    )

    if true_620_hits:

        print()

        print(
            f"{GREEN}"
            "WINNERS"
            f"{RESET}"
        )

        for n in true_620_hits:

            print(
                f"  {n:,}"
            )

    else:

        print()

        print(
            "No validated $620 candidates found."
        )

    return true_620_hits


# =============================================================================
# LINEAR SEARCH
# =============================================================================

def search_620(
    start: int,
    limit: int,
    cubic_only: bool = False
) -> List[int]:

    start = max(
        5,
        start
    )

    if start % 2 == 0:
        start += 1

    checked = 0

    base2_survivors = 0
    fibonacci_survivors = 0
    cubic_survivors = 0

    winners: List[int] = []

    t0 = time.monotonic()

    ui = TerminalDashboard(
        "LINEAR COEFFICIENT SEARCH ENGINE",
        log_window_size=LINEAR_LOG_LINES
    )

    last_display = 0.0

    for n in range(
        start,
        limit,
        2
    ):

        if n % 3 == 0:
            continue

        checked += 1

        if cubic_only:

            if is_prime_fast(
                n
            ):
                continue

            audit = FrobeniusAuditor(
                n,
                [-1, -1, -1, 1]
            ).execute_audit()

            if not audit[
                "frobenius_passed"
            ]:
                continue

            cubic_survivors += 1

            six20 = verify_620(
                n
            )

            if (
                six20["residue_ok"]
                and
                six20["base2_ok"]
            ):
                base2_survivors += 1

            if six20[
                "620_candidate"
            ]:

                winners.append(
                    n
                )

                ui.add_log(
                    f"[Cubic $620 Hit] "
                    f"Candidate: {n:,}"
                )

        else:

            if n % 5 not in (
                2,
                3
            ):
                continue

            if pow(
                2,
                n - 1,
                n
            ) != 1:
                continue

            base2_survivors += 1

            if (
                fibonacci_pair_mod_iterative(
                    n + 1,
                    n
                )[0] != 0
            ):
                continue

            fibonacci_survivors += 1

            if is_prime_fast(
                n
            ):
                continue

            winners.append(
                n
            )

            six20 = verify_620(
                n
            )

            audit = FrobeniusAuditor(
                n,
                [-1, -1, -1, 1]
            ).execute_audit()

            if audit[
                "frobenius_passed"
            ]:
                cubic_survivors += 1

            ui.add_log(
                f"[$620 Hit] "
                f"Candidate Found: {n:,}"
            )

        now = time.monotonic()

        if (
            checked % 1000 == 0
            or
            now - last_display >=
            DISPLAY_INTERVAL
        ):

            ui.refresh(
                now - t0,
                checked,
                cubic_survivors,
                "N/A",
                "LINEAR",
                len(winners),
                n,
                "LINEAR",
                max(
                    start,
                    limit
                ),
                current_candidate=n,
                phase=(
                    "CUBIC SEARCH"
                    if cubic_only
                    else
                    "620 SEARCH"
                )
            )

            last_display = now

    elapsed = (
        time.monotonic() -
        t0
    )

    ui.add_log(
        f"[Complete] "
        f"Elapsed {elapsed:,.3f} s"
    )

    ui.refresh(
        elapsed,
        checked,
        cubic_survivors,
        "N/A",
        "LINEAR",
        len(winners),
        limit,
        "LINEAR",
        max(
            start,
            limit
        ),
        current_candidate=limit,
        phase="COMPLETE"
    )

    return winners


# =============================================================================
# COMMAND LINE
# =============================================================================

def unified_main() -> None:

    args = sys.argv[1:]

    if not args:

        inspect_candidates(
            [2487941]
        )

        return

    # -------------------------------------------------------------------------
    # HEURISTIC LEARNED SHORTCUT SEARCH
    # -------------------------------------------------------------------------

    if args[0] == "--learned-shortcut-search":

        if (
            len(args) < 2
            or
            len(args) > 3
        ):

            print(
                "Usage: "
                "python script.py "
                "--learned-shortcut-search "
                "LIMIT_UPPER [RATIO_STRAT]"
            )

            print(
                "Ratio Strategies:"
            )

            print(
                "  3p-2"
            )

            print(
                "  2p+1"
            )

            print(
                "  7p-6"
            )

            sys.exit(2)

        try:

            limit_upper = int(
                args[1]
            )

        except ValueError:

            print(
                "LIMIT_UPPER must be an integer.",
                file=sys.stderr
            )

            sys.exit(2)

        strat = (
            args[2]
            if len(args) == 3
            else
            "3p-2"
        )

        try:

            search_shortcut_space(
                limit_upper,
                strat,
                learned_mode=True
            )

        except ValueError as exc:

            print(
                f"Error: {exc}",
                file=sys.stderr
            )

            sys.exit(2)

        return

    # -------------------------------------------------------------------------
    # EXACT SHORTCUT SEARCH
    # -------------------------------------------------------------------------

    if args[0] == "--shortcut-search":

        if (
            len(args) < 2
            or
            len(args) > 3
        ):

            print(
                "Usage: "
                "python script.py "
                "--shortcut-search "
                "LIMIT_UPPER [RATIO_STRAT]"
            )

            print(
                "Ratio Strategies:"
            )

            print(
                "  3p-2"
            )

            print(
                "  2p+1"
            )

            print(
                "  7p-6"
            )

            sys.exit(2)

        try:

            limit_upper = int(
                args[1]
            )

        except ValueError:

            print(
                "LIMIT_UPPER must be an integer.",
                file=sys.stderr
            )

            sys.exit(2)

        strat = (
            args[2]
            if len(args) == 3
            else
            "3p-2"
        )

        try:

            search_shortcut_space(
                limit_upper,
                strat,
                learned_mode=False
            )

        except ValueError as exc:

            print(
                f"Error: {exc}",
                file=sys.stderr
            )

            sys.exit(2)

        return

    # -------------------------------------------------------------------------
    # LINEAR SEARCH
    # -------------------------------------------------------------------------

    if args[0] == "--search":

        if len(args) != 3:

            print(
                "Usage: "
                "python script.py --search START LIMIT"
            )

            sys.exit(2)

        try:

            start = int(
                args[1]
            )

            limit = int(
                args[2]
            )

        except ValueError:

            print(
                "START and LIMIT must be integers.",
                file=sys.stderr
            )

            sys.exit(2)

        search_620(
            start,
            limit,
            cubic_only=False
        )

        return

    # -------------------------------------------------------------------------
    # CUBIC SEARCH
    # -------------------------------------------------------------------------

    if args[0] == "--cubic-search":

        if len(args) != 3:

            print(
                "Usage: "
                "python script.py --cubic-search START LIMIT"
            )

            sys.exit(2)

        try:

            start = int(
                args[1]
            )

            limit = int(
                args[2]
            )

        except ValueError:

            print(
                "START and LIMIT must be integers.",
                file=sys.stderr
            )

            sys.exit(2)

        search_620(
            start,
            limit,
            cubic_only=True
        )

        return

    # -------------------------------------------------------------------------
    # EXPLICIT CANDIDATES
    # -------------------------------------------------------------------------

    try:

        values = [
            int(x)
            for x in args
        ]

    except ValueError as exc:

        print(
            f"Invalid integer argument: {exc}",
            file=sys.stderr
        )

        sys.exit(2)

    inspect_candidates(
        values
    )


# =============================================================================
# APPLICATION ENTRY
# =============================================================================

if __name__ == "__main__":

    unified_main()