72 lines
3.3 KiB
Python
72 lines
3.3 KiB
Python
from datetime import datetime, timezone
|
|
import unittest
|
|
|
|
from src.services.decision.decision_packet_service import build_alert_candidates, build_decision_packet_from_rows
|
|
|
|
|
|
class ResearchCouncilDecisionPacketFieldTests(unittest.TestCase):
|
|
def test_packet_absorbs_council_fields_without_changing_action(self) -> None:
|
|
packet = build_decision_packet_from_rows(
|
|
instrument_id=1,
|
|
observed_ts=datetime(2026, 5, 10, 1, 0, tzinfo=timezone.utc),
|
|
plan={"id": 10, "status": "active", "bias": "bullish"},
|
|
candidate={"id": 20, "trading_plan_id": 10, "status": "blocked", "missing_confirmations": ["mss_confirmed"]},
|
|
signal={},
|
|
ticket={},
|
|
risk_result={"allowed": None, "status": "signal_missing", "reasons": ["signal_missing"]},
|
|
research_council={
|
|
"id": 77,
|
|
"status": "completed",
|
|
"payload": {
|
|
"decision": {
|
|
"research_summary": "Council wants more confirmation.",
|
|
"committee_confidence": 0.62,
|
|
"agreement_points": ["active_plan_present"],
|
|
"disagreement_points": ["structure_vs_constraints"],
|
|
"follow_up_checks": ["mss_confirmed"],
|
|
"recommended_watch_items": ["news_window_review", "visual_review_missing"],
|
|
"operator_questions": ["Has MSS confirmed?"],
|
|
}
|
|
},
|
|
},
|
|
)
|
|
|
|
self.assertEqual(packet.action_recommendation, "wait_for_confirmations")
|
|
self.assertTrue(packet.research_council["present"])
|
|
self.assertEqual(packet.research_council["run_id"], 77)
|
|
self.assertEqual(packet.research_council["research_summary"], "Council wants more confirmation.")
|
|
self.assertEqual(packet.research_council["committee_confidence"], 0.62)
|
|
|
|
def test_council_watch_items_create_visual_watch_requests(self) -> None:
|
|
packet = build_decision_packet_from_rows(
|
|
instrument_id=1,
|
|
observed_ts=datetime(2026, 5, 10, 1, 0, tzinfo=timezone.utc),
|
|
plan={"id": 10, "status": "active"},
|
|
candidate={"id": 20, "trading_plan_id": 10, "status": "blocked", "missing_confirmations": ["mss_confirmed"]},
|
|
signal={"id": 30},
|
|
ticket={},
|
|
risk_result={"allowed": None, "status": "signal_missing", "reasons": ["signal_missing"]},
|
|
research_council={
|
|
"id": 77,
|
|
"payload": {
|
|
"decision": {
|
|
"recommended_watch_items": ["news_window_review", "visual_review_missing"],
|
|
}
|
|
},
|
|
},
|
|
)
|
|
|
|
alerts = build_alert_candidates(packet)
|
|
payload = alerts[0]["payload"]
|
|
|
|
self.assertIn("news_window_review", payload["visual_trigger_types"])
|
|
self.assertIn("candidate_block_reason_review", payload["visual_trigger_types"])
|
|
self.assertEqual(payload["visual_trigger_policy"]["status"], "triggered")
|
|
self.assertIn("council_watch_item:news_window_review", payload["visual_trigger_policy"]["reason_codes"])
|
|
self.assertGreaterEqual(len(payload["visual_watch_requests"]), 2)
|
|
self.assertEqual(payload["research_council"]["run_id"], 77)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|