Files
ai-exchange/tests/unit/test_operator_workspace_service.py
T
2026-05-13 22:12:06 +08:00

854 lines
58 KiB
Python

import os
import unittest
from unittest.mock import patch
os.environ.setdefault("DATABASE_URL", "postgresql+psycopg://user:pass@localhost:5432/ai_ict_test")
from src.services.operator import DecisionAssistantSummaryService, OperatorNoteService, ReviewPacketService, SessionFocusService
class OperatorWorkspaceServiceTests(unittest.TestCase):
def test_create_note_returns_payload(self) -> None:
service = OperatorNoteService(repository=_NoteRepo())
payload = service.create_note(
instrument_id=1,
note_scope="session",
author="alice",
body="Watch NY_AM sweep quality.",
session_code="NY_AM",
tags=["handoff"],
)
self.assertEqual(payload["author"], "alice")
self.assertEqual(payload["session_code"], "NY_AM")
def test_session_focus_aggregates_candidates_executions_and_alerts(self) -> None:
service = SessionFocusService(
candidate_repository=_CandidateRepo(),
execution_service=_ExecutionService(),
decision_repository=_DecisionRepo(),
session_repository=_SessionRepo(),
trust_service=_TrustService(),
)
summary = service.build_summary(instrument_id=1, limit=2)
self.assertEqual(summary["items"][0]["candidate_count"], 1)
self.assertEqual(summary["items"][0]["open_execution_count"], 1)
self.assertEqual(summary["items"][0]["alert_count"], 1)
self.assertEqual(summary["items"][0]["action_hint"], "review_alerts")
def test_review_packet_collects_core_sections(self) -> None:
service = ReviewPacketService(
note_service=_NoteService(),
decision_service=_DecisionService(),
execution_service=_ExecutionService(),
trust_service=_TrustService(),
weekly_review_service=_WeeklyReviewService(),
decision_repository=_DecisionRepo(),
alert_quality_summary_service=_AlertQualitySummaryService(),
research_council_service=_ResearchCouncilService(),
optimization_review_service=_OptimizationReviewService(),
decision_assistant_service=_DecisionAssistantService(),
)
packet = service.build_packet(instrument_id=1)
self.assertIn("decision_packet", packet)
self.assertIn("recent_notes", packet)
self.assertIn("weekly_review", packet)
self.assertIn("alert_quality_summary", packet)
self.assertIn("trust_score", packet)
self.assertIn("research_council", packet)
self.assertIn("research_council_optimization_review", packet)
self.assertIn("decision_assistant_summary", packet)
self.assertEqual(packet["research_council"]["id"], 31)
self.assertEqual(packet["research_council_optimization_review"]["health_state"], "healthy")
def test_review_packet_allows_absent_research_council_without_regression(self) -> None:
service = ReviewPacketService(
note_service=_NoteService(),
decision_service=_DecisionService(),
execution_service=_ExecutionService(),
trust_service=_TrustService(),
weekly_review_service=_WeeklyReviewService(),
decision_repository=_DecisionRepo(),
alert_quality_summary_service=_AlertQualitySummaryService(),
research_council_service=_EmptyResearchCouncilService(),
optimization_review_service=_OptimizationReviewService(),
decision_assistant_service=_DecisionAssistantService(),
)
packet = service.build_packet(instrument_id=1)
self.assertIn("decision_packet", packet)
self.assertIn("recent_notes", packet)
self.assertIn("weekly_review", packet)
self.assertIn("trust_score", packet)
self.assertIsNone(packet["research_council"])
def test_decision_assistant_summary_prioritizes_current_setup(self) -> None:
service = DecisionAssistantSummaryService(
launch_readiness_service=_LaunchReadinessService(),
session_focus_service=_SessionFocusSummaryService(),
operator_digest_service=_OperatorDigestSummaryService(),
decision_repository=_PreviousPacketRepo(),
candidate_repository=_CandidateWatchlistRepo(),
research_council_service=_ResearchCouncilSummaryService(),
exchange_status_provider=_ExchangeStatusProvider(),
announcements_provider=_AnnouncementsProvider(),
)
summary = service.build_summary(
instrument_id=1,
timeframe="5m",
decision_packet={
"status": "actionable",
"action_recommendation": "confirm_ticket",
"candidate_id": 18,
"packet_ts": "2026-05-12T02:00:00+00:00",
"ai_explanation": "London sweep is confirmed and risk stays bounded.",
"narrative": "London draw into discount then MSS reclaim.",
"bias": "bullish",
"setup_type": "SWEEP_MSS_FVG",
"why_allowed": ["candidate_confirmed", "risk_governor_passed"],
"why_blocked": ["trust_soft_block"],
"trust_classification": "observe",
"operator_mode": "decision_support_only",
"research_council": {
"follow_up_checks": ["watch_london_open"],
"recommended_watch_items": ["news_window_review"],
"operator_questions": ["Should London wait for CPI to clear?"],
"next_confirmation_targets": ["wait_for_mss_reclaim"],
},
},
weekly_review={
"next_week_actions": ["review_london_session_playbook"],
"session_performance": {
"LONDON": {
"count": 5,
"framework_execution_rate": 0.8,
"model_outside_rate": 0.1,
"risk_violation_count": 1,
"avg_r_multiple": 1.4,
},
"NY_AM": {
"count": 4,
"framework_execution_rate": 0.5,
"model_outside_rate": 0.3,
"risk_violation_count": 2,
"avg_r_multiple": 0.4,
},
},
"high_quality_session": {"session_code": "LONDON", "framework_execution_rate": 0.8, "avg_r_multiple": 1.4},
"low_quality_session": {"session_code": "NY_AM", "framework_execution_rate": 0.5, "avg_r_multiple": 0.4},
},
recent_alerts=[{"created_ts": "2026-05-12T01:59:00+00:00", "alert_type": "candidate_actionable"}],
recent_notes=[
{
"created_ts": "2026-05-12T01:58:00+00:00",
"author": "assistant_template",
"body": "[top-opportunity] Candidate #18 | prior handoff",
"tags": ["assistant-template", "top-opportunity", "outcome:useful", "actionable"],
}
],
recent_executions=[{"updated_ts": "2026-05-12T01:57:00+00:00", "execution_status": "open"}],
)
self.assertEqual(summary["focus_mode"], "review_top_setup")
self.assertIn("Candidate #18", summary["headline"])
self.assertEqual(summary["top_priority_items"][0]["kind"], "decision_packet")
self.assertEqual(summary["top_opportunities"][0]["kind"], "decision_packet")
self.assertEqual(summary["candidate_watchlist_tiers"]["review_now"][0]["candidate_id"], 18)
self.assertEqual(summary["candidate_watchlist_tiers"]["strong_watch"][0]["candidate_id"], 21)
self.assertEqual(summary["candidate_watchlist_tiers"]["soft_watch"][0]["candidate_id"], 22)
self.assertEqual(summary["candidate_watchlist_tiers"]["review_now"][0]["action_method"], "POST")
self.assertIn("/trading/candidates/18/confirm-check", summary["candidate_watchlist_tiers"]["review_now"][0]["action_path"])
self.assertIn("focus_matrix", summary["candidate_watchlist_summary"])
self.assertIn("next_watchlist_focus", summary["candidate_watchlist_summary"])
self.assertIn("next_watchlist_focus_prompt", summary["candidate_watchlist_summary"])
self.assertEqual(summary["workflow_digest"][0]["phase"], "pre_market")
self.assertEqual(summary["workflow_digest"][1]["phase"], "intraday")
self.assertEqual(summary["workflow_digest"][2]["phase"], "post_trade")
self.assertIn("workflow_rhythm_summary", summary)
self.assertEqual(summary["workflow_rhythm_summary"]["phase_count"], 3)
self.assertIn("pending_count", summary["workflow_rhythm_summary"])
self.assertIn("next_action", summary["workflow_rhythm_summary"])
self.assertIn("workflow_session_completion_summary", summary)
self.assertEqual(summary["workflow_session_completion_summary"]["task_count"], 3)
self.assertIn("next_task_label", summary["workflow_session_completion_summary"])
self.assertIn("completion_ratio", summary["workflow_session_completion_summary"])
self.assertIn("workflow_artifacts", summary)
self.assertIn("workflow_artifact_summary", summary)
self.assertTrue(summary["workflow_artifacts"])
self.assertIn("next_artifact_kind", summary["workflow_artifact_summary"])
self.assertIn("assistant_loop_queue", summary)
self.assertIn("assistant_loop_summary", summary)
self.assertTrue(summary["assistant_loop_queue"])
self.assertEqual(summary["assistant_loop_summary"]["status"], "active")
self.assertTrue(summary["assistant_loop_summary"]["next_target_section"])
self.assertTrue(any(item["queue_id"] == "replay_learning" for item in summary["assistant_loop_queue"]))
self.assertIn("continuous_workspace_rail", summary)
self.assertIn("continuous_workspace_status", summary)
self.assertIn("continuous_workspace_summary", summary)
self.assertIn("workspace_continuity_handoff", summary)
self.assertTrue(summary["continuous_workspace_rail"])
self.assertIn("rail_index", summary["continuous_workspace_rail"][0])
self.assertIn("attention_level", summary["continuous_workspace_rail"][0])
self.assertIn("handoff_prompt", summary["continuous_workspace_rail"][0])
self.assertEqual(summary["continuous_workspace_summary"]["rail_count"], len(summary["continuous_workspace_rail"]))
self.assertTrue(summary["continuous_workspace_summary"]["next_target_section"])
self.assertIn("daily_rhythm_slot", summary["workflow_digest"][0])
self.assertIn("rhythm_checklist", summary["workflow_digest"][0])
self.assertIn("rhythm_status", summary["workflow_digest"][0])
self.assertIn("next_rhythm_action", summary["workflow_digest"][0])
self.assertIn("session_task_label", summary["workflow_digest"][0])
self.assertIn("session_task_status", summary["workflow_digest"][0])
self.assertIn("session_task_prompt", summary["workflow_digest"][0])
self.assertEqual(summary["decision_timeline"][0]["title"], "Current Packet")
self.assertEqual(summary["evidence_chain"][0]["title"], "Decision Gate")
self.assertEqual(summary["evidence_chain"][1]["title"], "Launch Mode")
self.assertEqual(summary["explanation_drilldown"][0]["title"], "Decision Logic")
self.assertEqual(summary["reason_citations"][0]["source_path"], "decision_packet.why_allowed[0]")
self.assertEqual(summary["learning_rollup"]["status"], "active")
self.assertEqual(summary["external_context_summary"]["status"], "active")
self.assertEqual(summary["review_entrypoints"]["status"], "active")
self.assertEqual(summary["review_entrypoints"]["actions"][0]["action_id"], "open_operator_notes")
self.assertTrue(summary["review_entrypoints"]["note_templates"])
self.assertIn("review_entry_action_queue", summary["review_entrypoints"])
self.assertIn("review_entry_handoff_summary", summary["review_entrypoints"])
self.assertTrue(summary["review_entrypoints"]["review_entry_action_queue"])
self.assertEqual(summary["review_entrypoints"]["note_templates"][0]["note_scope"], "workbench")
self.assertTrue(summary["review_entrypoints"]["note_templates"][0]["tags"])
self.assertEqual(summary["review_entrypoints"]["recommended_template_id"], "top_opportunity")
self.assertEqual(summary["review_entrypoints"]["template_summary"]["recommended_label"], "Top setup note")
self.assertEqual(summary["review_entrypoints"]["template_summary"]["recommended_reason"], "best_current_opportunity")
self.assertTrue(summary["review_entrypoints"]["template_summary"]["recommended_reuse_hint"])
self.assertEqual(summary["review_entrypoints"]["template_reuse_metrics"]["reuse_status"], "recommended_reused")
self.assertEqual(summary["review_entrypoints"]["template_reuse_metrics"]["recommended_reuse_count"], 1)
self.assertEqual(summary["review_entrypoints"]["template_reuse_metrics"]["recommended_outcome_status"], "useful_signal")
self.assertGreater(summary["review_entrypoints"]["template_reuse_metrics"]["recommended_usefulness_score"], 0)
self.assertEqual(summary["review_entrypoints"]["template_reuse_metrics"]["template_outcome_summary"]["best_template_id"], "top_opportunity")
self.assertIn("feedback_capture_needed_count", summary["review_entrypoints"]["template_reuse_metrics"]["template_outcome_summary"])
self.assertIn("feedback_loop_summary", summary["review_entrypoints"]["template_reuse_metrics"])
self.assertIn("next_feedback_template_id", summary["review_entrypoints"]["template_reuse_metrics"]["feedback_loop_summary"])
self.assertIn("template_feedback_aggregation", summary["review_entrypoints"]["template_reuse_metrics"])
self.assertIn("feedback_tuned_template_id", summary["review_entrypoints"]["template_reuse_metrics"])
self.assertIn("recommendation_tuning_status", summary["review_entrypoints"]["template_reuse_metrics"])
self.assertGreaterEqual(summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"]["useful_feedback_count"], 1)
self.assertIn("feedback_trend_status", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("negative_feedback_guardrail_count", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("negative_feedback_guardrail_template_ids", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("guardrail_resolution_queue", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("guardrail_resolution_count", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("preferred_template_decay_status", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("preferred_template_decay_template_ids", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("preference_recovery_queue", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("preference_recovery_count", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("next_preference_recovery_template_id", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("guardrail_audit_trail", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("guardrail_audit_trail_count", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("preference_recovery_recommendations", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("preference_recovery_recommendation_count", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("next_preference_recovery_action", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("guardrail_audit_filter_counts", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("guardrail_audit_filtered_trail", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("guardrail_audit_filtered_count", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("template_audit_lane_groups", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("recovery_action_shortcuts", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("recovery_action_shortcut_count", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("next_recovery_action_shortcut", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("template_audit_lane_recommendations", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("template_audit_lane_recommendation_count", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("shortcut_outcome_telemetry", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("shortcut_outcome_telemetry_count", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("shortcut_outcome_status_counts", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertIn("next_shortcut_outcome_prompt", summary["review_entrypoints"]["template_reuse_metrics"]["template_feedback_aggregation"])
self.assertEqual(summary["review_entrypoints"]["note_templates"][0]["reuse_count"], 1)
self.assertEqual(summary["review_entrypoints"]["note_templates"][0]["reuse_status"], "saved_reuse")
self.assertEqual(summary["review_entrypoints"]["note_templates"][0]["outcome_status"], "useful_signal")
self.assertTrue(summary["review_entrypoints"]["note_templates"][0]["outcome_evidence"])
self.assertTrue(summary["review_entrypoints"]["note_templates"][0]["feedback_actions"])
self.assertIn("feedback_loop_status", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("feedback_trend_history", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("negative_feedback_guardrail", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("negative_feedback_guardrail_prompt", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("guardrail_resolution_status", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("guardrail_resolution_prompt", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("preferred_template_decay", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("preferred_template_decay_reason", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("preference_recovery_status", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("preference_recovery_prompt", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("guardrail_audit_trail", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("guardrail_audit_trail_count", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("preference_recovery_recommendation", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("recovery_action_shortcuts", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("audit_lane_group", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("audit_lane_rank", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("audit_lane_recommendation", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("shortcut_outcome_telemetry", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("shortcut_outcome_telemetry_count", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("guardrail_audit_filter", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("guardrail_audit_filter_reason", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("guardrail_audit_filtered_trail", summary["review_entrypoints"]["note_templates"][0])
self.assertIn("guardrail_audit_filtered_count", summary["review_entrypoints"]["note_templates"][0])
self.assertTrue(any(item["template_id"] == "next_review" for item in summary["review_entrypoints"]["note_templates"]))
self.assertTrue(any(item["template_id"] == "queue_follow_up" for item in summary["review_entrypoints"]["note_templates"]))
self.assertTrue(any(item["reuse_hint"] for item in summary["review_entrypoints"]["note_templates"]))
self.assertEqual(summary["digest_surface"]["status"], "active")
self.assertIn("history_summary", summary["digest_surface"])
self.assertIn("recommended_kind", summary["digest_surface"]["history_summary"])
self.assertIn("stale_kind_count", summary["digest_surface"]["history_summary"])
self.assertIn("refresh_needed_count", summary["digest_surface"]["history_summary"])
self.assertIn("refresh_evidence_anchor_count", summary["digest_surface"]["history_summary"])
self.assertIn("refresh_confirmation_count", summary["digest_surface"]["history_summary"])
self.assertIn("refresh_confirmation_needed_count", summary["digest_surface"]["history_summary"])
self.assertIn("freshness_proof_count", summary["digest_surface"]["history_summary"])
self.assertIn("freshness_proof_gap_count", summary["digest_surface"]["history_summary"])
self.assertIn("refresh_confirmation_trail_count", summary["digest_surface"]["history_summary"])
self.assertIn("refresh_confirmation_trail", summary["digest_surface"]["history_summary"])
self.assertIn("proof_aging_trend_counts", summary["digest_surface"]["history_summary"])
self.assertIn("stale_proof_escalation_count", summary["digest_surface"]["history_summary"])
self.assertIn("next_stale_proof_kind", summary["digest_surface"]["history_summary"])
self.assertIn("next_stale_proof_prompt", summary["digest_surface"]["history_summary"])
self.assertIn("proof_follow_up_queue_count", summary["digest_surface"]["history_summary"])
self.assertIn("proof_follow_up_queue", summary["digest_surface"]["history_summary"])
self.assertIn("resolved_proof_count", summary["digest_surface"]["history_summary"])
self.assertIn("proof_resolution_state_counts", summary["digest_surface"]["history_summary"])
self.assertIn("next_proof_follow_up_prompt", summary["digest_surface"]["history_summary"])
self.assertIn("stale_proof_follow_up_count", summary["digest_surface"]["history_summary"])
self.assertIn("proof_follow_up_age_counts", summary["digest_surface"]["history_summary"])
self.assertIn("proof_resolution_history", summary["digest_surface"]["history_summary"])
self.assertIn("proof_resolution_history_count", summary["digest_surface"]["history_summary"])
self.assertIn("oldest_proof_follow_up_kind", summary["digest_surface"]["history_summary"])
self.assertIn("oldest_proof_follow_up_age_seconds", summary["digest_surface"]["history_summary"])
self.assertIn("proof_resolution_sla_status_counts", summary["digest_surface"]["history_summary"])
self.assertIn("proof_resolution_sla_breach_count", summary["digest_surface"]["history_summary"])
self.assertIn("proof_resolution_sla_queue", summary["digest_surface"]["history_summary"])
self.assertIn("proof_resolution_sla_queue_count", summary["digest_surface"]["history_summary"])
self.assertIn("repeated_stale_proof_suppression_count", summary["digest_surface"]["history_summary"])
self.assertIn("next_proof_resolution_sla_prompt", summary["digest_surface"]["history_summary"])
self.assertIn("proof_sla_backlog_routes", summary["digest_surface"]["history_summary"])
self.assertIn("proof_sla_backlog_queue", summary["digest_surface"]["history_summary"])
self.assertIn("proof_sla_backlog_count", summary["digest_surface"]["history_summary"])
self.assertIn("freshness_debt_summary", summary["digest_surface"]["history_summary"])
self.assertIn("next_freshness_debt_prompt", summary["digest_surface"]["history_summary"])
self.assertIn("freshness_debt_trend_counts", summary["digest_surface"]["history_summary"])
self.assertIn("sla_recovery_recommendations", summary["digest_surface"]["history_summary"])
self.assertIn("sla_recovery_recommendation_count", summary["digest_surface"]["history_summary"])
self.assertIn("next_sla_recovery_recommendation", summary["digest_surface"]["history_summary"])
self.assertIn("next_sla_recovery_prompt", summary["digest_surface"]["history_summary"])
self.assertIn("high_value_reminders", summary["digest_surface"])
self.assertIn("high_value_reminder_count", summary["digest_surface"])
self.assertIn("important_change_filter", summary["digest_surface"])
self.assertIn("importance_templates", summary["digest_surface"])
self.assertIn("digest_preference_profile", summary["digest_surface"])
self.assertIn("default_mode", summary["digest_surface"]["digest_preference_profile"])
self.assertIn("available_modes", summary["digest_surface"]["digest_preference_profile"])
self.assertIn("profile_reason", summary["digest_surface"]["digest_preference_profile"])
self.assertIn("next_high_value_change", summary["digest_surface"])
self.assertIn("digest_review_back_actions", summary["digest_surface"])
self.assertIn("digest_review_back_action_count", summary["digest_surface"])
self.assertIn("next_digest_review_back_action", summary["digest_surface"])
self.assertIn("history_browser", summary["digest_surface"])
self.assertIn("history_browser_status", summary["digest_surface"])
self.assertIn("digest_history_browser", summary)
self.assertEqual(summary["digest_history_browser"]["status"], "active")
self.assertTrue(summary["digest_history_browser"]["filter_options"])
self.assertTrue(summary["digest_history_browser"]["review_sequence"])
self.assertIn("digest_action_queue", summary["digest_surface"])
self.assertIn("digest_action_queue_count", summary["digest_surface"])
self.assertIn("next_digest_action", summary["digest_surface"])
self.assertTrue(summary["digest_surface"]["digest_action_queue"])
self.assertIn("refresh_prompts", summary["digest_surface"]["history_summary"])
self.assertIn("digest_history_groups", summary)
self.assertIn("group_status", summary["digest_history_groups"][0])
self.assertIn("headline", summary["digest_history_groups"][0])
self.assertIn("action_label", summary["digest_history_groups"][0])
self.assertIn("age_band", summary["digest_history_groups"][0])
self.assertIn("staleness_hint", summary["digest_history_groups"][0])
self.assertIn("refresh_prompt", summary["digest_history_groups"][0])
self.assertIn("refresh_action_label", summary["digest_history_groups"][0])
self.assertIn("refresh_evidence_anchor", summary["digest_history_groups"][0])
self.assertIn("refresh_evidence_path", summary["digest_history_groups"][0])
self.assertIn("refresh_confirmation_status", summary["digest_history_groups"][0])
self.assertIn("refresh_confirmation_prompt", summary["digest_history_groups"][0])
self.assertIn("freshness_proof_status", summary["digest_history_groups"][0])
self.assertIn("freshness_proof_detail", summary["digest_history_groups"][0])
self.assertIn("proof_age_trend", summary["digest_history_groups"][0])
self.assertIn("proof_escalation_level", summary["digest_history_groups"][0])
self.assertIn("proof_escalation_prompt", summary["digest_history_groups"][0])
self.assertIn("proof_follow_up_state", summary["digest_history_groups"][0])
self.assertIn("proof_follow_up_action_label", summary["digest_history_groups"][0])
self.assertIn("proof_resolved_state", summary["digest_history_groups"][0])
self.assertIn("proof_follow_up_age_seconds", summary["digest_history_groups"][0])
self.assertIn("proof_follow_up_age_band", summary["digest_history_groups"][0])
self.assertIn("proof_follow_up_stale_queue", summary["digest_history_groups"][0])
self.assertIn("proof_resolution_history", summary["digest_history_groups"][0])
self.assertIn("proof_resolution_sla_seconds", summary["digest_history_groups"][0])
self.assertIn("proof_resolution_sla_status", summary["digest_history_groups"][0])
self.assertIn("proof_resolution_sla_prompt", summary["digest_history_groups"][0])
self.assertIn("proof_sla_backlog_route", summary["digest_history_groups"][0])
self.assertIn("proof_sla_backlog_priority", summary["digest_history_groups"][0])
self.assertIn("freshness_debt_score", summary["digest_history_groups"][0])
self.assertIn("freshness_debt_trend", summary["digest_history_groups"][0])
self.assertIn("sla_recovery_recommendation", summary["digest_history_groups"][0])
self.assertIn("repeated_stale_proof_suppression", summary["digest_history_groups"][0])
self.assertIn("refresh_confirmation_trail", summary["digest_history_groups"][0])
self.assertIn("latest_confirmation_trail_item", summary["digest_history_groups"][0])
self.assertIn("browser_rank", summary["digest_history_groups"][0])
self.assertIn("filter_label", summary["digest_history_groups"][0])
self.assertIn("browser_prompt", summary["digest_history_groups"][0])
self.assertIn("review_back_priority", summary["digest_history_groups"][0])
self.assertTrue(summary["digest_history_preview"])
self.assertEqual(summary["digest_history_preview"][0]["kind"], "reminder")
self.assertEqual(summary["personalized_reminders"][0]["severity"], "high")
self.assertIn("importance_score", summary["personalized_reminders"][0])
self.assertIn("importance_template", summary["personalized_reminders"][0])
self.assertIn("high_value", summary["personalized_reminders"][0])
self.assertEqual(summary["setup_learning_rollup"]["status"], "active")
self.assertEqual(summary["setup_learning_rollup"]["top_lessons"][0]["lesson_type"], "journal_pattern")
self.assertEqual(summary["setup_learning_rollup"]["session_code"], "LONDON")
self.assertEqual(summary["setup_learning_rollup"]["session_code_source"], "market_session_fallback")
self.assertIn("replay_statistics", summary["setup_learning_rollup"])
self.assertIn("learning_attribution_summary", summary["setup_learning_rollup"])
self.assertIn("failure_reason_attribution", summary["setup_learning_rollup"])
self.assertIn("missed_opportunity_attribution", summary["setup_learning_rollup"])
self.assertIn("setup_session_market_state_stats", summary["setup_learning_rollup"])
self.assertIn("weekly_trend_breakdown", summary["setup_learning_rollup"])
self.assertIn("weekly_trend_summary", summary["setup_learning_rollup"])
self.assertIn("learning_focus_queue", summary["setup_learning_rollup"])
self.assertIn("learning_focus_queue_count", summary["setup_learning_rollup"])
self.assertIn("next_learning_focus", summary["setup_learning_rollup"])
self.assertIn("next_learning_focus_prompt", summary["setup_learning_rollup"])
self.assertIn("learning_focus_matrix", summary["setup_learning_rollup"])
self.assertTrue(summary["setup_learning_rollup"]["learning_focus_queue"])
self.assertGreaterEqual(summary["setup_learning_rollup"]["learning_attribution_summary"]["failure_reason_count"], 1)
self.assertIn("sample_count", summary["setup_learning_rollup"]["replay_statistics"])
self.assertIn("comparative_summary", summary["setup_learning_rollup"]["replay_statistics"])
self.assertIn("broader_baseline_summary", summary["setup_learning_rollup"]["replay_statistics"])
self.assertIn("notes", summary["setup_learning_rollup"]["replay_statistics"]["comparative_summary"])
self.assertIn("story", summary["setup_learning_rollup"]["replay_statistics"]["comparative_summary"])
self.assertIn("story", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"])
self.assertIn("framework_percentile", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"])
self.assertIn("composite_percentile", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"])
self.assertIn("composite_band", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"])
self.assertIn("composite_rank", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"])
self.assertIn("risk_rank", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"])
self.assertIn("risk_percentile", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"])
self.assertIn("replay_verdict", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"])
self.assertIn("peer_summary", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"])
self.assertEqual(summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family"], "LIQUIDITY_REVERSAL_FAMILY")
self.assertIn("setup_family_peer_summary", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"])
self.assertTrue(summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_peer_sessions"])
self.assertEqual(summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"]["status"], "active")
self.assertIn("trend_story", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("drift_alert", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("drift_severity", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("focus_recommendation", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertTrue(summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"]["focus_reasons"])
self.assertIn("watchlist_status", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("watchlist_priority", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("watchlist_priority_score", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_ready", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_readiness_hint", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_blockers", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_queue_status", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_queue_rank", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_next_action", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_queue_item", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_decision_history", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_decision_history_count", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("review_lane_age_status", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("review_lane_age_score", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("review_lane_aging_hint", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("review_lane_sla_seconds", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("review_lane_sla_status", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_backlog_priority", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_backlog_rank", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_backlog_reason", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_backlog_item", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_evidence_queue", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_evidence_queue_count", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_backlog_trend_status", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_backlog_trend_handoff", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_evidence_aging_status", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_evidence_aging_prompt", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_evidence_aging_queue", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_backlog_comparison_status", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("promotion_backlog_comparison_summary", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("demotion_history", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("demotion_history_count", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("sample_threshold", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertIn("sample_gap", summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"])
self.assertTrue(summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["setup_family_trend_delta"]["drift_watchlist_items"])
self.assertTrue(summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["top_sessions"])
self.assertTrue(summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["top_safe_sessions"])
self.assertTrue(summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["top_composite_sessions"])
self.assertTrue(summary["setup_learning_rollup"]["replay_statistics"]["broader_baseline_summary"]["peer_sessions"])
self.assertTrue(summary["scan_summary_cards"])
self.assertEqual(summary["scan_summary_cards"][0]["action_label"], "Open Setup")
self.assertEqual(summary["scan_summary_cards"][0]["emphasis"], "primary")
self.assertTrue(summary["scan_summary_cards"][0]["context"])
self.assertTrue(summary["scan_summary_cards"][0]["transition_hint"])
self.assertIn("completion_state", summary["scan_summary_cards"][0])
self.assertIn("completion_hint", summary["scan_summary_cards"][0])
self.assertIn("scan_completion_summary", summary)
self.assertEqual(summary["scan_completion_summary"]["status"], "active")
self.assertTrue(summary["scan_completion_summary"]["next_target_section"])
self.assertIn("handoff_marker", summary["scan_summary_cards"][0])
self.assertIn("handoff_status", summary["scan_summary_cards"][0])
self.assertIn("handoff_stale_after_seconds", summary["scan_summary_cards"][0])
self.assertIn("handoff_stale_warning", summary["scan_summary_cards"][0])
self.assertIn("scan_handoff_summary", summary)
self.assertEqual(summary["scan_handoff_summary"]["status"], "active")
self.assertTrue(summary["scan_handoff_summary"]["next_marker"])
self.assertIn("default_stale_after_seconds", summary["scan_handoff_summary"])
self.assertIn("stale_warning_count", summary["scan_handoff_summary"])
self.assertIn("handoff_stale_policy", summary["scan_handoff_summary"])
self.assertIn("cleanup_candidate_count", summary["scan_handoff_summary"])
self.assertIn("overdue_cleanup_count", summary["scan_handoff_summary"])
self.assertIn("next_cleanup_marker", summary["scan_handoff_summary"])
self.assertIn("next_cleanup_prompt", summary["scan_handoff_summary"])
self.assertIn("handoff_lane_groups", summary["scan_handoff_summary"])
self.assertIn("handoff_lifecycle_summary", summary["scan_handoff_summary"])
self.assertIn("operator_resume_queue", summary["scan_handoff_summary"])
self.assertIn("resume_queue_count", summary["scan_handoff_summary"])
self.assertIn("next_resume_marker", summary["scan_handoff_summary"])
self.assertIn("next_resume_prompt", summary["scan_handoff_summary"])
self.assertIn("resume_queue_persistence_status", summary["scan_handoff_summary"])
self.assertIn("resume_queue_persistence_key", summary["scan_handoff_summary"])
self.assertIn("resolved_lane_state_counts", summary["scan_handoff_summary"])
self.assertIn("resolved_lane_count", summary["scan_handoff_summary"])
self.assertIn("unresolved_lane_count", summary["scan_handoff_summary"])
self.assertIn("next_resolved_lane_prompt", summary["scan_handoff_summary"])
self.assertIn("resume_history", summary["scan_handoff_summary"])
self.assertIn("resume_history_count", summary["scan_handoff_summary"])
self.assertIn("resume_history_latest_event", summary["scan_handoff_summary"])
self.assertIn("stale_persistence_cleanup_queue", summary["scan_handoff_summary"])
self.assertIn("stale_persistence_cleanup_count", summary["scan_handoff_summary"])
self.assertIn("next_stale_persistence_cleanup_key", summary["scan_handoff_summary"])
self.assertIn("next_stale_persistence_cleanup_prompt", summary["scan_handoff_summary"])
self.assertIn("resume_backlog_groups", summary["scan_handoff_summary"])
self.assertIn("cleanup_action_ready_count", summary["scan_handoff_summary"])
self.assertIn("next_cleanup_action_label", summary["scan_handoff_summary"])
self.assertIn("next_cleanup_action_prompt", summary["scan_handoff_summary"])
self.assertIn("cleanup_execution_log", summary["scan_handoff_summary"])
self.assertIn("cleanup_execution_log_count", summary["scan_handoff_summary"])
self.assertIn("grouped_resume_handoff_summary", summary["scan_handoff_summary"])
self.assertIn("next_cleanup_execution_prompt", summary["scan_handoff_summary"])
self.assertIn("handoff_cleanup_recommendation", summary["scan_handoff_summary"])
self.assertTrue(summary["scan_handoff_summary"]["snooze_options"])
self.assertIn("snooze_seconds", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("lane_group", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("overdue_cleanup_candidate", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("cleanup_priority", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("lifecycle_state", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("resume_queue_rank", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("resume_action_label", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("resume_persistence_key", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("resume_persistence_status", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("resolved_lane_state", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("resolved_lane_prompt", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("resume_history", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("resume_history_count", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("stale_persistence_cleanup_status", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("stale_persistence_cleanup_prompt", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("cleanup_action_readiness", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("cleanup_action_readiness_reason", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("resume_backlog_group", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("resume_backlog_priority", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("cleanup_execution_log", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertIn("cleanup_execution_log_count", summary["scan_handoff_summary"]["handoff_markers"][0])
self.assertTrue(summary["external_context_summary"]["operator_questions"])
self.assertTrue(summary["external_context_summary"]["source_cards"])
self.assertEqual(summary["external_context_summary"]["exchange_status"]["status"], "active")
self.assertEqual(summary["external_context_summary"]["announcements_snapshot"]["status"], "active")
self.assertTrue(summary["external_context_summary"]["announcement_titles"])
self.assertIn("macro_news_calendar", summary["external_context_summary"])
self.assertGreaterEqual(summary["external_context_summary"]["macro_news_calendar_count"], 3)
self.assertIn("event_window_summary", summary["external_context_summary"])
self.assertIn("event_window_status", summary["external_context_summary"])
self.assertIn("event_window_prompt", summary["external_context_summary"])
self.assertTrue(summary["external_context_summary"]["high_volatility_window"])
self.assertTrue(summary["external_context_summary"]["exchange_anomaly_window"])
self.assertIn("window_type", summary["external_context_summary"]["macro_news_calendar"][0])
self.assertIn("chart_readonly_sources", summary["external_context_summary"])
self.assertIn("chart_stale_source_evidence", summary["external_context_summary"])
self.assertGreaterEqual(summary["external_context_summary"]["chart_readonly_source_count"], 1)
self.assertEqual(summary["external_context_summary"]["chart_stale_source_count"], 0)
self.assertEqual(summary["external_context_summary"]["chart_adapter_mode"], "optional_reference")
self.assertEqual(summary["external_context_summary"]["chart_primary_mode"], "internal_review_packet_html")
self.assertIn("optional", summary["external_context_summary"]["chart_context_prompt"].lower())
self.assertIn("CPI", summary["external_context_summary"]["headline"])
self.assertTrue(summary["no_trade_reason_items"])
self.assertIn("watch_london_open", summary["next_actions"])
self.assertIn("review_london_session_playbook", summary["next_actions"])
self.assertIn("action:observe_only->confirm_ticket", summary["changed_since_last"]["items"])
self.assertIn("candidate:none->18", summary["changed_since_last"]["items"])
class _NoteRepo:
def insert_note(self, **kwargs):
return 11
def fetch_recent_notes(self, **kwargs):
return [{"id": 11, "author": "alice"}]
class _CandidateRepo:
def fetch_recent_candidates(self, **kwargs):
return [{"session_code": "LONDON", "status": "executable", "executable": True}]
class _ExecutionService:
def build_execution_dashboard_items(self, **kwargs):
return [{"session_code": "LONDON", "execution_status": "open"}]
class _DecisionRepo:
def fetch_recent_decision_alerts(self, **kwargs):
return [{"payload": {"session_code": "LONDON"}, "alert_type": "candidate_actionable"}]
class _TrustService:
def build_summary(self, **kwargs):
return {
"models": [
{
"session_recommendations": [
{"session_code": "LONDON", "score": 80.0, "classification": "prefer"},
{"session_code": "NY_AM", "score": 30.0, "classification": "avoid"},
]
}
]
}
class _NoteService:
def get_recent_notes(self, **kwargs):
return [{"id": 1, "author": "alice"}]
class _DecisionService:
def build_preview(self, **kwargs):
return {"status": "actionable", "action_recommendation": "confirm_ticket"}
class _WeeklyReviewService:
def build_summary(self, **kwargs):
return {"entry_count": 2}
class _AlertQualitySummaryService:
def build_summary(self, **kwargs):
return {"recent_alert_count": 1, "operator_summary": "delivery success=100.0%"}
class _ResearchCouncilService:
def get_latest_run(self, **kwargs):
return {"id": 31, "payload": {"decision": {"overall_stance": "observe_only"}}}
class _EmptyResearchCouncilService:
def get_latest_run(self, **kwargs):
return None
class _OptimizationReviewService:
def build_review(self, **kwargs):
return {
"present": True,
"health_state": "healthy",
"recommended_actions": ["continue_periodic_optimization_cycle"],
}
class _DecisionAssistantService:
def build_summary(self, **kwargs):
return {
"status": "completed",
"focus_mode": "monitor_and_wait",
"headline": "Monitor session flow.",
"top_priority_items": [],
"next_actions": [],
}
class _SessionRepo:
def fetch_recent_sessions(self, **kwargs):
return [
{"session_code": "LONDON", "status": "active", "start_ts": None, "end_ts": None},
{"session_code": "NY_AM", "status": "closed", "start_ts": None, "end_ts": None},
]
class _LaunchReadinessService:
def build_summary(self, *, instrument_id: int, timeframe: str = "1m"):
return {
"instrument_id": instrument_id,
"timeframe": timeframe,
"analysis_only_ready": True,
"decision_support_ready": True,
"blocking_reasons": [],
"warning_reasons": ["trust_observe_mode"],
"next_actions": ["review_priority_setup"],
"product_operating_mode": "decision_support_only",
"market_state": {
"session": {"session_code": "LONDON", "status": "active"},
"freshness": {"code": "market_data_fresh"},
"stream_state": {"code": "market_stream_connected"},
"data_gap_state": {"code": "market_data_gap_clear"},
"news_window": {
"code": "news_window_active",
"provider_name": "tradingeconomics_snapshot",
"freshness_code": "news_provider_fresh",
"event_count": 1,
"active_events": [{"title": "CPI"}],
},
},
"external_waiting_items": ["real_trade_sample_verified"],
}
class _SessionFocusSummaryService:
def build_summary(self, *, instrument_id: int, limit: int = 6):
return {
"instrument_id": instrument_id,
"items": [
{
"session_code": "LONDON",
"status": "active",
"alert_count": 1,
"executable_candidate_count": 1,
"open_execution_count": 0,
"action_hint": "focus_now",
"session_recommendation": {"classification": "prefer", "score": 82.0},
}
],
}
class _OperatorDigestSummaryService:
def build_digest(self, *, instrument_id: int, top_limit: int = 5):
return {
"instrument_id": instrument_id,
"status": "completed",
"summary_counts": {"high_value_alert_count": 1},
"quality_flags": ["visual_mismatch_present"],
"quality_summary": {"status": "completed"},
"operator_summary": "pending feedback=2",
"review_queue": [
{
"queue_type": "high_value_alert",
"priority": "medium",
"alert_type": "candidate_actionable",
"reason": "needs_operator_review",
}
],
}
class _CandidateWatchlistRepo:
def fetch_recent_candidates(self, *, instrument_id: int, limit: int = 20):
return [
{
"id": 18,
"session_code": "LONDON",
"status": "candidate",
"quality_score": 81.0,
"model_code": "SWEEP_MSS_FVG",
"ai_explanation": "Current focus candidate.",
"missing_confirmations": ["trust_soft_block"],
},
{
"id": 21,
"session_code": "LONDON",
"status": "candidate",
"quality_score": 72.0,
"model_code": "SWEEP_MSS_FVG",
"ai_explanation": "Strong session-aligned watch.",
"missing_confirmations": ["mss"],
},
{
"id": 22,
"session_code": "NY_AM",
"status": "candidate",
"quality_score": 44.0,
"model_code": "SWEEP_MSS_FVG",
"ai_explanation": "Needs more confirmation.",
"missing_confirmations": ["fvg_retrace"],
},
{
"id": 23,
"session_code": "OFF_HOURS",
"status": "candidate",
"quality_score": 12.0,
"model_code": "SWEEP_MSS_FVG",
"ai_explanation": "Low-priority background candidate.",
"missing_confirmations": [],
},
]
class _PreviousPacketRepo:
def fetch_latest_decision_packet(self, *, instrument_id: int):
return {
"id": 7,
"instrument_id": instrument_id,
"packet_ts": "2026-05-12T01:55:00+00:00",
"action_recommendation": "observe_only",
"status": "observe_only",
"payload": {
"status": "observe_only",
"action_recommendation": "observe_only",
"candidate_id": None,
"bias": "neutral",
"trust_classification": "observe",
"why_blocked": ["candidate_not_confirmed"],
},
}
class _ResearchCouncilSummaryService:
def get_compact_lessons(
self,
*,
instrument_id: int,
session_code=None,
setup_type=None,
model_code=None,
limit: int = 5,
):
return [
{
"title": "London setup lesson",
"lesson_key": "lesson:london",
"lesson_summary": "Confirmed London sweep setups perform better after MSS reclaim.",
"lesson_type": "journal_pattern",
}
]
class _ExchangeStatusProvider:
def fetch_snapshot(self):
return {
"provider_name": "okx_system_status",
"status": "active",
"active_events": [{"title": "API maintenance", "service_type": "api"}],
}
class _AnnouncementsProvider:
def fetch_snapshot(self):
return {
"provider_name": "okx_announcements",
"status": "active",
"announcements": [{"title": "Listing schedule update", "ann_type": "listing"}],
}
if __name__ == "__main__":
unittest.main()