30051fdfd6
server/scenarios/runtime.py — ScenarioRuntime maps a Scenario to a Pipecat Flows state-machine spec: initial 'conversation' state with the scenario's system prompt + opening line, branch metadata carried in the spec (v0.1 has no in-flight transitions per G-002 — branching is post-hoc; Phase 2+ can fork without schema change). set_branch() resolves the branch outcome from the classifier; debrief_focus() returns the per-branch focus. TASK-03-07: server/pipeline.py build_pipeline() now accepts a scenario_id, loads the runtime, and uses scenario.setup.system_prompt instead of the SLICE-02 hardcoded walking-skeleton prompt. Falls back gracefully if the scenario can't load. server/__main__.py passes PRAXIS_SCENARIO=customer_service_refund_ca_v01 by default. 7 runtime tests pass (system prompt, set_branch accept/escalate, unknown-branch error, debrief_focus per branch, flows spec branches, debrief model config). ---ci--- phase: 1 milestone: v0.1 plan: 03 task: 03-03,03-07 status: execute persona: backend-engineer requirements: covered: [REQ-SCEN-01, REQ-SCEN-FMT-01, REQ-ORCH-02] ---/ci---
68 lines
2.3 KiB
Python
68 lines
2.3 KiB
Python
"""Unit tests for the scenario runtime + flows spec (TASK-03-03, TASK-03-07)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from server.scenarios.runtime import (
|
|
ScenarioRuntime,
|
|
build_runtime,
|
|
build_runtime_from_id,
|
|
)
|
|
from server.scenarios.loader import load
|
|
|
|
|
|
def test_runtime_uses_scenario_system_prompt():
|
|
s = load("customer_service_refund_ca_v01")
|
|
rt = build_runtime(s)
|
|
assert "Jordan" in rt.system_prompt
|
|
assert "cracked" in rt.opening_line
|
|
|
|
|
|
def test_runtime_set_branch_escalate():
|
|
rt = build_runtime_from_id("customer_service_refund_ca_v01")
|
|
b = rt.set_branch("escalate")
|
|
assert b.outcome == "failure"
|
|
assert b.failure_mode == "escalates_unresolved"
|
|
assert rt.outcome == "failure"
|
|
assert rt.branch_id == "escalate"
|
|
|
|
|
|
def test_runtime_set_branch_accept():
|
|
rt = build_runtime_from_id("customer_service_refund_ca_v01")
|
|
b = rt.set_branch("accept_resolution")
|
|
assert b.outcome == "success"
|
|
assert rt.outcome == "success"
|
|
|
|
|
|
def test_runtime_set_branch_unknown_raises():
|
|
rt = build_runtime_from_id("customer_service_refund_ca_v01")
|
|
with pytest.raises(ValueError, match="Unknown branch id"):
|
|
rt.set_branch("nonexistent_branch")
|
|
|
|
|
|
def test_runtime_debrief_focus_per_branch():
|
|
rt = build_runtime_from_id("customer_service_refund_ca_v01")
|
|
# No branch set → default focus.
|
|
assert "General" in rt.debrief_focus()
|
|
rt.set_branch("escalate")
|
|
assert "escalated" in rt.debrief_focus().lower()
|
|
rt.set_branch("accept_resolution")
|
|
assert "did well" in rt.debrief_focus().lower()
|
|
|
|
|
|
def test_runtime_as_flow_spec_has_branches():
|
|
rt = build_runtime_from_id("customer_service_refund_ca_v01")
|
|
spec = rt.as_flow_spec()
|
|
assert spec["initial_state"] == "conversation"
|
|
assert "system_prompt" in spec["states"]["conversation"]
|
|
assert len(spec["states"]["conversation"]["branches"]) == 2
|
|
# v0.1: no in-flight transitions (G-002 — post-hoc classification).
|
|
assert spec["transitions"] == []
|
|
|
|
|
|
def test_runtime_default_debrief_model():
|
|
"""The scenario's debrief config uses deepseek-v4-flash:cloud no_think (D-020)."""
|
|
rt = build_runtime_from_id("customer_service_refund_ca_v01")
|
|
assert rt.scenario.debrief.model == "deepseek-v4-flash:cloud"
|
|
assert rt.scenario.debrief.mode == "no_think" |