fix(k1): settle reopened standby after reset

This commit is contained in:
DCCONSTRUCTIONS
2026-08-14 15:16:30 +03:00
parent 0ca7316a24
commit 606cbbfae2
2 changed files with 118 additions and 3 deletions
@@ -2625,6 +2625,9 @@ class PhysicalCommandLedger:
and latest_recovery.resolution == "physical-standby-observed"
and latest_recovery.observation.session_state == "scan_over"
)
reopened_physical_state_requires_reconciliation = (
current.reopened_physical_state_requires_reconciliation
)
if current.reconciliations:
latest = current.reconciliations[-1]
if latest.reconciliation_id == reconciliation_id:
@@ -2642,6 +2645,7 @@ class PhysicalCommandLedger:
if (
latest_recovery is not None
and latest_recovery.resolution == ("physical-standby-observed")
and not reopened_physical_state_requires_reconciliation
and not (
awaiting_ready_after_scan_over
and observation.session_state == "ready"
@@ -2654,7 +2658,7 @@ class PhysicalCommandLedger:
)
if (
current.reconciled_physical_state != "active"
and not current.reopened_physical_state_requires_reconciliation
and not reopened_physical_state_requires_reconciliation
and not awaiting_ready_after_scan_over
):
raise PhysicalCommandTransitionError(
@@ -3808,6 +3812,41 @@ def _latest_current_classified_stop_reopen(
return matches[-1] if matches else None
def _is_reopened_classified_stop_standby_settlement(
record: PhysicalCommandRecord,
reconciliation: PhysicalCommandReconciliation,
*,
settlement_index: int,
) -> bool:
"""Accept one fresh READY that settles a reopened READY-classified STOP."""
classification = _prepared_stop_classification(record)
if not (
classification is not None
and classification.resolution == "physical-standby-observed"
and reconciliation.kind == "resolved-active-cessation"
and reconciliation.resolution == "physical-standby-observed"
and reconciliation.original_attempt.operation_id == record.operation_id
and reconciliation.observation.session_state == "ready"
and not reconciliation.observation.project_bound
and not reconciliation.observation.init_ready
):
return False
matching_reopens = [
(reopening, retirement)
for reopening in record.operator_reconciliation_reopens
for retirement in record.operator_retirements
if reopening.retirement_id == retirement.retirement_id
and retirement.original_attempt.operation_id == record.operation_id
and retirement.original_attempt.resolution == "not-dispatched"
]
if settlement_index >= len(matching_reopens):
return False
reopening, _ = matching_reopens[settlement_index]
reconciled_at = _as_datetime(reconciliation.reconciled_at_utc)
return reconciled_at >= _as_datetime(reopening.reopened_at_utc)
def _reopened_resolved_start_attempt(
record: PhysicalCommandRecord,
) -> PhysicalCommandAttemptAudit | None:
@@ -4929,6 +4968,7 @@ def _validate_record_semantics(record: PhysicalCommandRecord) -> None:
raise ValueError("physical reconciliation left the identity/profile chain")
active_projects_by_operation: dict[str, str | None] = {}
scan_over_ready_pending_by_operation: dict[str, bool] = {}
reopened_standby_settlements_by_operation: dict[str, int] = {}
for reconciliation in record.reconciliations:
operation_id = reconciliation.original_attempt.operation_id
if (
@@ -4959,13 +4999,29 @@ def _validate_record_semantics(record: PhysicalCommandRecord) -> None:
raise ValueError("resolved-active rebind changed or lacked the active project")
scan_over_ready_pending_by_operation[operation_id] = False
elif reconciliation.kind == "resolved-active-cessation":
if active_projects_by_operation.get(operation_id) is None and not (
standby_after_scan_over = bool(
scan_over_ready_pending_by_operation.get(operation_id) is True
and reconciliation.observation.session_state == "ready"
and not reconciliation.observation.project_bound
and not reconciliation.observation.init_ready
)
if (
active_projects_by_operation.get(operation_id) is None
and not standby_after_scan_over
):
raise ValueError("resolved-active cessation lacks a prior active state")
settlement_index = reopened_standby_settlements_by_operation.get(
operation_id,
0,
)
if not _is_reopened_classified_stop_standby_settlement(
record,
reconciliation,
settlement_index=settlement_index,
):
raise ValueError("resolved-active cessation lacks a prior active state")
reopened_standby_settlements_by_operation[operation_id] = (
settlement_index + 1
)
active_projects_by_operation[operation_id] = None
scan_over_ready_pending_by_operation[operation_id] = (
reconciliation.observation.session_state == "scan_over"