feat(rectification): expose candidate result reports
This commit is contained in:
@@ -680,6 +680,72 @@ class RectificationV5ServicesTest(unittest.TestCase):
|
||||
self.assertEqual(API_COMMAND_MAP[command], endpoint)
|
||||
self.assertIn(endpoint, TECHNIQUE_EXAMPLE_ENDPOINTS)
|
||||
|
||||
def test_zero_evidence_returns_declared_window_report(self):
|
||||
body = request(start_time="23:58", end_time="00:02")
|
||||
body["events"] = []
|
||||
normalized = normalize_rectification_request(body, today=date(2026, 7, 28))
|
||||
|
||||
result = score_candidates(normalized)
|
||||
report = result["rectification_report"]
|
||||
|
||||
self.assertEqual(report["candidate_range"]["start_time"], "23:58")
|
||||
self.assertEqual(report["candidate_range"]["end_time"], "00:02")
|
||||
self.assertEqual(report["candidate_range"]["width_minutes"], 5)
|
||||
self.assertIsNone(report["representative_time"])
|
||||
self.assertEqual(report["evidence"], [])
|
||||
self.assertFalse(report["candidate_range"]["representative_is_unique"])
|
||||
self.assertIn("do_not_apply_as_birth_time_truth", result["next_step_codes"])
|
||||
|
||||
def test_report_exposes_evidence_excluded_candidates_and_diagnostics_consistently(self):
|
||||
body = request()
|
||||
body["events"] = [
|
||||
event(1, "education", "education_start"),
|
||||
event(2, "career", "promotion"),
|
||||
]
|
||||
normalized = normalize_rectification_request(body, today=date(2026, 7, 28))
|
||||
built = {
|
||||
"candidate_times": ["05:13", "05:14", "05:15"],
|
||||
"matrix": {
|
||||
item["id"]: {
|
||||
"05:13": {"points": 4, "rule_ids": ["D10:test"], "technique_layers": ["D10"]},
|
||||
"05:14": {"points": 4, "rule_ids": ["D9:test"], "technique_layers": ["D9"]},
|
||||
"05:15": {"points": -1, "rule_ids": ["D1:test"], "technique_layers": ["D1"]},
|
||||
}
|
||||
for item in normalized["events"]
|
||||
},
|
||||
"date_sensitivity": [],
|
||||
"missing_layers": [],
|
||||
"static_contexts": [
|
||||
{"feature": {"time": "05:13", "ascendant_sign_index": 1}},
|
||||
{"feature": {"time": "05:14", "ascendant_sign_index": 2}},
|
||||
{"feature": {"time": "05:15", "ascendant_sign_index": 3}},
|
||||
],
|
||||
}
|
||||
diagnostic_values = {
|
||||
"primary_cluster_retention_rate": 1,
|
||||
"leave_one_event_out_retention_rate": 1,
|
||||
"leave_one_domain_out_retention_rate": 1,
|
||||
"date_sensitivity_retention_rate": 1,
|
||||
"neighbor_support_minutes": 1,
|
||||
"primary_secondary_margin_percent": 30,
|
||||
}
|
||||
with patch("scripts.rectification.api_service.build_event_contribution_matrix", return_value=built), patch(
|
||||
"scripts.rectification.api_service.build_candidate_feature_snapshot", return_value={}
|
||||
), patch("scripts.rectification.api_service.run_diagnostics", return_value=diagnostic_values):
|
||||
scored = score_candidates(normalized)
|
||||
diagnostic_result = diagnostics(normalized)
|
||||
|
||||
report = scored["rectification_report"]
|
||||
self.assertEqual(report["candidate_range"]["start_time"], "05:13")
|
||||
self.assertEqual(report["candidate_range"]["end_time"], "05:14")
|
||||
self.assertEqual(report["representative_time"], "05:13")
|
||||
self.assertEqual([row["status"] for row in report["evidence"]], ["supporting", "supporting"])
|
||||
self.assertEqual(report["evidence"][0]["methods"], ["D10"])
|
||||
self.assertGreaterEqual(len(report["excluded_candidates"]), 1)
|
||||
self.assertEqual(scored["candidate_summary"]["stability"]["label"], scored["overall_confidence"])
|
||||
self.assertEqual(diagnostic_result["rectification_report"], report)
|
||||
self.assertEqual(diagnostic_result["next_step_codes"], scored["next_step_codes"])
|
||||
|
||||
def test_http_handler_enforces_subject_and_event_kind_boundaries(self):
|
||||
handler = object.__new__(JyotishAPIHandler)
|
||||
retained = handler._rectification_v5_request(request(domain="family", event_kind="family_event"))
|
||||
|
||||
Reference in New Issue
Block a user