From 1ec8ca7abbc20933e6f69dbfbf3d8820a6133351 Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Fri, 23 Oct 2026 02:28:18 -0500 Subject: [PATCH] Align HKG location regressions with shared armed intent policy --- .../test_canfd_location_native_recovery.py | 2 +- .../test_classic_location_stock_intent.py | 22 ++++++++++++---- .../aol/tests/test_location_input_intent.py | 26 ++++++++++++++----- .../test_stock_location_family_intent.py | 22 +++++++++++++--- prebuilt.json | 2 +- 5 files changed, 57 insertions(+), 17 deletions(-) diff --git a/openpilot/starpilot/aol/tests/test_canfd_location_native_recovery.py b/openpilot/starpilot/aol/tests/test_canfd_location_native_recovery.py index 6b751c4f78..6bc748acca 100644 --- a/openpilot/starpilot/aol/tests/test_canfd_location_native_recovery.py +++ b/openpilot/starpilot/aol/tests/test_canfd_location_native_recovery.py @@ -23,7 +23,7 @@ from openpilot.starpilot.aol.runtime import current_native from openpilot.starpilot.aol.tests import test_ioniq_availability as caller_fixture from openpilot.starpilot.aol.tests.test_classic_location_stock_intent import host_heartbeat_bridge as host_heartbeat_bridge from openpilot.starpilot.aol.tests.test_classic_location_stock_intent import ( - assert_classic_location_independent_refusals as assert_stock_location_refusals, + assert_stock_location_warning_contract as assert_stock_location_refusals, ) from openpilot.starpilot.aol.wire import PandaSlot, SafetyState, encode_safety diff --git a/openpilot/starpilot/aol/tests/test_classic_location_stock_intent.py b/openpilot/starpilot/aol/tests/test_classic_location_stock_intent.py index ac9a266bbb..453a6db4c6 100644 --- a/openpilot/starpilot/aol/tests/test_classic_location_stock_intent.py +++ b/openpilot/starpilot/aol/tests/test_classic_location_stock_intent.py @@ -94,7 +94,7 @@ def _invalid_controls_emits_no_commands(received): -def assert_classic_location_independent_refusals(sd, card, state, now_ns): +def assert_stock_location_warning_contract(sd, card, state, now_ns): from copy import copy from openpilot.starpilot.aol.wire import decode_safety @@ -178,10 +178,22 @@ def assert_classic_location_independent_refusals(sd, card, state, now_ns): view.values['pandaStates'] = panda.as_reader().pandaStates native = dataclasses.replace(native, pandaInventory=tuple(inventory)) view.values['aolSafetyWire'] = encode_safety(native) + # Production dispatches location SOFT withdrawals through observe() and + # the shared warning owner, rather than the older critical-only helper. + view.values['aolAxisState'] = proof.as_reader() + view.logMonoTime['aolAxisState'] = stamp before = (current.lateral_baseline_ns, current.lateral_native_ns) - retained = current._temporary_host_intent_current(view, card.CP, cs, proof, stamp, now_ns, - latched=card.aol_card_intent.allowed_latch, producer=feedback.availability_producer) - assert retained == (fault == 'none'), fault + retained = not current.observe(view, card.CP, cs, now_ns, + latched=card.aol_card_intent.allowed_latch, intent_producer_session=feedback.availability_producer) + # Pedals, belt and temporary EPS conditions preserve only armed intent. + # A denied native LAT receipt while both host axes are withdrawn is also + # a pause; it supplies no native permission and never resumes commands. + # Classic independent AOL does not require the cruise MAIN level. This + # is not a new MAIN button edge and cannot replay the configured toggle. + expected = fault in ('none', 'seatbelt', 'brake', 'regen', 'gas', 'cancel', 'temporary_eps', 'native_denial') or ( + fault == 'main_off' and qualified_classic(card.CP, marked_only=True)) + assert retained == expected, (fault, current.__dict__) + assert not original.aolAxisState.lateralActive and not original.aolAxisState.longitudinalActive assert (current.lateral_baseline_ns, current.lateral_native_ns) == before @@ -633,7 +645,7 @@ def test_real_classic_stock_engagement_then_location_loss_keeps_intent(raw_fault continue fault_ticks += 1 if fault_ticks == 1: - assert_classic_location_independent_refusals(sd, card, state, now[0]) + assert_stock_location_warning_contract(sd, card, state, now[0]) assert log.OnroadEvent.EventName.pcmDisable in sd.events.names assert not axis.lateralActive and not axis.longitudinalActive assert not command.latActive and not command.longActive diff --git a/openpilot/starpilot/aol/tests/test_location_input_intent.py b/openpilot/starpilot/aol/tests/test_location_input_intent.py index 0b1577180a..c264d8ed06 100644 --- a/openpilot/starpilot/aol/tests/test_location_input_intent.py +++ b/openpilot/starpilot/aol/tests/test_location_input_intent.py @@ -81,7 +81,7 @@ def test_stock_pcm_location_input_pause_retains_intent_without_output(identity, @pytest.mark.parametrize('identity', [CAR.HYUNDAI_IONIQ_5_PE, CAR.KIA_EV9]) @pytest.mark.parametrize('fault', ['native_denial', 'native_invalid', 'panda_rx', 'relay', 'permanent_eps', 'invalid_can', 'can_timeout', 'door', 'seatbelt', 'brake', 'regen', 'physical_cancel', 'reverse', 'unknown_gear', - 'extra_user', 'hard_event', 'epoch', 'session', 'expired', 'future_source', 'no_baseline']) + 'extra_user', 'hard_event', 'epoch', 'session', 'expired', 'future_source', 'no_baseline', 'configured_cancel']) def test_stock_location_input_retention_refuses_independent_faults(identity, fault): case = fixture.IoniqAvailabilityTests(methodName='runTest') with ExitStack() as cleanup: @@ -107,7 +107,10 @@ def test_stock_location_input_retention_refuses_independent_faults(identity, fau state.seatbeltUnlatched = fault == 'seatbelt' state.brakePressed = fault == 'brake' state.regenBraking = fault == 'regen' - if fault == 'physical_cancel': + if fault == 'configured_cancel': + from dataclasses import replace + card.aol_card_intent.settings = replace(card.aol_card_intent.settings, cancel_actions=(9, 0, 0)) + if fault in ('physical_cancel', 'configured_cancel'): state.buttonEvents = [structs.CarState.ButtonEvent(type='cancel', pressed=True)] if fault in ('reverse', 'unknown_gear'): state.gearShifter = 'reverse' if fault == 'reverse' else 'unknown' @@ -124,7 +127,18 @@ def test_stock_location_input_retention_refuses_independent_faults(identity, fau if fault == 'future_source': proof.aolAxisState.sourceCarStateMonoTime = 10_030_000_000 if fault == 'no_baseline': - from openpilot.starpilot.aol.transport_pause import TransportPauseFeedback - card.aol_transport_feedback = TransportPauseFeedback(card.CP) - assert not receive(10_020_000_000, state=state, axis=proof.as_reader(), event=event.as_reader()) - assert not card.aol_card_intent.allowed_latch + # Remove the established baseline without erasing its session/history. + card.aol_transport_feedback.lateral_baseline_ns = 0 + # A physical pause is independent of the location SOFT warning. Current + # native proof and zero host commands remain mandatory; unassigned CANCEL + # preserves intent, whereas the explicitly configured CANCEL still clears. + baseline = (card.aol_transport_feedback.lateral_baseline_ns, card.aol_transport_feedback.lateral_native_ns) + retained = receive(10_020_000_000, state=state, axis=proof.as_reader(), event=event.as_reader()) + expected = fault in ('seatbelt', 'brake', 'regen') + assert retained == expected, fault + assert card.aol_card_intent.allowed_latch == expected + assert not axis.lateralActive and not axis.longitudinalActive + assert not command.latActive and not command.longActive + if expected: + assert baseline == (card.aol_transport_feedback.lateral_baseline_ns, card.aol_transport_feedback.lateral_native_ns) + diff --git a/openpilot/starpilot/aol/tests/test_stock_location_family_intent.py b/openpilot/starpilot/aol/tests/test_stock_location_family_intent.py index 29e715fceb..0c8d853a66 100644 --- a/openpilot/starpilot/aol/tests/test_stock_location_family_intent.py +++ b/openpilot/starpilot/aol/tests/test_stock_location_family_intent.py @@ -93,7 +93,7 @@ def test_existing_stock_hkg_location_and_nominal_pcm_off_keep_established_intent @pytest.mark.parametrize('family', ['canfd_radar', 'canfd_lka', 'canfd_lka_alt', 'canfd_camera', 'canfd_ccnc_camera']) @pytest.mark.parametrize('fault', ['native_denial', 'native_invalid', 'panda_rx', 'relay', 'permanent_eps', 'invalid_can', 'can_timeout', 'door', 'seatbelt', 'brake', 'regen', 'gas', 'physical_cancel', 'reverse', 'unknown_gear', - 'extra_user', 'hard_event', 'epoch', 'session', 'expired', 'future_source', 'no_baseline']) + 'extra_user', 'hard_event', 'epoch', 'session', 'expired', 'future_source', 'no_baseline', 'configured_cancel']) def test_stock_location_never_retains_intent_through_independent_fault(family, fault): from opendbc.car import structs @@ -134,7 +134,10 @@ def test_stock_location_never_retains_intent_through_independent_fault(family, f state.brakePressed = fault == 'brake' state.regenBraking = fault == 'regen' state.gasPressed = fault == 'gas' - if fault == 'physical_cancel': + if fault == 'configured_cancel': + from dataclasses import replace + card.aol_card_intent.settings = replace(card.aol_card_intent.settings, cancel_actions=(9, 0, 0)) + if fault in ('physical_cancel', 'configured_cancel'): state.buttonEvents = [structs.CarState.ButtonEvent(type='cancel', pressed=True)] if fault in ('reverse', 'unknown_gear'): state.gearShifter = 'reverse' if fault == 'reverse' else 'unknown' @@ -152,5 +155,16 @@ def test_stock_location_never_retains_intent_through_independent_fault(family, f proof.aolAxisState.sourceCarStateMonoTime = 10_060_000_000 if fault == 'no_baseline': card.aol_transport_feedback.lateral_baseline_ns = 0 - assert not receive(10_050_000_001, state=state, axis=proof.as_reader(), event=event.as_reader()) - assert not card.aol_card_intent.allowed_latch + # A physical pause is independent of the location SOFT warning. Current + # native proof and zero host commands remain mandatory; unassigned CANCEL + # preserves intent, whereas the explicitly configured CANCEL still clears. + baseline = (card.aol_transport_feedback.lateral_baseline_ns, card.aol_transport_feedback.lateral_native_ns) + retained = receive(10_050_000_001, state=state, axis=proof.as_reader(), event=event.as_reader()) + expected = fault in ('seatbelt', 'brake', 'regen', 'gas', 'physical_cancel') + assert retained == expected, fault + assert card.aol_card_intent.allowed_latch == expected + assert not axis.lateralActive and not axis.longitudinalActive + assert not command.latActive and not command.longActive + if expected: + assert baseline == (card.aol_transport_feedback.lateral_baseline_ns, card.aol_transport_feedback.lateral_native_ns) + diff --git a/prebuilt.json b/prebuilt.json index 06ef4cc34f..b6fa56e532 100644 --- a/prebuilt.json +++ b/prebuilt.json @@ -1 +1 @@ -{"protected_inventory_sha256": "3a3c366dd4876659aa63861b1316f18d9db29ddd42b8b63f66b660f6faa97f77", "schema_version": 1} +{"protected_inventory_sha256": "a8cf3e523e217d01bce30adf58c7478a7ca9a4216a754d6729da51111304172a", "schema_version": 1}