88 lines
3.3 KiB
Python
88 lines
3.3 KiB
Python
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from chat.runtime import ChatRuntime
|
|
from chat.dispatch_trace import DispatchTrace, DispatchAttempt
|
|
from core.cognition.pipeline import CognitiveTurnPipeline
|
|
|
|
|
|
def test_pack_grounded_definition_trace() -> None:
|
|
"""A pack-grounded DEFINITION turn produces selected='pack' and a trace whose
|
|
final attempt is outcome='admitted'.
|
|
"""
|
|
rt = ChatRuntime()
|
|
# "What is light?" targets a pack-resident lemma and routes to pack-grounding
|
|
resp = rt.chat("What is light?")
|
|
|
|
assert resp.grounding_source == "pack"
|
|
assert resp.dispatch_trace is not None
|
|
assert resp.dispatch_trace.selected == "pack"
|
|
|
|
attempts = resp.dispatch_trace.attempts
|
|
assert len(attempts) > 0
|
|
final_attempt = attempts[-1]
|
|
assert final_attempt.source == "pack"
|
|
assert final_attempt.outcome == "admitted"
|
|
assert "pack_grounded_surface_found" in final_attempt.reason
|
|
|
|
|
|
def test_fully_oov_universal_disclosure_trace() -> None:
|
|
"""A fully-OOV prompt (or unknown intent prompt) produces a trace where
|
|
pack/teaching/partial all show outcome='fell_through' with distinct reasons
|
|
and selected='universal_disclosure'.
|
|
"""
|
|
rt = ChatRuntime()
|
|
# "hello" has no subject matching packs or teaching, falling back to universal disclosure.
|
|
resp = rt.chat("hello")
|
|
|
|
assert resp.grounding_source == "none"
|
|
assert resp.dispatch_trace is not None
|
|
assert resp.dispatch_trace.selected == "universal_disclosure"
|
|
|
|
attempts = resp.dispatch_trace.attempts
|
|
|
|
# Check that pack, teaching, and partial all show outcome="fell_through"
|
|
attempts_by_source = {a.source: a for a in attempts}
|
|
for source in ("pack", "teaching", "partial", "oov", "universal_disclosure"):
|
|
assert source in attempts_by_source
|
|
attempt = attempts_by_source[source]
|
|
if source == "universal_disclosure":
|
|
assert attempt.outcome == "admitted"
|
|
else:
|
|
assert attempt.outcome == "fell_through"
|
|
|
|
# Verify they have distinct reasons
|
|
reasons = {attempts_by_source[s].reason for s in ("pack", "teaching", "partial")}
|
|
assert len(reasons) == 3
|
|
|
|
|
|
def test_trace_determinism() -> None:
|
|
"""The trace's reason strings are stable across two runs of the same prompt."""
|
|
rt1 = ChatRuntime()
|
|
rt2 = ChatRuntime()
|
|
|
|
prompt = "What is light?"
|
|
resp1 = rt1.chat(prompt)
|
|
resp2 = rt2.chat(prompt)
|
|
|
|
assert resp1.dispatch_trace is not None
|
|
assert resp2.dispatch_trace is not None
|
|
assert resp1.dispatch_trace.selected == resp2.dispatch_trace.selected
|
|
assert len(resp1.dispatch_trace.attempts) == len(resp2.dispatch_trace.attempts)
|
|
|
|
for a1, a2 in zip(resp1.dispatch_trace.attempts, resp2.dispatch_trace.attempts):
|
|
assert a1.source == a2.source
|
|
assert a1.outcome == a2.outcome
|
|
assert a1.reason == a2.reason
|
|
|
|
|
|
def test_pipeline_carries_dispatch_trace() -> None:
|
|
"""CognitiveTurnPipeline exposes the dispatch trace in CognitiveTurnResult."""
|
|
pipeline = CognitiveTurnPipeline(ChatRuntime())
|
|
result = pipeline.run("What is light?")
|
|
|
|
assert result.dispatch_trace is not None
|
|
assert result.dispatch_trace.selected == "pack"
|
|
assert len(result.dispatch_trace.attempts) > 0
|
|
assert result.dispatch_trace.attempts[-1].outcome == "admitted"
|