90 lines
3.0 KiB
Python
90 lines
3.0 KiB
Python
import pytest
|
|
|
|
from agent_framework.guardrails.rails import LoopRail
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_vloop_allows_repeated_reply_while_transaction_awaits_confirmation():
|
|
rail = LoopRail()
|
|
decision = await rail.evaluate(
|
|
"sim",
|
|
{
|
|
"transaction_status": "AWAITING_CONFIRMATION",
|
|
"history_texts": ["sim", "outra fala", "sim"],
|
|
},
|
|
)
|
|
assert decision.allowed is True
|
|
assert decision.metadata["mechanism"] == "deterministic_transaction_bypass"
|
|
assert decision.metadata["transaction_status"] == "AWAITING_CONFIRMATION"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_vloop_reads_awaiting_confirmation_from_active_transaction():
|
|
rail = LoopRail()
|
|
decision = await rail.evaluate(
|
|
"sim",
|
|
{
|
|
"active_transaction": {"status": "AWAITING_CONFIRMATION"},
|
|
"history_texts": ["sim", "sim"],
|
|
},
|
|
)
|
|
assert decision.allowed is True
|
|
assert decision.metadata["mechanism"] == "deterministic_transaction_bypass"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_vloop_allows_repeated_parameter_during_transaction_collection():
|
|
rail = LoopRail()
|
|
decision = await rail.evaluate(
|
|
"PED-1001",
|
|
{
|
|
"transaction_status": "COLLECTING_PARAMETERS",
|
|
"missing_parameters": ["order_id"],
|
|
"history_texts": ["PED-1001", "outra fala", "PED-1001"],
|
|
},
|
|
)
|
|
assert decision.allowed is True
|
|
assert decision.reason == "continuidade_transacional:COLLECTING_PARAMETERS"
|
|
assert decision.metadata["repeated"] is False
|
|
assert decision.metadata["mechanism"] == "deterministic_transaction_bypass"
|
|
assert decision.metadata["transaction_status"] == "COLLECTING_PARAMETERS"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_vloop_prefers_latest_live_mcp_transaction_over_stale_completed_status():
|
|
rail = LoopRail()
|
|
decision = await rail.evaluate(
|
|
"sim",
|
|
{
|
|
"transaction_status": "COMPLETED",
|
|
"active_transaction": {"status": "COMPLETED"},
|
|
"mcp_results": [
|
|
{"tool_name": "devolver_pedido", "transaction_status": "COMPLETED"},
|
|
{
|
|
"tool_name": "cancelar_pedido",
|
|
"transaction_status": "AWAITING_CONFIRMATION",
|
|
"awaiting_confirmation": True,
|
|
},
|
|
],
|
|
"history_texts": ["sim", "outra fala", "sim"],
|
|
},
|
|
)
|
|
assert decision.allowed is True
|
|
assert decision.metadata["mechanism"] == "deterministic_transaction_bypass"
|
|
assert decision.metadata["transaction_status"] == "AWAITING_CONFIRMATION"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_vloop_still_blocks_actual_repetition_outside_transaction_confirmation():
|
|
rail = LoopRail()
|
|
decision = await rail.evaluate(
|
|
"sim",
|
|
{
|
|
"transaction_status": None,
|
|
"history_texts": ["sim", "outra fala", "sim"],
|
|
},
|
|
)
|
|
assert decision.allowed is False
|
|
assert decision.reason == "Possível loop conversacional"
|
|
assert decision.metadata["repeated"] is True
|