fix(execution): fail closed on unresolved orders

This commit is contained in:
Hermes Agent
2026-08-14 15:29:31 +09:00
parent 147873cb5d
commit 843df1d6f1
5 changed files with 123 additions and 11 deletions
@@ -218,6 +218,12 @@ def test_legacy_pending_without_authoritative_metadata_is_fail_closed_and_alarm_
order_date=None,
updated_at=datetime.now(tz=timezone.utc) - timedelta(days=2),
)
broker.responder = lambda _side: FillStatus(
state="filled",
filled_qty=1,
avg_price=1000,
execution_id="wrong-current-date-order",
)
execution.run_once()
execution.run_once()
@@ -225,6 +231,7 @@ def test_legacy_pending_without_authoritative_metadata_is_fail_closed_and_alarm_
persisted = repo.fetch_slot(slot.slot_id)
assert persisted.status is SlotState.PENDING_BUY
assert broker.cancel_calls == []
metadata_alarms = [
call for call in alarms.calls if call[0] == "order_reconciliation_metadata_unknown"
]
@@ -232,6 +239,49 @@ def test_legacy_pending_without_authoritative_metadata_is_fail_closed_and_alarm_
assert set(metadata_alarms[0][2]) == {"slot_id", "symbol"}
def test_requested_cancel_terminal_unresolved_alarm_is_deduped_per_process_and_reemitted_after_restart():
broker = _RecordingBroker()
repo, service, intents = _wire()
alarms = _AlarmRecorder()
execution = ExecutionService(service, repo, broker, alarm_emitter=alarms)
decision = intents.submit_buy(
BuyIntent(intent_id="requested", portfolio_id="PF-1", qty=1, timeout_sec=1)
)
broker.responder = lambda _side: FillStatus(state="accepted")
execution.run_once()
slot = repo.fetch_slot(decision.slot_id)
repo._slots[slot.slot_id] = replace(
slot,
order_submitted_at=datetime.now(tz=timezone.utc) - timedelta(minutes=1),
)
execution.run_once()
assert repo.fetch_slot(slot.slot_id).cancel_state == "requested"
assert len(broker.cancel_calls) == 1
broker.responder = lambda _side: FillStatus(
state="unknown",
raw={
"reason": "order_not_visible_unresolved",
"raw_payload": {"authorization": "secret"},
},
)
execution.run_once()
execution.run_once()
persisted = repo.fetch_slot(slot.slot_id)
assert persisted.status is SlotState.PENDING_BUY
assert len(broker.cancel_calls) == 1
unresolved = [call for call in alarms.calls if call[0] == "order_cancel_unresolved"]
assert len(unresolved) == 1
assert unresolved[0][1] == "critical"
assert set(unresolved[0][2]) == {"slot_id", "symbol", "cancel_state", "order_date"}
assert "secret" not in repr(unresolved[0])
ExecutionService(service, repo, broker, alarm_emitter=alarms).run_once()
assert len(broker.cancel_calls) == 1
assert len([call for call in alarms.calls if call[0] == "order_cancel_unresolved"]) == 2
def test_cancel_rejected_is_fail_closed_alarm_and_authoritative_bounded_retry():
broker = _RecordingBroker()
broker.cancel_outcome = CancelOutcome(CancelState.REJECTED, "closed_session")
@@ -340,3 +390,24 @@ def test_kis_recent_missing_row_stays_in_bounded_visibility_grace(monkeypatch):
assert status.state == "accepted"
assert status.raw["reason"] == "order_visibility_grace"
assert status.raw["order_visible"] is False
def test_kis_missing_authoritative_order_date_fails_closed_without_network(monkeypatch):
now = datetime(2026, 8, 15, 9, 0, tzinfo=_KST)
def forbidden_get(*_args, **_kwargs):
raise AssertionError("legacy order without original date must not query KIS")
monkeypatch.setattr(kis_mod.httpx, "get", forbidden_get)
status = _kis(lambda: now).poll_fill(
"06010:0000123456",
side="buy",
symbol="005930",
order_date=None,
submitted_at=None,
)
assert status.state == "unknown"
assert not status.is_filled
assert not status.is_terminal_reject
assert status.raw == {"reason": "order_reconciliation_metadata_unknown"}