fix(rectification): offer representative time once event-fit is enough
Keep unique-top and width on confirmation only, and stop lagna-frame follow-ups from blocking cards on an already-scored cluster. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -264,3 +264,40 @@ def test_indistinguishable_width_matches_public_span() -> None:
|
||||
{"time": "04:47", "rank": 3, "tied_minute_count": 25},
|
||||
])
|
||||
assert width >= 25
|
||||
|
||||
|
||||
def test_fourteen_minute_tied_cluster_proposes_but_does_not_confirm() -> None:
|
||||
extra = [{
|
||||
"id": "00000000-0000-4000-8000-000000000004",
|
||||
"domain": "family",
|
||||
"summary": "家人变化",
|
||||
"event_kind": "family_event",
|
||||
"precision": "day",
|
||||
"date_start": "2020-01-01",
|
||||
"date_end": "2020-01-01",
|
||||
}]
|
||||
rows = [
|
||||
{
|
||||
"time": f"{15 + ((50 + offset) // 60):02d}:{(50 + offset) % 60:02d}",
|
||||
"score": 20,
|
||||
"evidence": [],
|
||||
"missing_layers": [],
|
||||
}
|
||||
for offset in range(14)
|
||||
]
|
||||
decisions = build_candidate_decisions(rows, result_id="00000000-0000-4000-8000-000000000099")
|
||||
receipt = build_decision_receipt(
|
||||
_request(extra_events=extra),
|
||||
decisions,
|
||||
{"missing_layers": ["KP_cusps"], "matrix": {}},
|
||||
_diagnostics(),
|
||||
)
|
||||
exact = receipt["gates"]["exact_confirmation"]
|
||||
assert receipt["selection_allowed"] is True
|
||||
assert receipt["propose_allowed"] is True
|
||||
assert receipt["gates"]["unique_top"]["passed"] is False
|
||||
assert exact["indistinguishable_width_minutes"] >= 14
|
||||
assert exact["adjacent_passed"] is False
|
||||
assert exact["engine_granted"] is False
|
||||
assert receipt["confirmation_allowed"] is False
|
||||
assert "adjacent_minutes_indistinguishable" in receipt["confirmation_reasons"]
|
||||
|
||||
@@ -5,6 +5,7 @@ import unittest
|
||||
from scripts.rectification.decision_policy import build_candidate_decisions, build_decision_receipt
|
||||
from scripts.rectification.refinement_packet import (
|
||||
build_refinement_packet,
|
||||
cluster_scan,
|
||||
dasha_agreement,
|
||||
match_level,
|
||||
precision_stage,
|
||||
@@ -145,6 +146,32 @@ class RefinementPacketTest(unittest.TestCase):
|
||||
self.assertEqual(ready["current"], "ready_to_adopt")
|
||||
self.assertFalse(ready["unique_minute_claim"])
|
||||
|
||||
def test_precision_stage_uses_candidate_cluster_not_full_declared_range(self):
|
||||
built = {
|
||||
"static_contexts": [
|
||||
feature("12:00", d1=3, d9=1, d10=4),
|
||||
feature("13:37", d1=4, d9=1, d10=4),
|
||||
feature("15:50", d1=4, d9=1, d10=4),
|
||||
feature("15:51", d1=4, d9=1, d10=4),
|
||||
feature("16:03", d1=5, d9=1, d10=4),
|
||||
]
|
||||
}
|
||||
scan = window_scan(built)
|
||||
self.assertEqual(scan["d1_lagna_count"], 3)
|
||||
self.assertTrue(scan["d1_candidates_differ"])
|
||||
cluster = cluster_scan(built, ["15:50", "15:51"], "15:50", 14)
|
||||
self.assertEqual(cluster["d1_lagna_count"], 1)
|
||||
self.assertFalse(cluster["d1_candidates_differ"])
|
||||
packet = build_refinement_packet(
|
||||
request_events(),
|
||||
built,
|
||||
representative_time="15:50",
|
||||
candidate_times=["15:50", "15:51"],
|
||||
cluster_width_minutes=14,
|
||||
)
|
||||
self.assertEqual(packet["window_scan"]["d1_lagna_count"], 3)
|
||||
self.assertNotEqual(packet["precision_stage"]["current"], "lagna_frame")
|
||||
|
||||
def test_window_scan_reports_d24_and_fine_minute_changes_without_unique_claim(self):
|
||||
scan = window_scan({
|
||||
"static_contexts": [
|
||||
|
||||
Reference in New Issue
Block a user