Настроить phase106 и детекторы агентного лупа
This commit is contained in:
parent
e4eac8e465
commit
631391f47a
|
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
"schema_version": "domain_scenario_pack_v1",
|
"schema_version": "domain_scenario_pack_v1",
|
||||||
"pack_id": "active_phase104_generic_role_tail_anchor_hygiene_20260615",
|
"pack_id": "active_phase106_profit_cashflow_margin_next_step_20260615",
|
||||||
"domain": "address_phase104_generic_role_tail_anchor_hygiene",
|
"domain": "address_phase106_profit_cashflow_margin_next_step",
|
||||||
"runtime_domain": "business_overview_role_tail_anchor_hygiene",
|
"runtime_domain": "business_overview_profit_cashflow_margin_boundary",
|
||||||
"title": "Generic role-tail anchor hygiene",
|
"title": "Profit, cashflow, margin and next-check boundary",
|
||||||
"description": "Active slice for the autonomous agent loop: broad company overview wording may mention customer/supplier roles, but generic role tails must not become counterparty anchors or poison later bank/counterparty drilldowns.",
|
"description": "Active slice for the autonomous agent loop: colloquial earnings wording must be answered as checked cashflow/accounting evidence with honest profit boundaries, then pivot safely into товарная маржа and concrete next checks.",
|
||||||
"status": "active",
|
"status": "active",
|
||||||
"source_of_truth_policy": {
|
"source_of_truth_policy": {
|
||||||
"purpose": "single mutable domain source for the current orchestration target",
|
"purpose": "single mutable domain source for the current orchestration target",
|
||||||
|
|
@ -21,46 +21,54 @@
|
||||||
},
|
},
|
||||||
"analysis_context": {
|
"analysis_context": {
|
||||||
"as_of_date": "2026-06-15",
|
"as_of_date": "2026-06-15",
|
||||||
"source": "phase104_generic_role_tail_anchor_hygiene_after_value_flow_p06"
|
"source": "phase106_after_phase104_role_tail_autorun_persistence",
|
||||||
|
"known_previous_anchors": [
|
||||||
|
"hm_business_overview_cashflow_limits_20260602_p4",
|
||||||
|
"hm_business_profile_evaluation_limits_p3",
|
||||||
|
"agent_margin_profitability_reliability_20260615_p12_detector_scope",
|
||||||
|
"phase104_generic_role_tail_anchor_hygiene_20260615_p04_loop"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"target_score": 88,
|
"target_score": 88,
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"main_organization": "ООО Альтернатива Плюс",
|
"main_organization": "ООО Альтернатива Плюс",
|
||||||
"control_year": "2020",
|
"control_year": "2020"
|
||||||
"bank_counterparty": "СБЕРБАНК",
|
|
||||||
"svk_counterparty": "Группа СВК"
|
|
||||||
},
|
},
|
||||||
"issue_codes_under_test": [
|
"issue_codes_under_test": [
|
||||||
"bank_counterparty_misclassified_as_business_partner",
|
"cashflow_misreported_as_clean_profit",
|
||||||
"technical_garbage_in_answer",
|
"margin_domain_leak_accounting_route",
|
||||||
"business_next_step_missing"
|
"business_next_step_missing",
|
||||||
|
"technical_garbage_in_answer"
|
||||||
],
|
],
|
||||||
"detectors_under_test": [
|
"detectors_under_test": [
|
||||||
"bank_counterparty_boundary_required",
|
|
||||||
"runtime_tokens_in_user_answer",
|
"runtime_tokens_in_user_answer",
|
||||||
"capability_ids_in_user_answer",
|
"capability_ids_in_user_answer",
|
||||||
"limited_answer_without_next_action"
|
"limited_answer_without_next_action",
|
||||||
|
"margin_domain_leak_accounting_route",
|
||||||
|
"margin_required_fields_missing",
|
||||||
|
"margin_next_action_missing"
|
||||||
],
|
],
|
||||||
"agent_audit_expectations": {
|
"agent_audit_expectations": {
|
||||||
"semantic_answer_review_first": true,
|
"semantic_answer_review_first": true,
|
||||||
"direct_answer_first": true,
|
"direct_answer_first": true,
|
||||||
"business_utility_required": true,
|
"business_utility_required": true,
|
||||||
"generic_role_tail_must_not_be_anchor": true,
|
"cashflow_not_clean_profit": true,
|
||||||
"bank_role_boundary_required": true,
|
"margin_domain_purity_required": true,
|
||||||
|
"next_action_required_when_limited": true,
|
||||||
"technical_garbage_forbidden": true,
|
"technical_garbage_forbidden": true,
|
||||||
"do_not_accept_if": [
|
"do_not_accept_if": [
|
||||||
"generic role wording such as 'client or supplier' becomes extracted_filters.counterparty",
|
"colloquial earnings wording is answered as confirmed clean profit without evidence",
|
||||||
"the Sberbank follow-up is answered for a stale role-tail instead of Sberbank",
|
"cashflow/net operating flow is silently presented as accounting profit or margin",
|
||||||
"Sberbank is presented as an ordinary customer/supplier without a bank/financial-role caveat",
|
"margin follow-up leaks into bank payments, fixed assets, amortization, or generic accounting route",
|
||||||
"the real supplier prefix for Группа СВК is erased by the role-tail guard",
|
"next-check answer is generic advice without concrete 1C evidence contours",
|
||||||
"final answer leaks route ids, capability ids, runtime enums, or debug payload"
|
"final answer leaks route ids, capability ids, runtime enums, or debug payload"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"scenarios": [
|
"scenarios": [
|
||||||
{
|
{
|
||||||
"scenario_id": "generic_role_tail_anchor_hygiene",
|
"scenario_id": "profit_cashflow_margin_next_step_boundary",
|
||||||
"title": "Role-tail overview, bank drilldown, and real supplier canary",
|
"title": "Colloquial earnings, clean-profit boundary, margin pivot, and next checks",
|
||||||
"description": "Validate that business overview role words stay semantic-only, Sberbank remains a bank-role drilldown, and an explicit supplier prefix still preserves a real counterparty.",
|
"description": "Validate that the assistant handles colloquial earnings wording, refuses to overclaim clean profit, pivots into товарная маржа without wrong-domain leakage, and proposes concrete next 1C checks.",
|
||||||
"steps": [
|
"steps": [
|
||||||
{
|
{
|
||||||
"step_id": "step_01_choose_company_scope",
|
"step_id": "step_01_choose_company_scope",
|
||||||
|
|
@ -86,104 +94,109 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"step_id": "step_02_business_overview_role_tail_not_counterparty",
|
"step_id": "step_02_colloquial_earned_money_2020",
|
||||||
"title": "Business overview role words do not become counterparty anchors",
|
"title": "Colloquial earned-money wording stays bounded",
|
||||||
"question": "Теперь дай взрослый обзор за {{bindings.control_year}} по компании: входящие, исходящие, нетто, топы, но банк в топах отдельно объясни как финансовый поток, если по назначению он не обычный клиент или поставщик.",
|
"question": "скока денег альтернатива заработала за 20 год?",
|
||||||
"depends_on": [
|
"depends_on": [
|
||||||
"step_01_choose_company_scope"
|
"step_01_choose_company_scope"
|
||||||
],
|
],
|
||||||
"expected_intents": [
|
|
||||||
"business_overview"
|
|
||||||
],
|
|
||||||
"semantic_tags": [
|
"semantic_tags": [
|
||||||
"business_overview",
|
"business_overview",
|
||||||
"generic_role_tail_anchor_hygiene",
|
"colloquial_cashflow",
|
||||||
"financial_role_purpose"
|
"cashflow_not_profit"
|
||||||
],
|
],
|
||||||
"required_answer_shape": "direct_answer_first",
|
"required_answer_shape": "direct_answer_first",
|
||||||
"forbidden_filter_keys": [
|
|
||||||
"counterparty"
|
|
||||||
],
|
|
||||||
"forbidden_filter_values": {
|
|
||||||
"counterparty": [
|
|
||||||
"или поставщик",
|
|
||||||
"поставщик",
|
|
||||||
"клиент",
|
|
||||||
"обычный клиент",
|
|
||||||
"обычный клиент или поставщик"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"required_answer_patterns_all": [
|
"required_answer_patterns_all": [
|
||||||
"(?i)2020|компан|организац",
|
"(?i)2020|20\\s*год",
|
||||||
"(?i)вход|поступ|исход|списан|нетто",
|
"(?i)поступ|входящ|денег|заработ",
|
||||||
"(?i)банк|сбербанк|финансов",
|
"(?i)не.*чист.*прибыл|не.*прибыл|прибыл.*не подтвержд|это.*не.*прибыл"
|
||||||
"(?i)не.*обычн.*клиент|не.*обычн.*поставщик|не.*выручк|не.*закупк|назначен"
|
|
||||||
],
|
],
|
||||||
"forbidden_answer_patterns": [
|
"forbidden_answer_patterns": [
|
||||||
"(?i)сбербанк.*обычный поставщик",
|
"(?i)^\\s*Коротко:",
|
||||||
"(?i)сбербанк.*обычный клиент",
|
"(?i)это\\s+чистая\\s+прибыль",
|
||||||
"(?i)чистая прибыль.*точно",
|
"(?i)точно.*прибыл",
|
||||||
"(?i)route_candidate|primitive|planner_|catalog_|snapshot_items|answer_object"
|
"(?i)route_candidate|primitive|planner_|catalog_|snapshot_items|answer_object|capability_id|mcp_discovery"
|
||||||
]
|
],
|
||||||
|
"criticality": "critical"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"step_id": "step_03_sberbank_role_after_role_tail_overview",
|
"step_id": "step_03_clean_profit_followup_boundary",
|
||||||
"title": "Bank-role drilldown still resolves Sberbank after role-tail overview",
|
"title": "Clean-profit follow-up must not convert cashflow into profit",
|
||||||
"question": "А отдельно по {{bindings.bank_counterparty}}У: он для нас клиент, поставщик или финансовый поток? Дай коротко по подтвержденным строкам.",
|
"question": "а это чистая прибыль?",
|
||||||
"depends_on": [
|
"depends_on": [
|
||||||
"step_02_business_overview_role_tail_not_counterparty"
|
"step_02_colloquial_earned_money_2020"
|
||||||
],
|
],
|
||||||
"semantic_tags": [
|
"semantic_tags": [
|
||||||
"bank_like_counterparty",
|
"profitability_boundary",
|
||||||
"financial_role_purpose",
|
"cashflow_not_profit",
|
||||||
"post_overview_anchor_integrity"
|
"followup_boundary"
|
||||||
],
|
],
|
||||||
"required_answer_shape": "direct_answer_first",
|
"required_answer_shape": "direct_answer_first",
|
||||||
"required_filters": {
|
|
||||||
"counterparty": "{{bindings.bank_counterparty}}"
|
|
||||||
},
|
|
||||||
"required_answer_patterns_all": [
|
"required_answer_patterns_all": [
|
||||||
"(?i)сбербанк|банк",
|
"(?i)не.*чист.*прибыл|не.*является.*прибыл|не подтвержд.*прибыл|это.*не.*прибыл",
|
||||||
"(?i)финансов|банковск|кредит|комисс|возврат|назначен|вид операц",
|
"(?i)денежн|поступ|нетто|оборот|cash|себестоим|расход|закрыва"
|
||||||
"(?i)не.*обычн.*клиент|не.*обычн.*поставщик|не.*клиентск.*выручк|нельзя.*читать"
|
|
||||||
],
|
],
|
||||||
"forbidden_answer_patterns": [
|
"forbidden_answer_patterns": [
|
||||||
"(?i)или поставщик",
|
"(?i)^\\s*Коротко:",
|
||||||
"(?i)сбербанк.*обычный поставщик",
|
"(?i)^\\s*да[,\\s]+это.*прибыл",
|
||||||
"(?i)сбербанк.*обычный клиент",
|
"(?i)точно.*чист.*прибыл",
|
||||||
"(?i)route_candidate|primitive|planner_|catalog_|snapshot_items|answer_object"
|
"(?i)route_candidate|primitive|planner_|catalog_|snapshot_items|answer_object|capability_id|mcp_discovery"
|
||||||
]
|
],
|
||||||
|
"criticality": "critical"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"step_id": "step_04_real_supplier_prefix_still_keeps_counterparty",
|
"step_id": "step_04_margin_pivot_keeps_inventory_domain",
|
||||||
"title": "Explicit supplier prefix still preserves a real counterparty",
|
"title": "Margin pivot uses inventory margin contour, not payments or fixed assets",
|
||||||
"question": "А теперь по поставщику {{bindings.svk_counterparty}} за {{bindings.control_year}}: сколько мы ему заплатили и какой общий денежный смысл?",
|
"question": "тогда какую прибыль или маржу можно проверить по товарам за 2020?",
|
||||||
"depends_on": [
|
"depends_on": [
|
||||||
"step_03_sberbank_role_after_role_tail_overview"
|
"step_03_clean_profit_followup_boundary"
|
||||||
],
|
],
|
||||||
"expected_intents": [
|
"expected_intents": [
|
||||||
"value_flow"
|
"inventory_margin_ranking_for_nomenclature"
|
||||||
],
|
],
|
||||||
|
"expected_capability": "inventory_inventory_margin_ranking_for_nomenclature",
|
||||||
|
"expected_recipe": "address_inventory_margin_ranking_for_nomenclature_v1",
|
||||||
"semantic_tags": [
|
"semantic_tags": [
|
||||||
"counterparty_net_cash_flow",
|
"margin_profitability",
|
||||||
"supplier_prefix_canary",
|
"inventory",
|
||||||
"stale_scope_guard"
|
"wrong_domain_trap",
|
||||||
|
"cashflow_to_margin_pivot"
|
||||||
],
|
],
|
||||||
"required_answer_shape": "direct_answer_first",
|
"required_answer_shape": "direct_answer_first",
|
||||||
"required_filters": {
|
"required_answer_patterns_any": [
|
||||||
"counterparty": "{{bindings.svk_counterparty}}"
|
"(?i)марж|валов|выруч|себестоим|номенклатур|товар|не могу подтвердить|не хватает"
|
||||||
},
|
|
||||||
"required_answer_patterns_all": [
|
|
||||||
"(?i)свк|группа",
|
|
||||||
"(?i)2020",
|
|
||||||
"(?i)заплат|исход|списан|получ|поступ|нетто|смысл"
|
|
||||||
],
|
],
|
||||||
"forbidden_answer_patterns": [
|
"forbidden_answer_patterns": [
|
||||||
"(?i)или поставщик",
|
"(?i)амортизац|основн(ые|ых)? средств|объект ОС|банк|оплат[аы]|payment_document|settlement",
|
||||||
"(?i)сбербанк",
|
"(?i)route_candidate|primitive|planner_|catalog_|snapshot_items|answer_object|capability_id|mcp_discovery"
|
||||||
"(?i)уточните организац|какую компанию",
|
],
|
||||||
"(?i)route_candidate|primitive|planner_|catalog_|snapshot_items|answer_object"
|
"criticality": "critical"
|
||||||
]
|
},
|
||||||
|
{
|
||||||
|
"step_id": "step_05_next_checks_are_concrete_1c_contours",
|
||||||
|
"title": "Next checks must be concrete 1C evidence contours",
|
||||||
|
"question": "что дальше проверить, чтобы понять здоровье бизнеса, без гаданий?",
|
||||||
|
"depends_on": [
|
||||||
|
"step_04_margin_pivot_keeps_inventory_domain"
|
||||||
|
],
|
||||||
|
"semantic_tags": [
|
||||||
|
"business_next_step",
|
||||||
|
"evidence_plan",
|
||||||
|
"no_generic_advice"
|
||||||
|
],
|
||||||
|
"required_answer_shape": "direct_answer_first",
|
||||||
|
"required_answer_patterns_all": [
|
||||||
|
"(?i)прибыл|марж|себестоим|финрезульт",
|
||||||
|
"(?i)ндс|налог",
|
||||||
|
"(?i)дебитор|кредитор|долг|расчет",
|
||||||
|
"(?i)склад|остат|оборач|товар"
|
||||||
|
],
|
||||||
|
"forbidden_answer_patterns": [
|
||||||
|
"(?i)^\\s*Коротко:",
|
||||||
|
"(?i)просто.*посмотр|общ.*рекоменд|улучшить маркетинг|нанять|стратег",
|
||||||
|
"(?i)route_candidate|primitive|planner_|catalog_|snapshot_items|answer_object|capability_id|mcp_discovery"
|
||||||
|
],
|
||||||
|
"criticality": "important"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,9 @@
|
||||||
"required_patterns_any": [
|
"required_patterns_any": [
|
||||||
"(?i)(выруч|себестоим|валов|марж|не хватает|не могу подтвердить|не подтвержден|unknown)"
|
"(?i)(выруч|себестоим|валов|марж|не хватает|не могу подтвердить|не подтвержден|unknown)"
|
||||||
],
|
],
|
||||||
|
"artifact_path_include_patterns": [
|
||||||
|
"(?i)steps[\\\\/][^\\\\/]*(?:margin|profitability|марж)"
|
||||||
|
],
|
||||||
"artifact_path_exclude_patterns": [
|
"artifact_path_exclude_patterns": [
|
||||||
"(?i)selected_item",
|
"(?i)selected_item",
|
||||||
"(?i)supplier",
|
"(?i)supplier",
|
||||||
|
|
|
||||||
|
|
@ -228,7 +228,7 @@ class AgentDetectorRunnerTests(unittest.TestCase):
|
||||||
root = Path(tmp)
|
root = Path(tmp)
|
||||||
artifact_dir = root / "run"
|
artifact_dir = root / "run"
|
||||||
write_text(
|
write_text(
|
||||||
artifact_dir / "scenarios" / "margin_root" / "steps" / "step_01" / "output.md",
|
artifact_dir / "scenarios" / "profit_cashflow_boundary" / "steps" / "step_01_margin_root" / "output.md",
|
||||||
"Top margin item: revenue 100, cogs 60, gross profit 40, margin 40%.",
|
"Top margin item: revenue 100, cogs 60, gross profit 40, margin 40%.",
|
||||||
)
|
)
|
||||||
write_text(
|
write_text(
|
||||||
|
|
@ -240,6 +240,15 @@ class AgentDetectorRunnerTests(unittest.TestCase):
|
||||||
/ "output.md",
|
/ "output.md",
|
||||||
"Supplier for the selected item: Example LLC.",
|
"Supplier for the selected item: Example LLC.",
|
||||||
)
|
)
|
||||||
|
write_text(
|
||||||
|
artifact_dir
|
||||||
|
/ "scenarios"
|
||||||
|
/ "business_health"
|
||||||
|
/ "steps"
|
||||||
|
/ "step_05_next_checks"
|
||||||
|
/ "output.md",
|
||||||
|
"Check profit, debt, inventory, taxes, and customer concentration next.",
|
||||||
|
)
|
||||||
registry_path = root / "detector_registry.json"
|
registry_path = root / "detector_registry.json"
|
||||||
issue_catalog_path = root / "issue_catalog.json"
|
issue_catalog_path = root / "issue_catalog.json"
|
||||||
write_json(
|
write_json(
|
||||||
|
|
@ -255,6 +264,7 @@ class AgentDetectorRunnerTests(unittest.TestCase):
|
||||||
"inputs": ["output.md"],
|
"inputs": ["output.md"],
|
||||||
"check": {
|
"check": {
|
||||||
"required_patterns_any": ["(?i)(revenue|cogs|gross profit|margin)"],
|
"required_patterns_any": ["(?i)(revenue|cogs|gross profit|margin)"],
|
||||||
|
"artifact_path_include_patterns": ["(?i)steps[\\\\/][^\\\\/]*(?:margin|profitability)"],
|
||||||
"artifact_path_exclude_patterns": ["(?i)selected_item"],
|
"artifact_path_exclude_patterns": ["(?i)selected_item"],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -275,7 +285,7 @@ class AgentDetectorRunnerTests(unittest.TestCase):
|
||||||
self.assertEqual(results["results"][0]["status"], "pass")
|
self.assertEqual(results["results"][0]["status"], "pass")
|
||||||
evidence_paths = [item["path"] for item in results["results"][0]["evidence"]]
|
evidence_paths = [item["path"] for item in results["results"][0]["evidence"]]
|
||||||
self.assertEqual(len(evidence_paths), 1)
|
self.assertEqual(len(evidence_paths), 1)
|
||||||
self.assertIn("margin_root", evidence_paths[0])
|
self.assertIn("step_01_margin_root", evidence_paths[0])
|
||||||
|
|
||||||
def test_composite_detector_fails_after_child_detector_fails(self) -> None:
|
def test_composite_detector_fails_after_child_detector_fails(self) -> None:
|
||||||
with tempfile.TemporaryDirectory() as tmp:
|
with tempfile.TemporaryDirectory() as tmp:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue