Artifex/tests/test_v2_progeny_signals.py

160 lines
6.4 KiB
Python
Raw Normal View History

from __future__ import annotations
import pytest
from django.test import TestCase
from agents.progeny import ProgenyService
from control_plane.agents.models import Agent, AgentVersion, PromotionStatus
from control_plane.events.models import Event
from control_plane.projects.models import Project, ProjectPlan, Milestone, Task
class ProgenySignalTests(TestCase):
def setUp(self):
self.project = Project.objects.create(name="Test Project", goal="Test goal")
self.plan = ProjectPlan.objects.create(project=self.project, version=1, goal="Test plan goal")
self.milestone = Milestone.objects.create(project=self.project, plan=self.plan, key="M1", title="Milestone 1", goal="Milestone goal")
self.task = Task.objects.create(project=self.project, milestone=self.milestone, task_type="CODING", goal="Implement feature")
self.agent = Agent.objects.create(name="Test Agent", role="CODER")
self.agent_version = AgentVersion.objects.create(
agent=self.agent,
version=1,
model="test-model",
system_contract="Test contract",
promotion_status=PromotionStatus.CHAMPION,
)
self.service = ProgenyService()
def test_create_reviewer_rework_signal(self):
signal = self.service.create_reviewer_signal(
project=self.project,
task=self.task,
milestone=self.milestone,
agent_version=self.agent_version,
status="REWORK_REQUIRED",
findings=[{"type": "tests_failed", "severity": "high", "message": "Tests failed"}],
summary="Reviewer requested rework",
)
self.assertEqual(signal.source, "reviewer")
self.assertEqual(signal.failure_category, "REWORK_REQUIRED")
self.assertEqual(signal.severity, "high")
self.assertEqual(signal.grouping_key, f"reviewer:{self.task.id}:REWORK_REQUIRED")
event = Event.objects.get(event_type="PROGENY_SIGNAL_CREATED")
self.assertEqual(event.payload["signal_id"], str(signal.id))
self.assertEqual(event.payload["source"], "reviewer")
def test_create_reviewer_reject_signal(self):
signal = self.service.create_reviewer_signal(
project=self.project,
task=self.task,
milestone=self.milestone,
agent_version=self.agent_version,
status="REJECTED",
findings=[{"type": "empty_diff", "severity": "high", "message": "No diff"}],
summary="Reviewer rejected",
)
self.assertEqual(signal.source, "reviewer")
self.assertEqual(signal.failure_category, "REJECTED")
self.assertEqual(signal.severity, "high")
event = Event.objects.get(event_type="PROGENY_SIGNAL_CREATED")
self.assertEqual(event.payload["status"], "REJECTED")
def test_create_judge_fail_signal(self):
signal = self.service.create_judge_signal(
project=self.project,
task=self.task,
milestone=self.milestone,
agent_version=self.agent_version,
result="FAIL",
evidence=[{"type": "test_status", "status": "FAIL"}],
summary="Judge failed",
)
self.assertEqual(signal.source, "judge")
self.assertEqual(signal.failure_category, "FAIL")
self.assertEqual(signal.severity, "high")
event = Event.objects.get(event_type="PROGENY_SIGNAL_CREATED")
self.assertEqual(event.payload["source"], "judge")
self.assertEqual(event.payload["result"], "FAIL")
def test_create_model_output_signal(self):
signal = self.service.create_model_output_signal(
project=self.project,
task=self.task,
milestone=self.milestone,
agent_version=self.agent_version,
error="Invalid JSON",
raw_output="{invalid json}",
)
self.assertEqual(signal.source, "model_output")
self.assertEqual(signal.failure_category, "MALFORMED_OUTPUT")
self.assertEqual(signal.severity, "high")
self.assertIn("Invalid JSON", signal.summary)
event = Event.objects.get(event_type="PROGENY_SIGNAL_CREATED")
self.assertEqual(event.payload["source"], "model_output")
def test_create_retry_exhausted_signal(self):
signal = self.service.create_retry_exhausted_signal(
project=self.project,
task=self.task,
milestone=self.milestone,
agent_version=self.agent_version,
attempts=3,
)
self.assertEqual(signal.source, "retry")
self.assertEqual(signal.failure_category, "RETRY_EXHAUSTED")
self.assertEqual(signal.severity, "critical")
self.assertIn("exhausted 3 retries", signal.summary)
event = Event.objects.get(event_type="PROGENY_SIGNAL_CREATED")
self.assertEqual(event.payload["source"], "retry")
def test_grouping_key_deterministic(self):
signal1 = self.service.create_reviewer_signal(
project=self.project,
task=self.task,
milestone=self.milestone,
agent_version=self.agent_version,
status="REWORK_REQUIRED",
findings=[],
summary="Rework 1",
)
signal2 = self.service.create_reviewer_signal(
project=self.project,
task=self.task,
milestone=self.milestone,
agent_version=self.agent_version,
status="REWORK_REQUIRED",
findings=[],
summary="Rework 2",
)
self.assertEqual(signal1.grouping_key, signal2.grouping_key)
def test_event_lineage(self):
self.service.create_reviewer_signal(
project=self.project,
task=self.task,
milestone=self.milestone,
agent_version=self.agent_version,
status="REWORK_REQUIRED",
findings=[],
summary="Rework",
)
self.service.create_judge_signal(
project=self.project,
task=self.task,
milestone=self.milestone,
agent_version=self.agent_version,
result="FAIL",
evidence=[],
summary="Fail",
)
events = Event.objects.filter(event_type="PROGENY_SIGNAL_CREATED").order_by("created_at")
self.assertEqual(events.count(), 2)
self.assertEqual(events[0].payload["source"], "reviewer")
self.assertEqual(events[1].payload["source"], "judge")