"""Deterministic RAG debugging exercise. Python 3.9+, no packages or API keys.
Synthetic labels demonstrate pipeline checks, not an LLM quality benchmark.
"""
cases = [
    dict(name="retrieval-miss", gold={"policy-v2"}, retrieved=["faq", "policy-v1"],
         context=["faq"], claims=[False], answerable=True, refused=False),
    dict(name="context-dropped", gold={"policy-v2"}, retrieved=["faq", "policy-v2"],
         context=["faq"], claims=[False], answerable=True, refused=False),
    dict(name="unsupported-answer", gold={"policy-v2"}, retrieved=["policy-v2"],
         context=["policy-v2"], claims=[True, False], answerable=True, refused=False),
    dict(name="supported-answer", gold={"policy-v2"}, retrieved=["policy-v2"],
         context=["policy-v2"], claims=[True, True], answerable=True, refused=False),
    dict(name="correct-refusal", gold=set(), retrieved=["faq"],
         context=["faq"], claims=[], answerable=False, refused=True),
    dict(name="unnecessary-refusal", gold={"policy-v2"}, retrieved=["policy-v2"],
         context=["policy-v2"], claims=[], answerable=True, refused=True),
]

def diagnose(case):
    gold = case["gold"]
    recall = len(gold & set(case["retrieved"])) / len(gold) if gold else None
    retained = len(gold & set(case["context"])) / len(gold) if gold else None
    claims = case["claims"]
    support = sum(claims) / len(claims) if claims else None
    if not case["answerable"]:
        stage = "correct refusal" if case["refused"] else "missing refusal"
    elif recall < 1:
        stage = "retrieval"
    elif retained < 1:
        stage = "context assembly"
    elif case["refused"]:
        stage = "unnecessary refusal"
    elif support is None or support < 1:
        stage = "generation / evidence"
    else:
        stage = "supported; check correctness separately"
    return recall, retained, support, stage

if __name__ == "__main__":
    expected = ["retrieval", "context assembly", "generation / evidence",
                "supported; check correctness separately", "correct refusal",
                "unnecessary refusal"]
    for case, stage in zip(cases, expected):
        result = diagnose(case)
        assert result[3] == stage, (case["name"], result)
        print(f"{case['name']}: recall={result[0]}, retained={result[1]}, "
              f"support={result[2]} -> {result[3]}")
    assert diagnose(cases[4])[:3] == (None, None, None)
    assert diagnose(cases[2])[2] == 0.5
