From 7205fdd4d09374138b1ce53f290e30102f8bd398 Mon Sep 17 00:00:00 2001 From: dctouch Date: Tue, 14 Apr 2026 16:03:03 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=A0=D0=A0=D0=9A=D0=95=D0=A1=D0=A2?= =?UTF-8?q?=D0=A0=D0=90=D0=A6=D0=98=D0=AF=20-=D0=97=D0=B0=D1=84=D0=B8?= =?UTF-8?q?=D0=BA=D1=81=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=20=D0=B0?= =?UTF-8?q?=D0=BA=D1=82=D0=B8=D0=B2=D0=BD=D1=8B=D0=B9=20=D1=81=D0=BA=D0=BB?= =?UTF-8?q?=D0=B0=D0=B4=D1=81=D0=BA=D0=BE=D0=B9=20domain=20contract=20?= =?UTF-8?q?=D0=B8=20=D0=BF=D1=80=D0=B8=D0=B2=D1=8F=D0=B7=D0=B0=D1=82=D1=8C?= =?UTF-8?q?=20=D0=BA=20=D0=BD=D0=B5=D0=BC=D1=83=20agent=20canon=20-=20?= =?UTF-8?q?=D0=94=D0=9E=D0=91=D0=90=D0=92=D0=9B=D0=95=D0=9D=20=D0=95=D0=94?= =?UTF-8?q?=D0=98=D0=9D=D0=AB=D0=99=20=D0=A4=D0=90=D0=99=D0=9B=20=D0=9A?= =?UTF-8?q?=D0=9E=D0=9D=D0=A2=D0=95=D0=9A=D0=A1=D0=A2=D0=90=20=D0=97=D0=90?= =?UTF-8?q?=D0=94=D0=90=D0=A7=D0=98=20-=20=D0=BF=D0=BE=20=D1=81=D0=B5?= =?UTF-8?q?=D0=BC=D0=B0=D0=BD=D1=82=D0=B8=D0=BA=D0=B5=20=D0=B8=20=D0=BB?= =?UTF-8?q?=D0=BE=D0=B3=D0=B8=D0=BA=D0=B5=20=D0=B2=20=D0=BE=D0=B4=D0=B8?= =?UTF-8?q?=D0=BD=20=D1=84=D0=B0=D0=B9=D0=BB=20active=5Fdomain=5Fcontract.?= =?UTF-8?q?json=20(line=201)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .codex/agents/domain_analyst.toml | 1 + .codex/agents/orchestrator.toml | 1 + .codex/skills/domain-case-loop/SKILL.md | 1 + .../references/repo_runtime_map.md | 3 + AGENTS.md | 1 + .../orchestration/active_domain_contract.json | 478 ++++++++++++++++++ 6 files changed, 485 insertions(+) create mode 100644 docs/orchestration/active_domain_contract.json diff --git a/.codex/agents/domain_analyst.toml b/.codex/agents/domain_analyst.toml index 1d0371d..5ac166e 100644 --- a/.codex/agents/domain_analyst.toml +++ b/.codex/agents/domain_analyst.toml @@ -8,6 +8,7 @@ You are the strict domain analyst for NDC_1C. You do not write product code. You read: +- docs/orchestration/active_domain_contract.json when present - case_brief.md - baseline_turn.json and rerun_turn.json when available - baseline_output.md / rerun_output.md diff --git a/.codex/agents/orchestrator.toml b/.codex/agents/orchestrator.toml index 332a47e..8d6da59 100644 --- a/.codex/agents/orchestrator.toml +++ b/.codex/agents/orchestrator.toml @@ -11,6 +11,7 @@ Primary repo facts: - The project uses a 1C/MCP-first runtime with address lane + deep lane. - Technical case artifacts should live in artifacts/domain_runs//. - The helper runner is python scripts/domain_case_loop.py. +- When present, `docs/orchestration/active_domain_contract.json` is the single mutable source of truth for the active domain. Your job: 1. Accept one concrete domain case or one linked multi-step domain scenario from the user. diff --git a/.codex/skills/domain-case-loop/SKILL.md b/.codex/skills/domain-case-loop/SKILL.md index baf64e4..97016d4 100644 --- a/.codex/skills/domain-case-loop/SKILL.md +++ b/.codex/skills/domain-case-loop/SKILL.md @@ -28,6 +28,7 @@ This skill packages the standard workflow for iterating on one concrete domain c Read `references/repo_runtime_map.md` before the first real cycle. For follow-up-heavy domains, also read `references/scenario_tree_acceptance_canon.md` before scenario mode, pack mode, or autonomous pack-loop mode. +If `docs/orchestration/active_domain_contract.json` exists, treat it as the single mutable source of truth for the current domain and prefer it over older scattered pool/pack prose docs. Use these repo-native capture paths: - automated capture: `python scripts/domain_case_loop.py run-case ...` diff --git a/.codex/skills/domain-case-loop/references/repo_runtime_map.md b/.codex/skills/domain-case-loop/references/repo_runtime_map.md index 30fefe6..50f7183 100644 --- a/.codex/skills/domain-case-loop/references/repo_runtime_map.md +++ b/.codex/skills/domain-case-loop/references/repo_runtime_map.md @@ -11,6 +11,9 @@ ## Capture strategy for this repo +Current mutable domain source of truth: +- `docs/orchestration/active_domain_contract.json` + 1. Prefer automated capture with: - `python scripts/domain_case_loop.py run-case ...` 2. For linked multi-step scenarios, capture with: diff --git a/AGENTS.md b/AGENTS.md index 4498f27..fc477d1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,6 +16,7 @@ Rules: ## codex_domain_loop - Project-scoped Codex orchestration lives under `.codex/`. - Use `.codex/skills/domain-case-loop` for repeatable domain hardening loops on one concrete case. +- Prefer `docs/orchestration/active_domain_contract.json` as the single mutable source of truth for the current domain/scenario pack; keep the agent canon stable and swap only this file when the active domain changes. - The same skill/launcher also supports multi-step domain scenarios with shared assistant session state under `artifacts/domain_runs//steps/`. - For full domain question pools, use pack mode and aggregate artifacts under `artifacts/domain_runs//scenarios/`. - Preserve current architecture: domain loop may automate capture, review, rerun, and artifact storage, but must not rewrite runtime foundations. diff --git a/docs/orchestration/active_domain_contract.json b/docs/orchestration/active_domain_contract.json new file mode 100644 index 0000000..5b0af55 --- /dev/null +++ b/docs/orchestration/active_domain_contract.json @@ -0,0 +1,478 @@ +{ + "schema_version": "active_domain_contract_v1", + "status": "active", + "domain_id": "inventory_stock_supplier_provenance", + "title": "Складские остатки, происхождение товара и связь с поставщиком", + "source_of_truth_policy": { + "purpose": "single mutable domain source for the current orchestration target", + "switching_rule": "when the project switches to another domain, replace this file instead of rewriting the stable agent canon", + "stable_layers": [ + "AGENTS.md", + ".codex/skills/domain-case-loop", + ".codex/agents/domain_analyst.toml", + ".codex/agents/orchestrator.toml" + ], + "mutable_layer": [ + "docs/orchestration/active_domain_contract.json" + ] + }, + "domain_goal": "Показать остатки товаров на складе на дату, затем по выбранной позиции или по связанному срезу пройти в происхождение товара, поставщика, закупочные документы, возраст закупки и дальнейшую продажу без потери контекста.", + "business_value": [ + "Пользователь должен сначала получить подтвержденный срез остатков на дату.", + "Пользователь должен затем выбрать реальную позицию из ответа и углубиться без ручного переписывания сущности.", + "Система должна понимать не только канонический вопрос, но и разговорные follow-up формулировки.", + "Для сценария склада acceptance определяется не одиночным ответом, а проходимостью дерева от root snapshot к критическим drilldown-веткам." + ], + "observed_anchors": { + "warehouse": "Основной склад", + "organization": "ООО \\Альтернатива Плюс\\", + "historical_as_of_date": "2019-03-31", + "current_as_of_date_example": "2021-09-30", + "focus_item_current": "Диван трехместный", + "focus_item_historical": "Столешница 600*3050*26 дуб ниагара", + "focus_item_small_residue": "Четки Пост (84*117)", + "supplier_candidate": "Торговый дом \\Союз", + "supplier_candidate_alt": "Гамма-мебель, ООО", + "buyer_candidate": "Департамент капитального ремонта города Москвы" + }, + "question_pool": { + "total_questions": 20, + "core_questions_total": 17, + "followup_checkpoints_total": 3, + "questions": [ + { + "question_id": "Q01", + "text": "Какие товары сейчас лежат на складе", + "layer": "root_snapshot", + "node_id": "N01_stock_snapshot", + "role": "root", + "wording_family": "canonical", + "semantic_goal": "получить актуальный item-level срез остатков на складе" + }, + { + "question_id": "Q02", + "text": "Какие товары лежат на складе на дату ...", + "layer": "root_snapshot", + "node_id": "N01_stock_snapshot", + "role": "root", + "wording_family": "canonical", + "semantic_goal": "получить item-level срез остатков на конкретную дату" + }, + { + "question_id": "Q03", + "text": "Из каких товаров состоит остаток по 41 счету", + "layer": "root_snapshot", + "node_id": "N02_account_41_snapshot", + "role": "root_variant", + "wording_family": "canonical", + "semantic_goal": "получить item-level состав остатка по 41.01" + }, + { + "question_id": "Q04", + "text": "Какие товары числятся на 41 счете на дату ...", + "layer": "root_snapshot", + "node_id": "N02_account_41_snapshot", + "role": "root_variant", + "wording_family": "canonical", + "semantic_goal": "получить датированный item-level состав остатка по 41.01" + }, + { + "question_id": "Q05", + "text": "Какие конкретно номенклатуры формируют остаток по складу на дату ...", + "layer": "root_snapshot", + "node_id": "N01_stock_snapshot", + "role": "root_variant", + "wording_family": "canonical", + "semantic_goal": "получить номенклатурный состав складского остатка на дату" + }, + { + "question_id": "Q06", + "text": "От какого поставщика куплен товар ...", + "layer": "selected_item_provenance", + "node_id": "N03_selected_item_supplier", + "role": "critical_child", + "wording_family": "canonical", + "semantic_goal": "получить прямой ответ о поставщике выбранного товара" + }, + { + "question_id": "Q07", + "text": "У какого поставщика были куплены товары, которые сейчас лежат на складе", + "layer": "supplier_overlap", + "node_id": "N06_supplier_overlap_now", + "role": "critical_child", + "wording_family": "canonical", + "semantic_goal": "понять supplier coverage по текущему складскому срезу" + }, + { + "question_id": "Q08", + "text": "По какому поставщику проходит текущий товарный остаток", + "layer": "supplier_overlap", + "node_id": "N06_supplier_overlap_now", + "role": "supporting_child", + "wording_family": "canonical", + "semantic_goal": "атрибутировать текущий остаток по поставщику без потери item/slice контекста" + }, + { + "question_id": "Q09", + "text": "Когда был куплен товар ...", + "layer": "selected_item_provenance", + "node_id": "N04_selected_item_purchase_date", + "role": "critical_child", + "wording_family": "canonical", + "semantic_goal": "получить дату первой/наблюдаемой закупки выбранного товара" + }, + { + "question_id": "Q10", + "text": "По каким документам был куплен товар ...", + "layer": "selected_item_provenance", + "node_id": "N05_selected_item_purchase_documents", + "role": "critical_child", + "wording_family": "canonical", + "semantic_goal": "получить закупочные документы для выбранного товара" + }, + { + "question_id": "Q11", + "text": "Какие товары от поставщика ... сейчас еще лежат на складе", + "layer": "supplier_overlap", + "node_id": "N07_supplier_items_on_stock", + "role": "supporting_child", + "wording_family": "canonical", + "semantic_goal": "получить item-level пересечение supplier -> current stock" + }, + { + "question_id": "Q12", + "text": "Какие товары по состоянию на дату ... были куплены у поставщика ...", + "layer": "supplier_overlap", + "node_id": "N08_supplier_items_on_date", + "role": "supporting_child", + "wording_family": "canonical", + "semantic_goal": "получить датированное item-level пересечение supplier -> stock slice" + }, + { + "question_id": "Q13", + "text": "Какие остатки по товарам на эту дату относятся к старым закупкам", + "layer": "aging", + "node_id": "N09_old_purchase_aging", + "role": "critical_child", + "wording_family": "followup_date_carryover", + "semantic_goal": "показать item-level старые закупки в рамках уже выбранной даты, а не на текущий момент" + }, + { + "question_id": "Q14", + "text": "Какие товары сейчас висят в остатке без понятной привязки к поставщику", + "layer": "aging", + "node_id": "N10_unresolved_supplier_link", + "role": "supporting_child", + "wording_family": "canonical", + "semantic_goal": "найти остатки без надежной supplier attribution" + }, + { + "question_id": "Q15", + "text": "Есть ли остатки товара, которые закупались очень давно", + "layer": "aging", + "node_id": "N09_old_purchase_aging", + "role": "supporting_child", + "wording_family": "canonical", + "semantic_goal": "показать very-old stock в item-level виде" + }, + { + "question_id": "Q16", + "text": "Кому был продан товар ...", + "layer": "sale_trace", + "node_id": "N11_selected_item_buyer", + "role": "critical_child", + "wording_family": "canonical", + "semantic_goal": "получить покупателя выбранного товара" + }, + { + "question_id": "Q17", + "text": "Через какие документы прошел путь товара: закупка -> склад -> продажа", + "layer": "sale_trace", + "node_id": "N12_purchase_to_sale_chain", + "role": "critical_child", + "wording_family": "canonical", + "semantic_goal": "получить полную документальную цепочку purchase -> stock -> sale" + }, + { + "question_id": "Q18", + "text": "Какие товары были куплены у поставщика ... и позже проданы покупателю ...", + "layer": "sale_trace", + "node_id": "N13_supplier_to_buyer_overlap", + "role": "supporting_child", + "wording_family": "canonical", + "semantic_goal": "проверить supplier -> item -> buyer overlap" + }, + { + "question_id": "Q19", + "text": "По выбранному объекту \"...\": кто это поставил нам", + "layer": "selected_item_provenance", + "node_id": "N03_selected_item_supplier", + "role": "critical_child", + "wording_family": "ui_selected_object_colloquial", + "semantic_goal": "проверить, что selected-object follow-up и разговорная supplier-фраза идут в exact provenance contour" + }, + { + "question_id": "Q20", + "text": "По выбранному объекту \"...\": по каким документам это купили", + "layer": "selected_item_provenance", + "node_id": "N05_selected_item_purchase_documents", + "role": "critical_child", + "wording_family": "ui_selected_object_colloquial", + "semantic_goal": "проверить selected-object follow-up в закупочные документы без ручного переписывания item" + } + ] + }, + "wording_families": [ + { + "family_id": "canonical", + "description": "нормальная каноническая формулировка доменного вопроса" + }, + { + "family_id": "colloquial", + "description": "разговорная или короткая пользовательская формулировка" + }, + { + "family_id": "ui_selected_object", + "description": "follow-up, собранный через выбор объекта из ответа" + }, + { + "family_id": "ui_selected_object_colloquial", + "description": "выбранный объект + разговорная формулировка drilldown-вопроса" + }, + { + "family_id": "followup_date_carryover", + "description": "follow-up с фразой `на эту дату` или `на ту дату`, где дата обязана тянуться из предыдущего шага" + } + ], + "scenario_tree": { + "root_nodes": [ + { + "node_id": "N01_stock_snapshot", + "title": "Складской snapshot на дату", + "covers_question_ids": ["Q01", "Q02", "Q05"], + "expected_intents": ["inventory_on_hand_as_of_date"], + "expected_answer_shape": "item_list_with_quantity_cost_warehouse_organization", + "required_wording_families": ["canonical", "colloquial"], + "children": ["N03_selected_item_supplier", "N06_supplier_overlap_now", "N09_old_purchase_aging"] + }, + { + "node_id": "N02_account_41_snapshot", + "title": "Состав остатка по 41.01 на дату", + "covers_question_ids": ["Q03", "Q04"], + "expected_intents": ["inventory_on_hand_as_of_date"], + "expected_answer_shape": "item_list_with_account_41_scope", + "required_wording_families": ["canonical", "colloquial"], + "children": ["N03_selected_item_supplier", "N11_selected_item_buyer"] + } + ], + "critical_nodes": [ + { + "node_id": "N03_selected_item_supplier", + "title": "Поставщик выбранного товара", + "covers_question_ids": ["Q06", "Q19"], + "expected_intents": ["inventory_purchase_provenance_for_item"], + "expected_answer_shape": "direct_supplier_answer_first_then_evidence", + "required_wording_families": ["canonical", "colloquial", "ui_selected_object", "ui_selected_object_colloquial"], + "required_carryover_invariants": ["selected_object", "date_scope", "warehouse_scope", "organization_scope"], + "children": ["N04_selected_item_purchase_date", "N05_selected_item_purchase_documents", "N09_old_purchase_aging"] + }, + { + "node_id": "N04_selected_item_purchase_date", + "title": "Дата закупки выбранного товара", + "covers_question_ids": ["Q09"], + "expected_intents": ["inventory_purchase_provenance_for_item"], + "expected_answer_shape": "direct_date_answer_first_then_evidence", + "required_wording_families": ["canonical", "ui_selected_object"], + "required_carryover_invariants": ["selected_object", "date_scope"] + }, + { + "node_id": "N05_selected_item_purchase_documents", + "title": "Закупочные документы выбранного товара", + "covers_question_ids": ["Q10", "Q20"], + "expected_intents": ["inventory_purchase_documents_for_item"], + "expected_answer_shape": "document_list_for_selected_item", + "required_wording_families": ["canonical", "ui_selected_object", "ui_selected_object_colloquial"], + "required_carryover_invariants": ["selected_object", "date_scope", "warehouse_scope"] + }, + { + "node_id": "N09_old_purchase_aging", + "title": "Старые закупки по остаткам на выбранную дату", + "covers_question_ids": ["Q13", "Q15"], + "expected_intents": ["inventory_aging_by_purchase_date"], + "expected_answer_shape": "item_level_oldest_first_stock_aging_list", + "required_wording_families": ["canonical", "followup_date_carryover"], + "required_carryover_invariants": ["date_scope", "warehouse_scope", "organization_scope"], + "ordering_rule": "oldest_first" + }, + { + "node_id": "N11_selected_item_buyer", + "title": "Покупатель выбранного товара", + "covers_question_ids": ["Q16"], + "expected_intents": ["inventory_sale_trace_for_item"], + "expected_answer_shape": "direct_buyer_answer_first_then_evidence", + "required_wording_families": ["canonical", "ui_selected_object"], + "required_carryover_invariants": ["selected_object", "date_scope"] + }, + { + "node_id": "N12_purchase_to_sale_chain", + "title": "Документальная цепочка purchase -> stock -> sale", + "covers_question_ids": ["Q17"], + "expected_intents": ["inventory_purchase_to_sale_chain"], + "expected_answer_shape": "ordered_chain_with_purchase_stock_sale_documents", + "required_wording_families": ["canonical", "ui_selected_object"], + "required_carryover_invariants": ["selected_object", "date_scope"] + } + ], + "supporting_nodes": [ + { + "node_id": "N06_supplier_overlap_now", + "title": "Supplier overlap по текущему stock slice", + "covers_question_ids": ["Q07", "Q08"], + "expected_intents": ["inventory_supplier_stock_overlap_as_of_date"], + "expected_answer_shape": "supplier_to_stock_slice_summary" + }, + { + "node_id": "N07_supplier_items_on_stock", + "title": "Какие товары поставщика лежат на складе сейчас", + "covers_question_ids": ["Q11"], + "expected_intents": ["inventory_supplier_stock_overlap_as_of_date"], + "expected_answer_shape": "item_list_filtered_by_supplier" + }, + { + "node_id": "N08_supplier_items_on_date", + "title": "Какие товары поставщика были в остатке на дату", + "covers_question_ids": ["Q12"], + "expected_intents": ["inventory_supplier_stock_overlap_as_of_date"], + "expected_answer_shape": "dated_item_list_filtered_by_supplier" + }, + { + "node_id": "N10_unresolved_supplier_link", + "title": "Остатки без понятной supplier attribution", + "covers_question_ids": ["Q14"], + "expected_intents": ["inventory_supplier_stock_overlap_as_of_date"], + "expected_answer_shape": "item_list_with_unresolved_supplier_linkage" + }, + { + "node_id": "N13_supplier_to_buyer_overlap", + "title": "Supplier -> item -> buyer overlap", + "covers_question_ids": ["Q18"], + "expected_intents": ["inventory_purchase_to_sale_chain"], + "expected_answer_shape": "confirmed_or_honestly_limited_supplier_item_buyer_overlap" + } + ], + "critical_edges": [ + { + "edge_id": "E01_snapshot_to_selected_item_supplier", + "from_node": "N01_stock_snapshot", + "to_node": "N03_selected_item_supplier", + "transition_type": "selected_object_drilldown", + "primary_user_path": true, + "required_carryover_invariants": ["selected_object", "date_scope", "warehouse_scope", "organization_scope"], + "failure_means": "домен не принят, даже если root snapshot уже exact" + }, + { + "edge_id": "E02_selected_item_supplier_to_purchase_documents", + "from_node": "N03_selected_item_supplier", + "to_node": "N05_selected_item_purchase_documents", + "transition_type": "selected_object_deeper_trace", + "primary_user_path": true, + "required_carryover_invariants": ["selected_object", "date_scope"], + "failure_means": "сломано углубление из поставщика в документы закупки" + }, + { + "edge_id": "E03_snapshot_or_provenance_to_aging", + "from_node": "N01_stock_snapshot", + "to_node": "N09_old_purchase_aging", + "transition_type": "date_sensitive_followup", + "primary_user_path": true, + "required_carryover_invariants": ["date_scope", "warehouse_scope", "organization_scope"], + "ordering_rule": "oldest_first", + "failure_means": "сломано понимание `на эту дату` или неверная answer shape по старым закупкам" + }, + { + "edge_id": "E04_snapshot_to_sale_trace", + "from_node": "N02_account_41_snapshot", + "to_node": "N11_selected_item_buyer", + "transition_type": "historical_selected_object_drilldown", + "primary_user_path": false, + "required_carryover_invariants": ["selected_object", "date_scope"], + "failure_means": "sale-trace ветка незакрыта" + } + ], + "primary_user_paths": [ + { + "path_id": "P01_snapshot_to_supplier", + "nodes": ["N01_stock_snapshot", "N03_selected_item_supplier"], + "description": "Самый типичный живой путь: получить список остатков, выбрать позицию, спросить кто поставил." + }, + { + "path_id": "P02_snapshot_to_supplier_to_documents", + "nodes": ["N01_stock_snapshot", "N03_selected_item_supplier", "N05_selected_item_purchase_documents"], + "description": "После поставщика пользователь углубляется в закупочные документы." + }, + { + "path_id": "P03_snapshot_to_aging_on_same_date", + "nodes": ["N01_stock_snapshot", "N09_old_purchase_aging"], + "description": "Пользователь спрашивает про старые закупки на ту же дату, что и исходный snapshot." + } + ] + }, + "acceptance_contract": { + "acceptance_unit": "scenario_tree", + "do_not_accept_if": [ + "работает только root snapshot, но ломается critical selected-object edge", + "работает только canonical wording, но ломается colloquial или ui_selected_object wording", + "теряется date_scope на follow-up с `на эту дату` или `на ту дату`", + "ответ меняет business object, например вместо item-level ответа отдаёт dump документов", + "нарушается ordering semantics, например `старые закупки` идут не oldest-first" + ], + "required_green_for_acceptance": [ + "root nodes", + "critical edges on primary_user_paths", + "canonical coverage on critical nodes", + "colloquial coverage on critical nodes", + "ui_selected_object coverage where UI supports object selection" + ], + "required_defect_classes": [ + "semantic_understanding_gap", + "edge_carryover_gap", + "answer_shape_mismatch", + "ordering_semantics_mismatch", + "runtime_capability_gap", + "loop_coverage_gap" + ], + "minimum_score_rule": "accepted only if analyst score >= 80 and no unresolved P0 remains" + }, + "known_failure_patterns_to_watch": [ + { + "pattern_id": "F01_selected_object_colloquial_supplier", + "symptom": "selected-object follow-up `кто это поставил нам` падает в clarification instead of provenance exact route", + "defect_class": "semantic_understanding_gap" + }, + { + "pattern_id": "F02_numeric_tail_account_poisoning", + "symptom": "numeric fragments inside item names such as `600*3050*26` contaminate account/domain inference", + "defect_class": "semantic_understanding_gap" + }, + { + "pattern_id": "F03_date_carryover_loss", + "symptom": "follow-up `на эту дату` loses the originating date and silently switches to current date", + "defect_class": "edge_carryover_gap" + }, + { + "pattern_id": "F04_answer_shape_downgrade", + "symptom": "user asks for item-level stock aging but runtime returns raw purchase documents", + "defect_class": "answer_shape_mismatch" + }, + { + "pattern_id": "F05_oldest_first_violation", + "symptom": "`старые закупки` are listed newest-first or in another non-business order", + "defect_class": "ordering_semantics_mismatch" + } + ], + "legacy_references": [ + "docs/orchestration/domain_inventory_stock_supplier_trace.md", + "docs/orchestration/domain_inventory_stock_supplier_trace_pool.md", + "docs/orchestration/domain_inventory_stock_supplier_trace_pack.json" + ] +}