mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-07-09 05:12:12 +02:00
record_completion, get_original_request, build_synthesis_request, cleanup_stale - test_provenance_triples.py (19 tests) — all 5 triple builders: decomposition, finding, plan, step_result, synthesis — verifying types, provenance links, goals/steps, document references, labels - test_explainability_parsing.py (21 tests) — from_triples dispatch for all new types, parsing of goals/steps/documents, precedence ordering, backwards compatibility with Analysis/Conclusion File: test_aggregator.py Tests: 16 Covers: register_fanout, record_completion, get_original_request, build_synthesis_request, cleanup_stale ──────────────────────────────────────── File: test_provenance_triples.py Tests: 19 Covers: All 5 triple builders: types, provenance links, goals/steps, documents, labels ──────────────────────────────────────── File: test_explainability_parsing.py Tests: 21 Covers: from_triples dispatch, parsing for Decomposition, Finding, Plan, StepResult ──────────────────────────────────────── File: test_pattern_base_subagent.py Tests: 8 Covers: is_subagent, emit_subagent_completion ──────────────────────────────────────── File: test_completion_dispatch.py Tests: 6 Covers: Completion detection logic, full aggregator integration flow, synthesis not re-intercepted ──────────────────────────────────────── File: test_orchestrator_contracts.py Tests: 7 Covers: Orchestration fields roundtrip, subagent-completion step, synthesis step, plan step Tests
144 lines
4.1 KiB
Python
144 lines
4.1 KiB
Python
"""
|
|
Unit tests for PatternBase subagent helpers — is_subagent() and
|
|
emit_subagent_completion().
|
|
"""
|
|
|
|
import pytest
|
|
from unittest.mock import MagicMock, AsyncMock
|
|
from dataclasses import dataclass
|
|
|
|
from trustgraph.schema import AgentRequest
|
|
|
|
from trustgraph.agent.orchestrator.pattern_base import PatternBase
|
|
|
|
|
|
@dataclass
|
|
class MockProcessor:
|
|
"""Minimal processor mock for PatternBase."""
|
|
pass
|
|
|
|
|
|
def _make_request(**kwargs):
|
|
defaults = dict(
|
|
question="Test question",
|
|
user="testuser",
|
|
collection="default",
|
|
)
|
|
defaults.update(kwargs)
|
|
return AgentRequest(**defaults)
|
|
|
|
|
|
def _make_pattern():
|
|
return PatternBase(MockProcessor())
|
|
|
|
|
|
class TestIsSubagent:
|
|
|
|
def test_returns_true_when_correlation_id_set(self):
|
|
pattern = _make_pattern()
|
|
request = _make_request(correlation_id="corr-123")
|
|
assert pattern.is_subagent(request) is True
|
|
|
|
def test_returns_false_when_correlation_id_empty(self):
|
|
pattern = _make_pattern()
|
|
request = _make_request(correlation_id="")
|
|
assert pattern.is_subagent(request) is False
|
|
|
|
def test_returns_false_when_correlation_id_missing(self):
|
|
pattern = _make_pattern()
|
|
request = _make_request()
|
|
assert pattern.is_subagent(request) is False
|
|
|
|
|
|
class TestEmitSubagentCompletion:
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_calls_next_with_completion_request(self):
|
|
pattern = _make_pattern()
|
|
request = _make_request(
|
|
correlation_id="corr-123",
|
|
parent_session_id="parent-sess",
|
|
subagent_goal="What is X?",
|
|
expected_siblings=4,
|
|
)
|
|
next_fn = AsyncMock()
|
|
|
|
await pattern.emit_subagent_completion(
|
|
request, next_fn, "The answer is Y",
|
|
)
|
|
|
|
next_fn.assert_called_once()
|
|
completion_req = next_fn.call_args[0][0]
|
|
assert isinstance(completion_req, AgentRequest)
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_completion_has_correct_step_type(self):
|
|
pattern = _make_pattern()
|
|
request = _make_request(
|
|
correlation_id="corr-123",
|
|
subagent_goal="What is X?",
|
|
)
|
|
next_fn = AsyncMock()
|
|
|
|
await pattern.emit_subagent_completion(
|
|
request, next_fn, "answer text",
|
|
)
|
|
|
|
completion_req = next_fn.call_args[0][0]
|
|
assert len(completion_req.history) == 1
|
|
step = completion_req.history[0]
|
|
assert step.step_type == "subagent-completion"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_completion_carries_answer_in_observation(self):
|
|
pattern = _make_pattern()
|
|
request = _make_request(
|
|
correlation_id="corr-123",
|
|
subagent_goal="What is X?",
|
|
)
|
|
next_fn = AsyncMock()
|
|
|
|
await pattern.emit_subagent_completion(
|
|
request, next_fn, "The answer is Y",
|
|
)
|
|
|
|
completion_req = next_fn.call_args[0][0]
|
|
step = completion_req.history[0]
|
|
assert step.observation == "The answer is Y"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_completion_preserves_correlation_fields(self):
|
|
pattern = _make_pattern()
|
|
request = _make_request(
|
|
correlation_id="corr-123",
|
|
parent_session_id="parent-sess",
|
|
subagent_goal="What is X?",
|
|
expected_siblings=4,
|
|
)
|
|
next_fn = AsyncMock()
|
|
|
|
await pattern.emit_subagent_completion(
|
|
request, next_fn, "answer",
|
|
)
|
|
|
|
completion_req = next_fn.call_args[0][0]
|
|
assert completion_req.correlation_id == "corr-123"
|
|
assert completion_req.parent_session_id == "parent-sess"
|
|
assert completion_req.subagent_goal == "What is X?"
|
|
assert completion_req.expected_siblings == 4
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_completion_has_empty_pattern(self):
|
|
pattern = _make_pattern()
|
|
request = _make_request(
|
|
correlation_id="corr-123",
|
|
subagent_goal="goal",
|
|
)
|
|
next_fn = AsyncMock()
|
|
|
|
await pattern.emit_subagent_completion(
|
|
request, next_fn, "answer",
|
|
)
|
|
|
|
completion_req = next_fn.call_args[0][0]
|
|
assert completion_req.pattern == ""
|