Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions scripts/read_binance_account_facts.py
Original file line number Diff line number Diff line change
Expand Up @@ -614,8 +614,7 @@ def validate_strategy_report(report: Mapping[str, Any], runtime_target: Mapping[
or not isinstance(report.get("run_id"), str)
or not report["run_id"].strip()
or report.get("execution_blocked_reason")
or not isinstance(errors, Mapping)
or errors.get("errors") != []
or errors not in ({}, {"errors": []})
or not isinstance(side_effects, Mapping)
or type(side_effects.get("executed_call_count")) is not int
or side_effects.get("executed_call_count") < 0
Expand Down Expand Up @@ -700,7 +699,6 @@ def _target_identity(raw: str) -> dict[str, Any]:
raise _stop("runtime_target_invalid")
try:
from quant_platform_kit.common.runtime_target import resolve_runtime_target_from_env
from quant_platform_kit.common.live_continuity import runtime_target_permits_standard_execution

target = resolve_runtime_target_from_env(
env={"RUNTIME_TARGET_JSON": raw}, expected_platform_id="binance"
Expand All @@ -710,7 +708,6 @@ def _target_identity(raw: str) -> dict[str, Any]:
value = target.to_dict()
if (
target.dry_run_only
or not runtime_target_permits_standard_execution(target)
or not isinstance(value.get("account_scope"), str)
or not value["account_scope"]
or value["account_scope"] == "default"
Expand Down
63 changes: 63 additions & 0 deletions tests/test_binance_account_facts.py
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,35 @@ def test_runtime_target_and_protected_binding_match_canonical_selector_shape():
assert reader._binding(json.dumps(binding), target, UID_DIGEST, READER_SHA) == binding


def test_runtime_target_accepts_reconcile_only_with_valid_continuity_fingerprint():
from quant_platform_kit.common.live_continuity import runtime_target_fingerprint
from scripts import read_binance_account_facts as reader

target = {
"platform_id": "binance",
"strategy_profile": "synthetic-profile",
"dry_run_only": False,
"deployment_selector": "synthetic-deployment",
"account_selector": ["synthetic-account"],
"account_scope": "synthetic-scope",
"service_name": "synthetic-service",
}
continuity = {
"state": "RECONCILE_ONLY",
"baseline_kind": "legacy_authorized",
"baseline_id": "synthetic-baseline",
"baseline_target_sha256": runtime_target_fingerprint(target),
"captured_at": "2026-10-02",
}
target["live_continuity"] = continuity
resolved = reader._target_identity(json.dumps(target))
assert resolved["live_continuity"]["state"] == "RECONCILE_ONLY"

target["live_continuity"] = {**continuity, "baseline_target_sha256": "0" * 64}
with pytest.raises(reader.ReaderError, match="runtime_target_invalid"):
reader._target_identity(json.dumps(target))


def _eligible_strategy_report(*, receipt_outcome="no_action", confirmation=None, observation=None):
from quant_platform_kit.common.execution_receipts import build_execution_receipt

Expand Down Expand Up @@ -717,6 +746,40 @@ def test_strategy_report_accepts_closed_execution_receipt():
reader.validate_strategy_report(report, target)


@pytest.mark.parametrize("error_summary", [{}, {"errors": []}])
def test_strategy_report_accepts_only_exact_empty_error_summary_shapes(error_summary):
from scripts import read_binance_account_facts as reader

report, target = _eligible_strategy_report()
report["error_summary"] = error_summary
reader.validate_strategy_report(report, target)


@pytest.mark.parametrize("error_summary", [
None,
[],
{"errors": None},
{"errors": ["synthetic-error"]},
{"errors": [], "extra": "synthetic"},
])
def test_strategy_report_rejects_invalid_or_open_error_summary_shapes(error_summary):
from scripts import read_binance_account_facts as reader

report, target = _eligible_strategy_report()
report["error_summary"] = error_summary
with pytest.raises(reader.ReaderError, match="strategy_report_not_eligible"):
reader.validate_strategy_report(report, target)


def test_strategy_report_rejects_missing_error_summary():
from scripts import read_binance_account_facts as reader

report, target = _eligible_strategy_report()
del report["error_summary"]
with pytest.raises(reader.ReaderError, match="strategy_report_not_eligible"):
reader.validate_strategy_report(report, target)


def test_strategy_report_accepts_missing_receipt_only_for_explicit_zero_counters():
from scripts import read_binance_account_facts as reader

Expand Down
Loading