"""Callback lifecycle classification state constants (single source).

회장 승인 2축(+root_cause 태그) schema의 enum/상수 단일소스.
- 축A: delivery_outcome (최종 어떻게 수집됐나)
- 축B: normal_callback_miss_cause (왜 normal 이 안 떴나)
- 축C: root_cause_tags (evidence-derivable 다중 태그)
- evidence_completeness: COMPLETE / PARTIAL / MISSING

단일소스 스펙: memory/specs/system_callback_lifecycle_state_schema_260522.md
★ 이 모듈은 anu_v3 런타임을 import 하지 않는다 (evidence-only decoupled).
"""

# ── 축A: delivery_outcome ──
NORMAL_CALLBACK_RECEIVED = "NORMAL_CALLBACK_RECEIVED"
FALLBACK_COLLECTOR_APPLIED = "FALLBACK_COLLECTOR_APPLIED"
DUPLICATE_FALLBACK_NO_OP = "DUPLICATE_FALLBACK_NO_OP"
MANUAL_ANU_REVERIFY = "MANUAL_ANU_REVERIFY"
NOT_YET_COLLECTED = "NOT_YET_COLLECTED"
UNKNOWN_INSUFFICIENT_EVIDENCE = "UNKNOWN_INSUFFICIENT_EVIDENCE"  # = UNKNOWN(INSUFFICIENT_EVIDENCE)

DELIVERY_OUTCOMES = frozenset({
    NORMAL_CALLBACK_RECEIVED, FALLBACK_COLLECTOR_APPLIED, DUPLICATE_FALLBACK_NO_OP,
    MANUAL_ANU_REVERIFY, NOT_YET_COLLECTED, UNKNOWN_INSUFFICIENT_EVIDENCE,
})

# ── 축B: normal_callback_miss_cause ──
NONE = "NONE"
ENVELOPE_PREPARED_NOT_FIRED = "ENVELOPE_PREPARED_NOT_FIRED"
FINISH_TASK_GIT_GATE_BLOCKED_BEFORE_CALLBACK = "FINISH_TASK_GIT_GATE_BLOCKED_BEFORE_CALLBACK"
SELF_KEY_FAIL_CLOSED_BEFORE_FIRE = "SELF_KEY_FAIL_CLOSED_BEFORE_FIRE"
SELF_KEY_FIRED_NON_AUTHORITATIVE = "SELF_KEY_FIRED_NON_AUTHORITATIVE"
CALLBACK_DELIVERY_GAP = "CALLBACK_DELIVERY_GAP"
CALLBACK_CONTRACT_VIOLATION = "CALLBACK_CONTRACT_VIOLATION"
MISS_CAUSE_UNKNOWN = "UNKNOWN_INSUFFICIENT_EVIDENCE"

MISS_CAUSES = frozenset({
    NONE, ENVELOPE_PREPARED_NOT_FIRED, FINISH_TASK_GIT_GATE_BLOCKED_BEFORE_CALLBACK,
    SELF_KEY_FAIL_CLOSED_BEFORE_FIRE, SELF_KEY_FIRED_NON_AUTHORITATIVE,
    CALLBACK_DELIVERY_GAP, CALLBACK_CONTRACT_VIOLATION, MISS_CAUSE_UNKNOWN,
})

# ── 축C: root_cause_tags (다중 · append-only) ──
FOREIGN_DIRTY_BLOCKER = "FOREIGN_DIRTY_BLOCKER"
BOT_APP_TOKEN_ABSENT = "BOT_APP_TOKEN_ABSENT"
REFLECTION_NOT_MERGED = "REFLECTION_NOT_MERGED"
GIT_GATE_SHARED_WORKSPACE_MISFIRE = "GIT_GATE_SHARED_WORKSPACE_MISFIRE"
SCOPE_GUARD_MAIN_HEAD_DIVERGENCE = "SCOPE_GUARD_MAIN_HEAD_DIVERGENCE"
CALLBACK_ENVELOPE_ONLY = "CALLBACK_ENVELOPE_ONLY"
# SELF_KEY_FAIL_CLOSED_BEFORE_FIRE 는 축B 값이자 축C 태그로도 쓰임(동일 문자열).

ROOT_CAUSE_TAGS = frozenset({
    FOREIGN_DIRTY_BLOCKER, BOT_APP_TOKEN_ABSENT, REFLECTION_NOT_MERGED,
    GIT_GATE_SHARED_WORKSPACE_MISFIRE, SCOPE_GUARD_MAIN_HEAD_DIVERGENCE,
    CALLBACK_ENVELOPE_ONLY, SELF_KEY_FAIL_CLOSED_BEFORE_FIRE,
})

# root_cause_tags 결정적 출력 순서 (회장 매핑과 정합)
ROOT_CAUSE_TAG_ORDER = [
    FOREIGN_DIRTY_BLOCKER,
    GIT_GATE_SHARED_WORKSPACE_MISFIRE,
    SCOPE_GUARD_MAIN_HEAD_DIVERGENCE,
    SELF_KEY_FAIL_CLOSED_BEFORE_FIRE,
    BOT_APP_TOKEN_ABSENT,
    REFLECTION_NOT_MERGED,
    CALLBACK_ENVELOPE_ONLY,
]

# ── evidence_completeness ──
COMPLETE = "COMPLETE"
PARTIAL = "PARTIAL"
MISSING = "MISSING"

# ── classification ──
INCIDENT = "incident"
NORMAL = "normal"
INCIDENT_MISS_CAUSES = frozenset({
    SELF_KEY_FIRED_NON_AUTHORITATIVE, CALLBACK_CONTRACT_VIOLATION, CALLBACK_DELIVERY_GAP,
})

# ── cron owner key 식별 (라우팅 식별자 · 비밀 아님 · 스펙 §6 단일소스) ──
# routing identifier, not a secret
# c119085a=ANU(authoritative), 그 외(예: 1e41a232)=executor self-key(non-authoritative).
DEFAULT_ANU_KEYS = frozenset({"c119085addb0f8b7"})

def is_anu_owner_key(key, anu_keys=DEFAULT_ANU_KEYS):
    """owner key 가 ANU authoritative key 인지 판정. None/미상 → False."""
    return bool(key) and key in anu_keys

# ── evidence 소스 (판정 근거 단일소스 · 스펙 §6) ──
CANONICAL_EVIDENCE_SOURCES = ["result_json", "schedule_history", "escalate", "collectors", "applied_count", "git"]
CORE_EVIDENCE_SOURCES = frozenset({"result_json", "schedule_history", "collectors"})

# ── 기타 제약 사항 ──
# callback envelope UTF-8 byte 상한 (스펙 §10 envelope-only · 매직넘버 단일소스화)
MAX_ENVELOPE_BYTES = 3900
