"""Offline, deterministic hypothesis refinement over an explicitly synthetic case.

The rule-based analyst is deliberately tiny and NOT general-purpose reasoning.
Hypotheses guide searches; only retrieved source records count as evidence.
"""
import asyncio
import json
from memory_index import build_index, sample_memories
from parallel_relevance import rank
from routing import route


def assess(evidence):
    """Case-specific deterministic stand-in for independent reasoning sessions."""
    ids = set(evidence)
    if {"security-review", "release-rule"} <= ids:
        return "launch blocked by unresolved security review", []
    if "launch-plan" in ids:
        # Candidate answer reveals a missing precondition and a refutation query.
        return "launch planned", ["security approval", "approval exception policy"]
    return "insufficient evidence", []


async def refine(memories, max_rounds=3):
    if not 1 <= max_rounds <= 10:
        raise ValueError("max_rounds must be between 1 and 10")
    root = build_index(memories)
    queries = ["atlas launch"]
    evidence = {}
    trace = []
    for step in range(max_rounds):
        before = set(evidence)
        failures = []
        for query in queries:
            candidates = route(root, query)
            for result in await rank(query, candidates):
                if result.error:
                    failures.append({"id": result.memory.id, "error": result.error})
                elif result.score is not None and result.score > 0:
                    evidence[result.memory.id] = result.memory
        conclusion, next_queries = assess(evidence)
        if not next_queries:
            stop_reason = "insufficient_evidence" if not evidence else "assessment_complete"
        elif set(evidence) == before:
            stop_reason = "no_new_evidence"
        elif step + 1 == max_rounds:
            stop_reason = "round_limit"
        else:
            stop_reason = None
        status = "provisional" if next_queries else ("assessed" if evidence else "abstained")
        trace.append({"round": step + 1, "queries": queries,
                      "conclusion": conclusion, "evidence_ids": sorted(evidence),
                      "status": status, "stop_reason": stop_reason,
                      "pending_queries": next_queries,
                      "contradictions": [{"source": m.id, "challenges": other}
                                         for m in evidence.values()
                                         for other in m.contradicts if other in evidence],
                      "failures": failures})
        if stop_reason is not None:
            break
        queries = next_queries
    return trace


if __name__ == "__main__":
    print(json.dumps(asyncio.run(refine(sample_memories())), indent=2))
