ОРРКЕСТРАЦИЯ - Оркестрация домена: ввести step-validator и починить исторический as_of_date в item-trace
This commit is contained in:
@@ -13,6 +13,7 @@ from scripts.domain_case_loop import (
|
||||
evaluate_analyst_gate,
|
||||
load_scenario_pack,
|
||||
merge_scenario_date_scope,
|
||||
validate_step_contract,
|
||||
)
|
||||
|
||||
|
||||
@@ -134,6 +135,65 @@ def test_load_scenario_pack_accepts_active_domain_contract(tmp_path) -> None:
|
||||
assert pack["scenarios"][0]["steps"][1]["question_id"] == "Q19"
|
||||
|
||||
|
||||
def test_load_scenario_pack_enriches_step_with_node_contract_defaults(tmp_path) -> None:
|
||||
manifest_path = tmp_path / "active_domain_contract.json"
|
||||
manifest_path.write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"schema_version": "active_domain_contract_v1",
|
||||
"status": "active",
|
||||
"domain_id": "inventory_stock_supplier_provenance",
|
||||
"runtime_domain": "inventory_stock",
|
||||
"title": "Warehouse domain",
|
||||
"question_pool": {
|
||||
"questions": [
|
||||
{"question_id": "Q19", "node_id": "N03_selected_item_supplier", "text": "Q19"},
|
||||
]
|
||||
},
|
||||
"scenario_tree": {
|
||||
"critical_nodes": [
|
||||
{
|
||||
"node_id": "N03_selected_item_supplier",
|
||||
"expected_intents": ["inventory_purchase_provenance_for_item"],
|
||||
"expected_answer_shape": "direct_supplier_answer_first_then_evidence",
|
||||
"required_carryover_invariants": ["focus_object", "date_scope"],
|
||||
}
|
||||
]
|
||||
},
|
||||
"orchestration_pack": {
|
||||
"pack_id": "inventory_active_contract_smoke",
|
||||
"scenarios": [
|
||||
{
|
||||
"scenario_id": "inventory_selected_item_provenance",
|
||||
"title": "Selected item provenance",
|
||||
"steps": [
|
||||
{
|
||||
"step_id": "step_02_supplier",
|
||||
"question_id": "Q19",
|
||||
"node_id": "N03_selected_item_supplier",
|
||||
"question": "По выбранному объекту \"...\": кто это поставил нам",
|
||||
}
|
||||
],
|
||||
}
|
||||
],
|
||||
},
|
||||
},
|
||||
ensure_ascii=False,
|
||||
indent=2,
|
||||
)
|
||||
+ "\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
pack = load_scenario_pack(manifest_path)
|
||||
step = pack["scenarios"][0]["steps"][0]
|
||||
|
||||
assert step["expected_intents"] == ["inventory_purchase_provenance_for_item"]
|
||||
assert step["required_answer_shape"] == "direct_supplier_answer_first_then_evidence"
|
||||
assert "focus_object" in step["required_carryover_invariants"]
|
||||
assert "date_scope" in step["required_carryover_invariants"]
|
||||
|
||||
|
||||
def test_build_scenario_acceptance_matrix_marks_green_edge_when_covering_scenario_is_accepted() -> None:
|
||||
pack = {
|
||||
"pack_id": "inventory_active_contract_smoke",
|
||||
@@ -323,3 +383,119 @@ def test_evaluate_analyst_gate_requires_temporal_honesty_field_truth_and_layerin
|
||||
assert requires_user_decision is False
|
||||
assert user_decision_type == "none"
|
||||
assert user_decision_prompt is None
|
||||
|
||||
|
||||
def test_validate_step_contract_rejects_wrong_month_filter_even_when_execution_is_exact() -> None:
|
||||
validated = validate_step_contract(
|
||||
{
|
||||
"execution_status": "exact",
|
||||
"status": "exact",
|
||||
"node_role": "root",
|
||||
"analysis_context": {"as_of_date": "2016-05-31"},
|
||||
"expected_intents": ["inventory_on_hand_as_of_date"],
|
||||
"detected_intent": "inventory_on_hand_as_of_date",
|
||||
"expected_capability": "confirmed_inventory_on_hand_as_of_date",
|
||||
"capability_id": "confirmed_inventory_on_hand_as_of_date",
|
||||
"expected_recipe": "address_inventory_on_hand_as_of_date_v1",
|
||||
"selected_recipe": "address_inventory_on_hand_as_of_date_v1",
|
||||
"expected_result_mode": "confirmed_balance",
|
||||
"result_mode": "confirmed_balance",
|
||||
"required_filters": {
|
||||
"as_of_date": "2016-05-31",
|
||||
"period_from": "2016-05-01",
|
||||
"period_to": "2016-05-31",
|
||||
},
|
||||
"required_answer_shape": "item_list_with_quantity_cost_warehouse_organization",
|
||||
"required_carryover_invariants": [],
|
||||
"required_state_objects": [],
|
||||
"forbidden_capabilities": [],
|
||||
"forbidden_recipes": [],
|
||||
"actual_direct_answer": "На 31.12.2016 на складе подтверждено 4 позиций.",
|
||||
"top_non_empty_lines": ["На 31.12.2016 на складе подтверждено 4 позиций."],
|
||||
"extracted_filters": {
|
||||
"as_of_date": "2016-12-31",
|
||||
"period_from": "2016-01-01",
|
||||
"period_to": "2016-12-31",
|
||||
},
|
||||
"date_scope": {"as_of_date": "2016-12-31"},
|
||||
"focus_object": None,
|
||||
}
|
||||
)
|
||||
|
||||
assert validated["acceptance_status"] == "rejected"
|
||||
assert "wrong_as_of_date" in validated["violated_invariants"]
|
||||
assert "wrong_period_from" in validated["violated_invariants"]
|
||||
assert "wrong_period_to" in validated["violated_invariants"]
|
||||
assert validated["hard_fail"] is True
|
||||
|
||||
|
||||
def test_validate_step_contract_rejects_selected_object_followup_without_focus_object_and_with_wrong_route() -> None:
|
||||
validated = validate_step_contract(
|
||||
{
|
||||
"execution_status": "exact",
|
||||
"status": "exact",
|
||||
"node_role": "critical_child",
|
||||
"analysis_context": {"as_of_date": "2019-03-31"},
|
||||
"expected_intents": ["inventory_purchase_provenance_for_item"],
|
||||
"detected_intent": "inventory_on_hand_as_of_date",
|
||||
"expected_capability": "inventory_purchase_provenance_for_item",
|
||||
"capability_id": "confirmed_inventory_on_hand_as_of_date",
|
||||
"expected_result_mode": "confirmed_balance",
|
||||
"result_mode": "confirmed_balance",
|
||||
"required_filters": {"as_of_date": "2019-03-31"},
|
||||
"required_answer_shape": "direct_supplier_answer_first_then_evidence",
|
||||
"required_carryover_invariants": ["focus_object", "date_scope"],
|
||||
"required_state_objects": [],
|
||||
"forbidden_capabilities": ["confirmed_inventory_on_hand_as_of_date"],
|
||||
"forbidden_recipes": ["address_inventory_on_hand_as_of_date_v1"],
|
||||
"selected_recipe": "address_inventory_on_hand_as_of_date_v1",
|
||||
"actual_direct_answer": "На 31.03.2019 на складе подтверждено 16 позиций.",
|
||||
"top_non_empty_lines": ["На 31.03.2019 на складе подтверждено 16 позиций."],
|
||||
"extracted_filters": {"as_of_date": "2019-03-31"},
|
||||
"date_scope": {"as_of_date": "2019-03-31"},
|
||||
"focus_object": None,
|
||||
}
|
||||
)
|
||||
|
||||
assert validated["acceptance_status"] == "rejected"
|
||||
assert "wrong_intent" in validated["violated_invariants"]
|
||||
assert "wrong_followup_action" in validated["violated_invariants"]
|
||||
assert "forbidden_capability_selected" in validated["violated_invariants"]
|
||||
assert "forbidden_recipe_selected" in validated["violated_invariants"]
|
||||
assert "focus_object_missing" in validated["violated_invariants"]
|
||||
|
||||
|
||||
def test_validate_step_contract_rejects_top_level_noise_as_direct_answer() -> None:
|
||||
validated = validate_step_contract(
|
||||
{
|
||||
"execution_status": "exact",
|
||||
"status": "exact",
|
||||
"node_role": "critical_child",
|
||||
"analysis_context": {"as_of_date": "2019-03-31"},
|
||||
"expected_intents": ["inventory_purchase_provenance_for_item"],
|
||||
"detected_intent": "inventory_purchase_provenance_for_item",
|
||||
"expected_capability": "inventory_purchase_provenance_for_item",
|
||||
"capability_id": "inventory_inventory_purchase_provenance_for_item",
|
||||
"expected_result_mode": "confirmed_balance",
|
||||
"result_mode": "confirmed_balance",
|
||||
"required_filters": {"as_of_date": "2019-03-31"},
|
||||
"required_answer_shape": "direct_supplier_answer_first_then_evidence",
|
||||
"required_carryover_invariants": [],
|
||||
"required_state_objects": [],
|
||||
"forbidden_capabilities": [],
|
||||
"forbidden_recipes": [],
|
||||
"selected_recipe": "address_inventory_purchase_provenance_for_item_v1",
|
||||
"actual_direct_answer": "Статус результата: подтверждено.",
|
||||
"top_non_empty_lines": [
|
||||
"Статус результата: подтверждено.",
|
||||
"Поставщик: Торговый дом \\Союз\\.",
|
||||
],
|
||||
"extracted_filters": {"as_of_date": "2019-03-31"},
|
||||
"date_scope": {"as_of_date": "2019-03-31"},
|
||||
"focus_object": {"object_id": "item:1", "label": "Столешница"},
|
||||
}
|
||||
)
|
||||
|
||||
assert validated["acceptance_status"] == "rejected"
|
||||
assert "direct_answer_missing" in validated["violated_invariants"]
|
||||
assert "top_level_noise_present" in validated["violated_invariants"]
|
||||
|
||||
Reference in New Issue
Block a user