fix(rectification): anchor candidate windows to civil dates across midnight
Carry explicit local date intervals instead of inferring the day from clock order. Cluster width, delivery, adoption, and reports keep the actual civil date; adopted date is stored separately from the reported birth_date. Algorithm identity is scoring-9 / spec-v5. Scoring weights, confirmation thresholds, and Skill version are unchanged. Isolated Linux final-3 gates passed; four pre-existing Python failures remain. This is not a production release.
This commit is contained in:
@@ -88,9 +88,21 @@ def build_flexible_birth_time_profile_from_window(
|
||||
ayanamsa: str = "raman",
|
||||
node_mode: str = "mean",
|
||||
source_reference: Mapping[str, Any],
|
||||
candidate_intervals: list[dict[str, str]] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
start, end = _parse_window(birth_date, start_time, end_time)
|
||||
normalized_times = _normalize_candidate_times(birth_date, start, end, candidate_times)
|
||||
if candidate_intervals is None:
|
||||
start, end = _parse_window(birth_date, start_time, end_time)
|
||||
normalized_times = _normalize_candidate_times(birth_date, start, end, candidate_times)
|
||||
else:
|
||||
from scripts.rectification.candidate_window import enumerate_candidate_window
|
||||
moments = enumerate_candidate_window({"birth_date": birth_date, "start_time": start_time,
|
||||
"end_time": end_time, "candidate_intervals": candidate_intervals})
|
||||
by_clock = {value.strftime("%H:%M"): value for value in moments}
|
||||
if not 2 <= len(candidate_times) <= MAX_CANDIDATE_MINUTES or len(set(candidate_times)) != len(candidate_times):
|
||||
raise FlexibleBirthTimeProfileError("candidate_count_must_be_two_to_thirty_one")
|
||||
if any(value not in by_clock for value in candidate_times):
|
||||
raise FlexibleBirthTimeProfileError("candidate_time_outside_window")
|
||||
normalized_times = sorted(by_clock[value] for value in candidate_times)
|
||||
candidates = [
|
||||
_candidate_from_recast(
|
||||
candidate_at=value,
|
||||
@@ -103,6 +115,14 @@ def build_flexible_birth_time_profile_from_window(
|
||||
for value in normalized_times
|
||||
]
|
||||
profile = build_flexible_birth_time_profile(candidates, source_reference=source_reference)
|
||||
if candidate_intervals is not None:
|
||||
# Keep civil chronology and declared gaps instead of the legacy clock-sorted envelope.
|
||||
clocks = [value.strftime("%H:%M") for value in normalized_times]
|
||||
profile["birth_time_window"].update({"start_time": start_time, "end_time": end_time,
|
||||
"candidate_times": clocks, "candidate_intervals": deepcopy(candidate_intervals),
|
||||
"candidate_datetimes": [value.isoformat(timespec="minutes") for value in normalized_times]})
|
||||
refs = {row["candidate_time"]: row for row in profile["candidate_references"]}
|
||||
profile["candidate_references"] = [{**refs[value.strftime("%H:%M")], "candidate_date": value.date().isoformat()} for value in normalized_times]
|
||||
profile["calculation_profile"] = {
|
||||
"ayanamsa": ayanamsa,
|
||||
"node_mode": node_mode,
|
||||
|
||||
Reference in New Issue
Block a user