fix(k1): cease reset zero-dispatch checkpoint
This commit is contained in:
@@ -81,9 +81,12 @@ Current violations observed on 2026-08-14:
|
|||||||
described below.
|
described below.
|
||||||
- `K1-P0-RESET-CHECKPOINT`: an explicit local scenario reset resolved a
|
- `K1-P0-RESET-CHECKPOINT`: an explicit local scenario reset resolved a
|
||||||
zero-dispatch START as `not-dispatched`, but left its exact recovery
|
zero-dispatch START as `not-dispatched`, but left its exact recovery
|
||||||
checkpoint revision 17 in `prepared`. No device/network command was sent;
|
checkpoint revision 17 in `prepared`. The reset now ceases that exact
|
||||||
the stale checkpoint blocks the next START and requires a local atomic
|
checkpoint before publishing its replay marker; its reducer and the complete
|
||||||
settlement fix before live acceptance continues.
|
scenario-reset suite are green. Live startup convergence is accepted:
|
||||||
|
checkpoint revision 18 is `ceased` against the unchanged physical
|
||||||
|
`not-dispatched` head, with no device/network command. Clean Bluetooth
|
||||||
|
selection and the next START remain to be accepted separately.
|
||||||
- `K1-P1-STOP-STABILITY`: STOP authority visibly oscillated before the operator
|
- `K1-P1-STOP-STABILITY`: STOP authority visibly oscillated before the operator
|
||||||
clicked. Not fixed in the checkpoint increment.
|
clicked. Not fixed in the checkpoint increment.
|
||||||
- `K1-P1-PENDING-FEEDBACK`: reconnect/search/select/provision transitions replace
|
- `K1-P1-PENDING-FEEDBACK`: reconnect/search/select/provision transitions replace
|
||||||
|
|||||||
@@ -8519,6 +8519,32 @@ class XgridsK1CompatibilityService:
|
|||||||
physical_preflight.get("record_revision"),
|
physical_preflight.get("record_revision"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
retired_physical_record = physical_retirement.get("record")
|
||||||
|
if (
|
||||||
|
isinstance(retired_physical_record, Mapping)
|
||||||
|
and retired_physical_record.get("action") == "start"
|
||||||
|
and retired_physical_record.get("stage") == "resolved"
|
||||||
|
and retired_physical_record.get("resolution") == "not-dispatched"
|
||||||
|
):
|
||||||
|
start_operation_id = retired_physical_record.get("operation_id")
|
||||||
|
start_acquisition_id = retired_physical_record.get("acquisition_id")
|
||||||
|
start_payload_sha256 = retired_physical_record.get("payload_sha256")
|
||||||
|
if not all(
|
||||||
|
isinstance(value, str)
|
||||||
|
for value in (
|
||||||
|
start_operation_id,
|
||||||
|
start_acquisition_id,
|
||||||
|
start_payload_sha256,
|
||||||
|
)
|
||||||
|
):
|
||||||
|
raise ActiveAcquisitionRecoveryCheckpointError(
|
||||||
|
"scenario reset resolved START without exact checkpoint identity"
|
||||||
|
)
|
||||||
|
self._cease_prepared_start_checkpoint_not_dispatched(
|
||||||
|
operation_id=cast(str, start_operation_id),
|
||||||
|
acquisition_id=cast(str, start_acquisition_id),
|
||||||
|
payload_sha256=cast(str, start_payload_sha256),
|
||||||
|
)
|
||||||
physical_disposition = str(physical_retirement.get("disposition") or "unknown")
|
physical_disposition = str(physical_retirement.get("disposition") or "unknown")
|
||||||
retired_physical_operation_id = physical_preflight.get("operation_id")
|
retired_physical_operation_id = physical_preflight.get("operation_id")
|
||||||
with self._lock:
|
with self._lock:
|
||||||
|
|||||||
@@ -19,6 +19,12 @@ from k1link.device_plugins.xgrids_k1 import (
|
|||||||
network_mutation_ledger as network_ledger_module,
|
network_mutation_ledger as network_ledger_module,
|
||||||
)
|
)
|
||||||
from k1link.device_plugins.xgrids_k1 import physical_command_ledger as ledger_module
|
from k1link.device_plugins.xgrids_k1 import physical_command_ledger as ledger_module
|
||||||
|
from k1link.device_plugins.xgrids_k1.active_acquisition_recovery_checkpoint import (
|
||||||
|
ActiveAcquisitionRecoveryConnection,
|
||||||
|
ActiveAcquisitionRecoveryIdentity,
|
||||||
|
ActiveAcquisitionRecoveryTransportBinding,
|
||||||
|
active_acquisition_project_name_sha256,
|
||||||
|
)
|
||||||
from k1link.device_plugins.xgrids_k1.facade import (
|
from k1link.device_plugins.xgrids_k1.facade import (
|
||||||
BleScanRequest,
|
BleScanRequest,
|
||||||
CompatibilityAttestationRequest,
|
CompatibilityAttestationRequest,
|
||||||
@@ -145,6 +151,58 @@ def _seed_resettable_physical_record(
|
|||||||
return record
|
return record
|
||||||
|
|
||||||
|
|
||||||
|
def _seed_prepared_start_checkpoint(
|
||||||
|
service: XgridsK1CompatibilityService,
|
||||||
|
record: PhysicalCommandRecord,
|
||||||
|
) -> None:
|
||||||
|
store = service._active_acquisition_checkpoint # noqa: SLF001
|
||||||
|
assert store is not None
|
||||||
|
project_name = "reset-prepared-checkpoint"
|
||||||
|
binding = ActiveAcquisitionRecoveryTransportBinding(
|
||||||
|
runtime_instance_id=service._snapshot_runtime_id, # noqa: SLF001
|
||||||
|
intent_id=record.connection.intent_id,
|
||||||
|
transport_ref=record.connection.transport_ref,
|
||||||
|
connection_mode=record.connection.connection_mode,
|
||||||
|
target_ipv4=record.connection.target_ipv4,
|
||||||
|
target_port=record.connection.target_port,
|
||||||
|
host_path_epoch=record.connection.host_path_epoch,
|
||||||
|
control_session_id=record.connection.control_session_id,
|
||||||
|
producer_generation=record.connection.producer_generation,
|
||||||
|
logical_device_id="reset-prepared-device",
|
||||||
|
compatibility_profile_id=record.compatibility_profile_id,
|
||||||
|
vendor_device_id_sha256=record.identity.vendor_device_id_sha256,
|
||||||
|
device_serial_sha256=record.identity.device_serial_sha256,
|
||||||
|
)
|
||||||
|
store.prepare(
|
||||||
|
transition_id=f"test-reset-prepare:{record.operation_id}",
|
||||||
|
predecessor_revision=0,
|
||||||
|
acquisition_id=record.acquisition_id,
|
||||||
|
original_start_operation_id=record.operation_id,
|
||||||
|
start_payload_sha256=record.payload_sha256,
|
||||||
|
identity=ActiveAcquisitionRecoveryIdentity(
|
||||||
|
logical_device_id="reset-prepared-device",
|
||||||
|
vendor_device_id_sha256=record.identity.vendor_device_id_sha256,
|
||||||
|
device_serial_sha256=record.identity.device_serial_sha256,
|
||||||
|
),
|
||||||
|
connection=ActiveAcquisitionRecoveryConnection(
|
||||||
|
transport_ref=record.connection.transport_ref,
|
||||||
|
connection_mode=record.connection.connection_mode,
|
||||||
|
target_ipv4=record.connection.target_ipv4,
|
||||||
|
target_port=record.connection.target_port,
|
||||||
|
),
|
||||||
|
compatibility_profile_id=record.compatibility_profile_id,
|
||||||
|
project_name=project_name,
|
||||||
|
project_name_wire_sha256=active_acquisition_project_name_sha256(project_name),
|
||||||
|
original_evidence_session_id="reset-prepared-evidence",
|
||||||
|
duration_seconds=None,
|
||||||
|
requested_streams=("spatial.point-cloud.live",),
|
||||||
|
evidence_policy="required",
|
||||||
|
mount_type="handheld",
|
||||||
|
gnss_mode="none",
|
||||||
|
prepared_binding=binding,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _install_exact_reset_scan(
|
def _install_exact_reset_scan(
|
||||||
service: XgridsK1CompatibilityService,
|
service: XgridsK1CompatibilityService,
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
@@ -297,6 +355,46 @@ def test_cold_scenario_reset_is_local_only_and_exact_retry_converges(
|
|||||||
assert first["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
|
assert first["connection_policy"]["actions"]["scan-ble"]["allowed"] is True
|
||||||
|
|
||||||
|
|
||||||
|
def test_scenario_reset_ceases_exact_prepared_start_checkpoint(
|
||||||
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
|
tmp_path: Path,
|
||||||
|
) -> None:
|
||||||
|
service = _service(monkeypatch, tmp_path)
|
||||||
|
record = _seed_resettable_physical_record(service, prepared_only=True)
|
||||||
|
_seed_prepared_start_checkpoint(service, record)
|
||||||
|
before = service._active_acquisition_checkpoint.snapshot() # type: ignore[union-attr] # noqa: SLF001
|
||||||
|
assert before.status == "prepared"
|
||||||
|
|
||||||
|
request = _reset(
|
||||||
|
mode="bridge",
|
||||||
|
revision=0,
|
||||||
|
reset_id="op-reset-prepared-checkpoint-01",
|
||||||
|
)
|
||||||
|
reset = service.select_connection_mode(request)
|
||||||
|
|
||||||
|
physical = service._physical_command_ledger.snapshot().record # noqa: SLF001
|
||||||
|
checkpoint_snapshot = service._active_acquisition_checkpoint.snapshot() # type: ignore[union-attr] # noqa: SLF001
|
||||||
|
checkpoint = checkpoint_snapshot.checkpoint
|
||||||
|
assert physical is not None
|
||||||
|
assert physical.stage == "resolved"
|
||||||
|
assert physical.resolution == "not-dispatched"
|
||||||
|
assert checkpoint_snapshot.status == "ceased"
|
||||||
|
assert checkpoint is not None
|
||||||
|
assert checkpoint.state == "ceased"
|
||||||
|
assert checkpoint.original_start_operation_id == record.operation_id
|
||||||
|
marker = reset["connection_scenario_reset"]
|
||||||
|
assert marker["physical_disposition"] == "not-dispatched"
|
||||||
|
assert marker["device_command_performed"] is False
|
||||||
|
assert marker["network_write_performed"] is False
|
||||||
|
|
||||||
|
replayed = service.select_connection_mode(request)
|
||||||
|
assert replayed["connection_scenario_reset"] == marker
|
||||||
|
assert (
|
||||||
|
service._active_acquisition_checkpoint.snapshot().checkpoint # type: ignore[union-attr] # noqa: SLF001
|
||||||
|
== checkpoint
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_reset_attempt_cutoff_uses_operation_identity_not_local_stage_sequence(
|
def test_reset_attempt_cutoff_uses_operation_identity_not_local_stage_sequence(
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
tmp_path: Path,
|
tmp_path: Path,
|
||||||
|
|||||||
Reference in New Issue
Block a user