# -*- coding: utf-8 -*-
"""anu_v3.executor_callback_contract — ANU-side mandatory callback doctrine.

task-2553+32 — restores the executor completion callback mandatory rule on the
ANU side as executable code (§3 lifecycle, §4.2/§4.6/§4.7/§4.8/§4.9, §6.13/14).

Standalone, zero-mutation: imports/edits ZERO tracked module. anu_v3.runtime_
reconcile_checkpoint (+31) is NOT mutated — see the additive sidecar
anu_v3.runtime_reconcile_checkpoint_recovery_layer (§5 additive-only).

NO-CRON note (9-R.1): zero cron register/remove here. This is a doctrine
contract object. +9a/+23/+25 system-sanctioned fallback cancel-on-success is a
separate designed lifecycle transition this module only *asserts is preserved*
(execute 0).
"""
from __future__ import annotations

from dataclasses import dataclass
from typing import List

DOCTRINE_SCHEMA = "anu_v3.executor_callback_contract.v1"

# Authoritative corrected lifecycle (§3, 회장 verbatim 1~7).
LIFECYCLE_NORMAL_STRUCTURE = (
    "1. ANU 가 봇에 위임",
    "2. 봇이 작업 수행",
    "3. 봇은 완료 직후 ANU 에 normal completion callback cron 발사 (MANDATORY)",
    "4. ANU collector 가 결과 회수·검증·Codex audit·ANU-Codex adjudication·"
    "loop/next action 판단",
    "5. fallback/dead-man callback = normal callback 누락·봇 stuck 대비 safety",
    "6. normal collector 성공 시 fallback cancel-on-success 적용",
    "7. runtime registry/checkpoint = callback 누락·cron 꼬임·NO-CRON artifact "
    "read-only 복원 보조 계층 (대체 아님)",
)

NO_CRON_CORRECT_MEANING = (
    "registry/checkpoint 가 임의 신규 cron 추가 등록·cron 제거를 하지 않는다는 "
    "뜻. executor 가 작업 완료 후 ANU 에 normal completion callback 을 보내지 "
    "말라는 뜻이 절대 아님."
)

# Executor completion callback is a MANDATORY lifecycle signal.
EXECUTOR_COMPLETION_CALLBACK_REQUIRED = True


# ── primary / safety / recovery topology (§6.13 / §6.14 / §4.7 / §4.8) ────────
def callback_is_primary() -> bool:
    """§6.13 — the normal completion callback is the PRIMARY completion path."""
    return True


def registry_is_primary_completion_mechanism() -> bool:
    """§8 / §6.13 — registry/checkpoint is NEVER the primary mechanism."""
    return False


def checkpoint_is_recovery_layer() -> bool:
    """§4.7 / §6.13 — runtime checkpoint is a recovery layer, not primary."""
    return True


def fallback_is_safety_path() -> bool:
    """§4.8 / §6.6 / §6.14 — fallback/dead-man callback is a safety path."""
    return True


def cancel_on_success_applies_after_normal_success() -> bool:
    """§4.9 / §6.7 — fallback cancel-on-success applies AFTER normal success.

    9-R.1: this is a system-sanctioned designed lifecycle transition
    (+9a/+23/+25 seam + live-verifier 5-cond AND). +32 only asserts the path
    is preserved — it executes ZERO cron remove itself.
    """
    return True


def plus32_executor_removes_any_cron() -> bool:
    """9-R.1 — the +32 executor removes ZERO cron (회장 'cron 제거' 금지)."""
    return False


def executor_completion_callback_is_cron_add_violation() -> bool:
    """§6.5 — the executor's normal callback is NOT a cron-add ban breach."""
    return False


# ── no-normal-callback classification (§6.8 / §6.9) ───────────────────────────
RESULT_READY_NO_NORMAL_CALLBACK = "RESULT_READY_NO_NORMAL_CALLBACK"
NORMAL_COLLECTOR_COMPLETED = "NORMAL_COLLECTOR_COMPLETED"


def classify_no_normal_callback(
    *, result_present: bool, done_present: bool, normal_callback_registered: bool
) -> str:
    if normal_callback_registered:
        return NORMAL_COLLECTOR_COMPLETED
    if result_present or done_present:
        return RESULT_READY_NO_NORMAL_CALLBACK
    return RESULT_READY_NO_NORMAL_CALLBACK


def is_normal_lifecycle_complete(classification: str) -> bool:
    """§6.9 — RESULT_READY_NO_NORMAL_CALLBACK is recovery, not complete."""
    return classification == NORMAL_COLLECTOR_COMPLETED


# ── closeout authority correction (9-R.2 / §6.15) ─────────────────────────────
@dataclass(frozen=True)
class CloseoutAuthorityCheck:
    """9-R.2 — separate finalization authority from lifecycle signal."""

    # FAIL if escalated: repository/task-state finalization authority.
    finalization_authority_escalated: bool
    # REQUIRED: executor self-task normal completion/result/report outputs.
    executor_self_lifecycle_outputs_present: bool


def closeout_authority_violation(c: CloseoutAuthorityCheck) -> List[str]:
    """§6.15 — only finalization-authority escalation is a violation.

    Producing the executor's own normal completion callback / result.json /
    report / .done is REQUIRED and is NOT a violation (9-R.2).
    """
    reasons: List[str] = []
    if c.finalization_authority_escalated:
        reasons.append(
            "repository/task-state finalization (closeout 확정) authority "
            "escalated -> FAIL (§6.15)."
        )
    if not c.executor_self_lifecycle_outputs_present:
        reasons.append(
            "executor self-task lifecycle outputs (normal callback / "
            "result.json / report / .done) missing -> REQUIRED (9-R.2)."
        )
    return reasons


def doctrine_verdict() -> str:
    return (
        "executor completion callback = MANDATORY. "
        "NO-CRON ≠ executor completion callback 금지."
    )
