ОРРКЕСТРАЦИЯ - Оркестрация домена: запретить ложный accepted при живых repair targets
This commit is contained in:
@@ -7,10 +7,12 @@ from pathlib import Path
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
||||
|
||||
from scripts.domain_case_loop import (
|
||||
build_deterministic_repair_targets,
|
||||
build_scenario_acceptance_matrix,
|
||||
carry_forward_analysis_context,
|
||||
derive_pack_final_status,
|
||||
evaluate_analyst_gate,
|
||||
evaluate_deterministic_loop_gate,
|
||||
load_scenario_pack,
|
||||
merge_scenario_date_scope,
|
||||
validate_step_contract,
|
||||
@@ -499,3 +501,112 @@ def test_validate_step_contract_rejects_top_level_noise_as_direct_answer() -> No
|
||||
assert validated["acceptance_status"] == "rejected"
|
||||
assert "direct_answer_missing" in validated["violated_invariants"]
|
||||
assert "top_level_noise_present" in validated["violated_invariants"]
|
||||
|
||||
|
||||
def test_build_deterministic_repair_targets_marks_followup_router_gap_as_p0() -> None:
|
||||
repair_targets = build_deterministic_repair_targets(
|
||||
{"pack_id": "demo_pack", "domain": "inventory_stock", "final_status": "partial"},
|
||||
[
|
||||
{
|
||||
"scenario_id": "inventory_selected_item_provenance",
|
||||
"title": "Selected item provenance",
|
||||
"artifact_dir": "artifacts/domain_runs/demo/scenarios/inventory_selected_item_provenance",
|
||||
"scenario_state": {
|
||||
"step_outputs": {
|
||||
"step_02_supplier": {
|
||||
"step_id": "step_02_supplier",
|
||||
"question_resolved": 'По выбранному объекту "Столешница": кто поставил',
|
||||
"execution_status": "exact",
|
||||
"acceptance_status": "rejected",
|
||||
"reply_type": "factual",
|
||||
"selected_recipe": "address_inventory_on_hand_as_of_date_v1",
|
||||
"capability_id": "confirmed_inventory_on_hand_as_of_date",
|
||||
"violated_invariants": [
|
||||
"wrong_followup_action",
|
||||
"focus_object_missing",
|
||||
"forbidden_capability_selected",
|
||||
],
|
||||
"warnings": [],
|
||||
"hard_fail": True,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
)
|
||||
|
||||
assert repair_targets["target_count"] == 1
|
||||
target = repair_targets["targets"][0]
|
||||
assert target["severity"] == "P0"
|
||||
assert target["problem_type"] == "followup_action_resolution_gap"
|
||||
assert "followup_action_resolution_gap" in target["root_cause_layers"]
|
||||
assert "object_memory_gap" in target["root_cause_layers"]
|
||||
assert "addressIntentResolver.ts" in " ".join(target["candidate_files"])
|
||||
|
||||
|
||||
def test_build_deterministic_repair_targets_marks_anchor_gap_as_p1() -> None:
|
||||
repair_targets = build_deterministic_repair_targets(
|
||||
{"pack_id": "demo_pack", "domain": "inventory_stock", "final_status": "partial"},
|
||||
[
|
||||
{
|
||||
"scenario_id": "inventory_sale_trace",
|
||||
"title": "Sale trace",
|
||||
"artifact_dir": "artifacts/domain_runs/demo/scenarios/inventory_sale_trace",
|
||||
"scenario_state": {
|
||||
"step_outputs": {
|
||||
"step_02_selected_item_buyer_ui": {
|
||||
"step_id": "step_02_selected_item_buyer_ui",
|
||||
"question_resolved": 'По выбранному объекту "Шкаф": кому был продан товар',
|
||||
"execution_status": "partial",
|
||||
"acceptance_status": "rejected",
|
||||
"reply_type": "partial_coverage",
|
||||
"fallback_type": "partial",
|
||||
"mcp_call_status": "materialized_but_not_anchor_matched",
|
||||
"selected_recipe": "address_inventory_sale_trace_for_item_v1",
|
||||
"capability_id": "inventory_inventory_sale_trace_for_item",
|
||||
"violated_invariants": [],
|
||||
"warnings": [],
|
||||
"hard_fail": False,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
)
|
||||
|
||||
assert repair_targets["target_count"] == 1
|
||||
target = repair_targets["targets"][0]
|
||||
assert target["severity"] == "P1"
|
||||
assert target["problem_type"] == "domain_anchor_gap"
|
||||
assert target["root_cause_layers"] == ["domain_anchor_gap"]
|
||||
assert "addressQueryService.ts" in " ".join(target["candidate_files"])
|
||||
|
||||
|
||||
def test_evaluate_deterministic_loop_gate_rejects_partial_pack_even_without_targets() -> None:
|
||||
gate_ok, reason = evaluate_deterministic_loop_gate(
|
||||
{"final_status": "partial"},
|
||||
{"severity_counts": {"P0": 0, "P1": 0}},
|
||||
)
|
||||
|
||||
assert gate_ok is False
|
||||
assert reason == "pack_final_status=partial"
|
||||
|
||||
|
||||
def test_evaluate_deterministic_loop_gate_rejects_remaining_p1_targets() -> None:
|
||||
gate_ok, reason = evaluate_deterministic_loop_gate(
|
||||
{"final_status": "accepted"},
|
||||
{"severity_counts": {"P0": 0, "P1": 2}},
|
||||
)
|
||||
|
||||
assert gate_ok is False
|
||||
assert reason == "repair_targets_remaining=P0:0,P1:2"
|
||||
|
||||
|
||||
def test_evaluate_deterministic_loop_gate_accepts_clean_pack_without_remaining_p0_p1() -> None:
|
||||
gate_ok, reason = evaluate_deterministic_loop_gate(
|
||||
{"final_status": "accepted"},
|
||||
{"severity_counts": {"P0": 0, "P1": 0, "warning": 1}},
|
||||
)
|
||||
|
||||
assert gate_ok is True
|
||||
assert reason == "deterministic_gate_passed"
|
||||
|
||||
Reference in New Issue
Block a user