"""
QPPG Service — Query-Process-Predict-Guard deployment package.
==============================================================

Four tiers of agent reliability tooling:

  Tier 0 — Scoring
    QPPGService       — labeled KNN scorer (requires verified-correct chains)
    LabelFreeScorer   — zero-label scorer (behavioral + GMM + obs-pool + QARA)

  Tier 1 — Monitoring
    QppgMonitor       — drop-in agent monitor; tracks risk, fires alerts,
                        auto-calibrates, exports reports/CSV

  Tier 3 — Diagnosis
    FailureTaxonomist — classifies WHY a chain failed (retrieval failure,
                        excessive search, conflicting evidence, etc.)

  Tier 4 — Recovery
    SelfHealer        — converts FailureMode into prompt injections that
                        repair the agent mid-run

Quick start (label-free, zero setup):
    from qppg_service import QppgMonitor

    monitor = QppgMonitor(threshold=0.65)
    alert = monitor.track(question, steps, final_answer, finished=True)
    if alert:
        print(f"HIGH RISK ({alert.risk_score:.2f}): {alert.recommendation}")
    print(monitor.export_report())

Full pipeline (detect → diagnose → repair):
    from qppg_service import QppgMonitor, FailureTaxonomist, SelfHealer

    monitor = QppgMonitor()
    tx      = FailureTaxonomist()
    healer  = SelfHealer()

    alert = monitor.track(question, steps, final_answer)
    if alert:
        failure = tx.classify(question, steps, final_answer, finished)
        action  = healer.suggest(failure, question, steps, final_answer)
        print(action.prompt_injection)   # inject into agent

Expected AUROC (from exp39-44, exp89-92):
    Behavioral-only (n=0 chains):         SC_OLD=0.812±0.062 within (CV), 0.672 cross
    With calibration (n>=5):              SC8=0.883 within, 0.664 cross
    Supervised QARA (n>=50 labeled):      ~0.675 cross-domain
    Sonnet judge alone (exp89/91):        0.7735 within, 0.7411 cross-NQ (best single signal)
    J5 = SC_OLD×1+Sonnet×3 (exp89/92):   0.7767 within, conformal P=0.91 at FPR≤5%

Sonnet judge API (exp89):
    import anthropic
    client = anthropic.Anthropic()
    scorer = LabelFreeScorer()
    result = scorer.score_with_judge(question, steps, answer, client=client)
    # result.components["judge_score"] — judge risk [0,1], higher = riskier
    # result.components["judge_quality"] — GOOD | BORDERLINE | POOR

Conformal alerting (exp92, P=0.91 at FPR≤10%):
    q_hat = scorer.conformal_threshold(correct_chains, alpha=0.10, use_judge=True, client=client)
    result = scorer.score_with_judge(question, steps, answer, client=client)
    if result.risk_score > q_hat:
        send_alert()   # guaranteed: P(false positive) ≤ 10%
"""

from .service           import QPPGService
from .label_free_scorer import LabelFreeScorer, LabelFreeResult, AgentFingerprinter
from .monitor           import QppgMonitor, QppgAlert, MonitorStats, add_step, OnlineBanditWeights
from .failure_taxonomy  import FailureTaxonomist, FailureMode
from .self_healer       import SelfHealer, RecoveryAction
from .store             import ChainStore
from .drift             import DriftDetector, DriftAlert
from .alerting          import WebhookAlerter

__all__ = [
    # Tier 0 — Scoring
    "QPPGService",
    "LabelFreeScorer", "LabelFreeResult",
    # Tier 0b — Fingerprinting / cold-start calibration (exp71)
    "AgentFingerprinter",
    # Tier 1 — Monitoring
    "QppgMonitor", "QppgAlert", "MonitorStats",
    # Decorator helpers + online RL
    "add_step", "OnlineBanditWeights",
    # Tier 3 — Diagnosis
    "FailureTaxonomist", "FailureMode",
    # Tier 4 — Recovery
    "SelfHealer", "RecoveryAction",
    # Persistence
    "ChainStore",
    # Drift detection
    "DriftDetector", "DriftAlert",
    # Alerting
    "WebhookAlerter",
]
