АРЧ - Усилить root-frame возврат, memory recap и colloquial provenance follow-up

This commit is contained in:
2026-04-15 20:34:21 +03:00
parent f911f9893b
commit 8056bdfaf2
16 changed files with 2032 additions and 21 deletions
@@ -0,0 +1,206 @@
# Follow-up Context + Root Pivot Audit (2026-04-15)
Дата: 2026-04-15
Статус: `active audit note`
Источник прогона: `C:\Users\DCTOUCH\Desktop\test.txt`
## 1. Зачем этот документ
Этот note фиксирует, что именно подтвердил живой прогон с appended audit, что в исходном разборе нужно скорректировать, и как это соотносится с уже внедренным bounded fix:
- `root_context_only` carryover при pivot из inventory drilldown в налоговый/смежный учетный домен;
- сохранение baseline inventory selected-object маршрутов;
- отсутствие архитектурного конфликта с текущими rails.
Цель документа не переписать общий план, а зафиксировать фактический срез по одному реальному диалогу, чтобы следующие правки не лечили неверную причину.
## 2. Что подтверждено прогоном
### 2.1. VAT root-query работает как capability
Стартовый запрос про прогноз НДС на март 2020 отработал корректно:
- `detected_intent = vat_payable_forecast`
- `selected_recipe = address_vat_payable_forecast_v1`
- ответ построен в address lane, а не через chat/deep fallback
Это важно, потому что базовый VAT route в этом прогоне не деградировал.
### 2.2. Meta follow-up по VAT сломан по answer policy
Запрос `это много или мало?` не получил новый evaluative answer shape. Вместо этого ассистент повторил почти весь предыдущий factual VAT answer.
Подтвержденные симптомы:
- `followup_context_applied = true`
- `previous_intent = vat_payable_forecast`
- `target_intent = unknown`
- route при этом остался в address lane
Вывод:
- поломка не в data retrieval;
- поломка в policy для meta follow-up поверх успешного финансового ответа.
### 2.3. Есть leakage VAT frame в новый inventory root-query
На запрос `остаток на складе за май 2020` система все равно несет хвост VAT-сценария:
- `previous_intent = vat_payable_forecast`
- `target_intent = inventory_on_hand_as_of_date`
- `intent_selection_mode = carry_previous_intent`
При этом итоговый inventory intent все же распознается правильно, но сам факт такого carryover является архитектурно неправильным. Новый root-query не должен стартовать с хвостом чужого домена.
### 2.4. Multiple-organization clarification в этом прогоне работает правильно
После вопроса `какая база подключена ?` система ушла в `assistant_data_scope_query_detected`, показала 3 организации и не выбрала активную организацию самовольно.
На первом inventory root-query без организации система корректно вернула clarification:
- `organization_clarification_required`
- `multiple_known_organizations_detected`
После ответа `альтернатива` активная организация была зафиксирована как:
- `organization_grounded_from_scope_candidates`
Это важная корректировка исходного разбора: в данном прогоне проблема не в преждевременном выборе организации из наблюдаемых строк.
### 2.5. Selected-object sale trace маршрутизируется, но может честно вернуться empty
Запрос по выбранной позиции `кому продали` был правильно классифицирован:
- `detected_intent = inventory_sale_trace_for_item`
- `selected_recipe = address_inventory_sale_trace_for_item_v1`
Но retrieval вернул:
- `limited_reason_category = empty_match`
- `mcp_call_status = no_raw_rows`
Это означает:
- classification и follow-up routing для этого шага в прогоне живы;
- ответ не найден в доступном execution contour;
- данный шаг сам по себе не доказывает, что orchestration сломан.
### 2.6. Short follow-up после limited sale step теряет selected-object continuity
Следующий короткий вопрос `а купили у кого` уже не продолжил selected-object inventory chain. Он ушел в living chat:
- `tool_gate_decision = skip_address_lane`
- `tool_gate_reason = non_domain_query_indexed`
- `followup_context_detected = false`
Это и есть реальный continuity incident в конце цепочки.
## 3. Что в исходном разборе нужно поправить
### 3.1. Нельзя утверждать, что этот прогон сломан из-за авто-grounding организации из observed rows
В `test.txt` не подтверждается `organization_grounded_from_observed_rows`. По этому диалогу организация была:
1. сначала явно не выбрана;
2. затем корректно запрошена через clarification;
3. затем выбрана пользователем;
4. затем grounded из scope candidates.
Следовательно, в данном прогоне root cause не в org policy.
### 3.2. Пустой sale trace не равен провалу intent-routing
`empty_match` по sale trace нельзя автоматически считать провалом follow-up architecture. В этом кейсе route выбран корректно; проблема либо в данных, либо в доступном документном/проводочном контуре.
### 3.3. Главный continuity bug здесь не на шаге `кому продали`, а на шаге `а купили у кого`
Пока selected-object sale trace хотя бы доходит до exact capability, короткий follow-up после ограниченного результата уже не доходит даже до address lane. Именно это место нужно держать как следующий incident.
## 4. Соотношение с уже внедренным bounded fix
### 4.1. Что уже закрыто чисто
В runtime уже внедрен узкий guard:
- при pivot из inventory drilldown в foreign accounting domain не тащить selected item;
- сохранять только root context (`organization`, `warehouse`, `as_of_date`, `period_from`, `period_to`);
- маркировать carryover как `root_context_only`.
Этот fix архитектурно совместим с текущими rails, потому что:
- не переписывает state model;
- не ломает inventory selected-object цепочки внутри inventory domain;
- не меняет execution semantics exact routes;
- ограничивает только cross-domain contamination.
### 4.2. Что этот прогон показывает поверх уже закрытого
Прогон из `test.txt` показывает еще три отдельные задачи, которые не конфликтуют с `root_context_only` fix и должны решаться отдельно:
1. `meta_followup_answer_policy`
VAT/налоговые meta follow-up типа `это много или мало?` должны выдавать evaluative short answer, а не replay предыдущего factual summary.
2. `root_domain_pivot_resets_previous_intent`
Новый inventory root-query после VAT/налогового домена не должен нести `previous_intent = vat_payable_forecast`.
3. `selected_object_continuity_after_limited_result`
Short follow-up после limited selected-object answer не должен выпадать в `non_domain_query_indexed`, если последний успешный/ограниченный шаг был inventory drilldown по выбранной позиции.
4. `invalid_entity_extraction_guard`
Временной кусок `за май` не должен попадать в `warehouse`.
## 5. Что нельзя делать по итогам этого прогона
1. Нельзя откатывать или ослаблять `root_context_only` fix.
Этот прогон не опровергает его; он показывает другой класс дефектов.
2. Нельзя лечить root leakage полным отключением follow-up carryover.
Это сломает рабочие selected-object цепочки в inventory.
3. Нельзя интерпретировать любой `empty_match` как classifier failure.
Нужно различать:
- route selected correctly;
- retrieval found no rows;
- follow-up context lost before route selection.
4. Нельзя лечить `warehouse = "за май"` через новые хардкодные словари по конкретным месяцам.
Нужен entity admissibility guard для warehouse anchor.
## 6. Приоритетный backlog после аудита
### P0
1. Запретить replay полного factual ответа на evaluative/meta follow-up поверх VAT/tax summary.
2. Ввести reset previous intent на root-domain pivot из VAT/tax в inventory root query.
3. Вернуть address-lane continuity для short purchase follow-up после limited selected-object inventory step.
### P1
1. Отбрасывать временные фрагменты как invalid warehouse anchor.
2. Развести в acceptance:
- `route matched but empty`
- `route not matched`
- `follow-up continuity lost`
## 7. Обязательные regression checks
1. `VAT factual -> это много или мало?`
Ожидание: короткая evaluative реплика, без replay исходного factual summary.
2. `VAT root -> inventory root`
Ожидание: новый root query не наследует `previous_intent` из чужого домена.
3. `inventory selected item -> sale empty_match -> а купили у кого`
Ожидание: address lane не теряется, selected object продолжает жить.
4. `остаток на складе за май 2020`
Ожидание: `warehouse` не заполняется значением `за май`.
## 8. Итог
По этому прогону архитектурная картина такая:
- узкий fix `root_context_only` был правильным и не противоречит системе;
- текущий диалог подтверждает еще несколько независимых дефектов вокруг meta follow-up, root pivot reset и short follow-up continuity;
- org clarification policy в этом кейсе, наоборот, отработала лучше, чем предполагал исходный аудит;
- следующий слой исправлений должен быть точечным и не должен ломать действующие inventory selected-object rails.
@@ -0,0 +1,78 @@
# Project Status Update (2026-04-15)
Дата: 2026-04-15
Статус: `incremental update`
Базовые статусные документы:
- `project_status_rails_graph_2026-04-08.md`
- `step5_architecture_ux_quality_plan_v1_2026-04-08.md`
## 1. Новое подтвержденное улучшение
В address/orchestration runtime внедрен bounded guard:
- inventory drilldown -> tax/VAT/adjacent accounting pivot
- не тащит selected item в новый домен
- сохраняет только root context
Это снижает риск cross-domain contamination без отката follow-up памяти внутри inventory domain.
## 2. Что этот апдейт не должен означать
Этот инкремент не означает, что:
1. все follow-up проблемы уже решены;
2. inventory root-queries полностью изолированы от предыдущих VAT frame;
3. любой selected-object chain теперь устойчив при limited answers;
4. answer-shape policy для meta follow-up уже приведена в порядок.
То есть статус должен читаться как:
- один архитектурный риск закрыт;
- несколько соседних policy-рельс остаются открытыми.
## 3. Свежий live snapshot по `test.txt`
### Подтверждено
1. VAT exact route жив.
2. Data-scope selection по организациям жив.
3. Clarification по множественным организациям в этом сценарии корректный.
4. Sale trace по выбранной позиции запускается как exact capability.
### Открытые инциденты
1. Meta follow-up после VAT summary повторяет старый factual answer.
2. Inventory root-query после VAT все еще может нести чужой `previous_intent`.
3. Short purchase follow-up после limited sale step может выпадать в `non_domain_query_indexed`.
4. Entity extraction все еще допускает мусорный warehouse anchor из temporal phrase.
## 4. Риск неправильной интерпретации
По этому состоянию нельзя говорить:
- "архитектура диалога развалилась полностью"
- "inventory sale trace не работает вообще"
- "организация выбирается хаотично из observed rows"
Более точная формулировка:
- exact routes частично живы;
- bounded carryover hardening движется в правильную сторону;
- основной оставшийся риск — несогласованность соседних follow-up policies.
## 5. Что держим как ближайший operational focus
1. Meta follow-up answer-shape hardening.
2. Root-domain pivot reset для новых inventory root-queries.
3. Selected-object continuity after limited result.
4. Invalid entity admissibility guard for `warehouse`.
## 6. Acceptance note
Следующие исправления должны идти как отдельные bounded changes с targeted regressions.
Нельзя закрывать статус формулировкой "follow-up problem solved globally", пока:
- `это много или мало?` после VAT не дает короткий evaluative answer;
- `а купили у кого` после limited inventory step не держит selected-object continuity;
- `за май` может попасть в `warehouse`.
@@ -0,0 +1,132 @@
# Step-5 Increment Update (2026-04-15)
Дата: 2026-04-15
Статус: `active`
Связанные документы:
- `step5_architecture_ux_quality_plan_v1_2026-04-08.md`
- `project_status_rails_graph_2026-04-08.md`
- `followup_context_root_pivot_audit_2026-04-15.md`
## 1. Что именно обновлено в runtime
В текущем инкременте зафиксирован bounded fix для cross-domain carryover:
1. Если пользователь находится внутри inventory drilldown по выбранной позиции,
2. и следующим коротким сообщением делает pivot в чужой учетный домен,
3. runtime больше не тянет selected item в новый route,
4. а сохраняет только root context.
Практически это выражается так:
- `followupSelectionMode = carry_root_context`
- `followupContext.root_context_only = true`
Сохраняются только root-level поля:
- `organization`
- `warehouse`
- `as_of_date`
- `period_from`
- `period_to`
Не сохраняются:
- `item`
- object-level `previous_intent`
- object-level anchor
## 2. Почему это решение считается чистым
Это решение не спорит с текущей архитектурой rails, потому что:
1. не меняет execution semantics existing exact capabilities;
2. не отключает inventory selected-object carryover внутри inventory domain;
3. не подменяет root frame object frame-ом и наоборот;
4. не лечит UX-проблемы через query-level костыли.
То есть это не "новая архитектура", а аккуратный guard на границе между:
- follow-up orchestration,
- selected-object navigation,
- domain pivot policy.
## 3. Что показал свежий live audit
Разбор прогона из `C:\Users\DCTOUCH\Desktop\test.txt` подтверждает:
### Уже нормально
1. VAT root route сам по себе работает.
2. Data-scope вопрос по базе/организации работает.
3. Multiple-organization clarification в этом сценарии работает корректно.
4. Inventory selected-object sale trace доходит до exact capability.
### Еще не закрыто
1. Meta follow-up `это много или мало?` все еще replays предыдущий factual VAT answer.
2. Новый inventory root-query после VAT все еще несет `previous_intent = vat_payable_forecast`.
3. После limited selected-object sale step короткое `а купили у кого` может выпасть в `non_domain_query_indexed`.
4. В extraction все еще возможен мусорный `warehouse = "за май"`.
## 4. Как интерпретировать эти дефекты
Важно не смешивать разные классы проблем:
### A. Route/intent problem
Когда нужный intent вообще не распознан или address lane не запускается.
### B. Retrieval/execution problem
Когда route выбран корректно, но retrieval возвращает `empty_match` / `no_raw_rows`.
### C. Answer-shape problem
Когда данные/intent корректны, но форма ответа не соответствует пользовательскому вопросу.
### D. Follow-up continuity problem
Когда новый короткий вопрос не унаследовал допустимый контекст из предыдущего шага.
Свежий прогон содержит все четыре типа, но в разных местах. Это важно для планирования, чтобы не чинить retrieval-пустоту как orchestration-баг и наоборот.
## 5. Следующий bounded backlog
### P0
1. `meta_followup_answer_policy`
Для evaluative short follow-up поверх VAT/tax factual summary запретить replay полного ответа.
2. `root_domain_pivot_resets_previous_intent`
Для нового root inventory query после VAT/tax не тянуть `previous_intent` из чужого домена.
3. `selected_object_continuity_after_limited_result`
После limited inventory drilldown answer short follow-up должен оставаться в address lane.
### P1
1. `invalid_warehouse_anchor_guard`
Темпоральные куски вроде `за май` не должны заполнять `warehouse`.
2. `acceptance_split_for_empty_match`
В acceptance нужно отдельно учитывать:
- `route matched but empty`
- `route not matched`
- `follow-up continuity lost`
## 6. Обязательные regression chains
1. `прогноз НДС -> это много или мало?`
2. `прогноз НДС -> остаток на складе за май 2020`
3. `inventory selected item -> кому продали -> а купили у кого`
4. `остаток на складе за май 2020` с проверкой admissibility для `warehouse`
## 7. Итог
Состояние на 2026-04-15 выглядит так:
- bounded root-context-only fix — правильный;
- inventory rails не надо откатывать;
- текущие open issues лежат рядом с ним, а не внутри него;
- дальнейшая работа должна идти через изолированные policy/acceptance fixes, а не через очередной общий rewrite follow-up логики.
@@ -0,0 +1,428 @@
# 10 - Текущая архитектура ассистента на 2026-04-15
## 1. Назначение документа
Этот документ фиксирует не историческую эволюцию, а текущий рабочий архитектурный срез ассистента в проекте `NDC_1C`.
Цель документа:
- зафиксировать, какие архитектурные блоки реально участвуют в runtime сейчас;
- отделить текущий работающий контур от ранних проектных отчетов и аудитов;
- дать опорную карту для дальнейшего bounded hardening без разрушения baseline.
Документ не заменяет ранние отчеты в `docs/ARCH`, а накладывается на них как актуальный operational snapshot.
## 2. Как читать `docs/ARCH` после этого обновления
Исторические документы сохраняют свою роль:
- `1-4` — bootstrap, ранний pipeline, MVP и GUI/manual слой;
- `5` — ранний отчет по assistant mode;
- `6` — интегральный статус проекта и Stage 4 на конец марта;
- `7-9` — архитектурные аудиты, gap-регистры, source-to-proof и relation разведка.
Текущий документ нужен для другого:
- не объяснить, как проект развивался;
- а зафиксировать, как именно устроен ассистент сейчас на уровне runtime, state, orchestration и capability routing.
## 3. Executive Summary
На текущем этапе ассистент представляет собой не один monolithic pipeline, а связку из пяти рабочих слоев:
1. `Assistant / living router` — решает, идти ли в address/data lane, в data-scope lane или в обычный chat.
2. `Address orchestration runtime` — собирает predecompose, carryover, continuation contract и orchestration decision.
3. `Address exact execution lane` — выполняет exact-capability routes через `AddressQueryService`.
4. `Session memory + navigation state` — хранит `investigation_state`, `address_navigation_state`, `result_sets`, `focus_object`, `organization/date scope`.
5. `Answer/debug contract layer` — формирует ответ, debug payload, continuation contract и данные для GUI/debug drawer.
Ключевая особенность текущей архитектуры:
- разговорный слой уже не является единственным носителем контекста;
- контекст все больше держится в структурированном session/navigation state;
- exact-capability routes уже существуют как отдельный runtime-контур, а не как побочный продукт общего chat-flow.
## 4. Graphify-срез по кодовой базе
По `graphify-out/GRAPH_REPORT.md` на `2026-04-15`:
- корпус: `473 files`;
- граф: `4865 nodes`, `10622 edges`, `132 communities`;
- среди god nodes находятся:
- `resolveAddressIntent()`;
- `composeFactualReply()`;
- `resolveAssistantOrchestrationDecision()`.
Архитектурно самые важные community:
- `Community 2` — orchestration и `AssistantService`;
- `Community 6` — exact capability/runtime execution, включая `AddressQueryService`;
- `Community 14` — domain cards, domain purity, source gating;
- `Community 17` — navigation state, `focus_object`, `result_sets`, session carryover;
- `Community 20` — address orchestration runtime adapter и follow-up message policy.
Это подтверждает, что текущая система уже раскладывается на отдельные runtime-блоки, а не живет в одном промптовом центре принятия решений.
## 5. Текущая карта runtime
### 5.1 Верхний уровень
Текущий поток запроса выглядит так:
`GUI/API -> AssistantService -> orchestration decision -> address runtime adapter -> AddressQueryService -> compose/debug/session persistence`
На этом уровне уже зафиксированы три разных режима:
- `address_data`;
- `assistant_data_scope`;
- `chat`.
Ключевая точка маршрутизации — `resolveAssistantOrchestrationDecision()` в `llm_normalizer/backend/src/services/assistantService.ts`.
### 5.2 Session memory
Сессионная память не ограничивается простым хранением истории сообщений.
Текущий session store:
- `AssistantSessionStore`;
- `investigation_state`;
- `address_navigation_state`.
Это означает, что архитектурно ассистент уже работает не только на transcript memory, но и на явном структурированном state.
## 6. Orchestration слой
### 6.1 Главный orchestration узел
`AssistantService` является текущим orchestration-ядром ассистента.
Он отвечает за:
- выбор living mode;
- resolution follow-up context;
- построение continuation contracts;
- связывание session memory с runtime execution;
- routing между address lane, data-scope и chat.
На текущем этапе это уже не просто “controller”, а фактический координатор между state, semantics и runtime.
### 6.2 Address orchestration runtime
Для address/data контура вынесен отдельный adapter:
- `assistantAddressOrchestrationRuntimeAdapter.ts`
Он выполняет:
- LLM predecompose или fallback predecompose;
- нормализацию `effectiveMessage`;
- resolution carryover context через `resolveAddressFollowupCarryoverContext()`;
- защиту от неудачных канонизаций через `shouldPreferRawFollowupMessage()`;
- построение `dialogContinuationContract`;
- формирование `addressRuntimeMeta`.
Это важное отличие текущей архитектуры от ранних отчетов:
- predecompose;
- carryover;
- continuation contract;
- orchestration decision
теперь собраны в отдельный runtime-блок, а не размазаны по нескольким ad hoc helper-ам.
## 7. Session state и navigation state
### 7.1 Что реально хранится
`addressNavigationState.ts` фиксирует текущую модель навигационного состояния.
Текущий `session_context` включает:
- `active_result_set_id`;
- `active_focus_object`;
- `last_confirmed_route`;
- `date_scope`:
- `as_of_date`;
- `period_from`;
- `period_to`;
- `organization_scope`.
Отдельно хранятся:
- `result_sets[]`;
- `navigation_history[]`.
### 7.2 Что это значит архитектурно
Текущий диалоговый контекст больше не должен держаться только “в голове модели”.
У системы уже есть структурированные сущности:
- результат ответа как `result_set`;
- выбранный объект как `focus_object`;
- подтвержденный маршрут как `last_confirmed_route`;
- текущий root scope как `organization/date scope`.
Это база для устойчивых drilldown-сценариев.
### 7.3 Как state эволюционирует
`evolveAddressNavigationStateWithAssistantItem()` делает следующее:
- вынимает из assistant reply `detected_intent`, `selected_recipe`, `extracted_filters`;
- строит `result_set_id`;
- при наличии — строит `focus_object`;
- пишет navigation event;
- обновляет active result/focus/route/date/org scope.
Важно:
- `active_focus_object` не затирается автоматически при отсутствии нового focus;
- `organization_scope` и `date_scope` также тянутся как долговременный session context.
## 8. Follow-up и continuation semantics
### 8.1 Carryover контекст
`resolveAddressFollowupCarryoverContext()` сейчас является центральным узлом follow-up логики.
Он собирает carryover из:
- предыдущего address reply;
- navigation state;
- organization clarification state;
- implicit continuation signal;
- selected object / displayed entities;
- inventory root frame.
### 8.2 Root frame и drilldown frame
В текущей реализации уже присутствует различие между:
- `inventory_root`;
- `inventory_drilldown`;
- `generic`.
То есть архитектура уже ушла от полностью плоского carryover.
Фактически в runtime уже живут два уровня:
- root context:
- организация;
- дата/период;
- root intent;
- object/drilldown context:
- item/counterparty/contract/focus object;
- drilldown intent.
### 8.3 Root-only carryover
Отдельно введен режим `carry_root_context` / `root_context_only`.
Он используется в тех местах, где нужно:
- сохранить организацию и temporal scope;
- но не тянуть старый object-level intent в новый доменный вопрос.
Архитектурно это важный шаг: система уже умеет не только продолжать предыдущий вопрос, но и ограничивать глубину carryover.
### 8.4 Continuation contract
`buildAddressDialogContinuationContractV2()` сейчас формирует отдельный machine-readable контракт продолжения.
Он хранит:
- `decision`;
- `decision_reasons`;
- `previous_intent`;
- `target_intent`;
- `intent_selection_mode`;
- `anchor_type`;
- `anchor_value`;
- `implicit_continuation_signal`.
Это уже полноценный runtime artifact, а не побочный debug-комментарий.
## 9. Exact capability runtime
### 9.1 Role of `AddressQueryService`
`AddressQueryService` — текущий exact execution engine для address/data маршрутов.
Основной поток внутри `tryHandle()`:
- `runAddressDecomposeStage()`;
- pre-execution grounding;
- organization clarification / scope resolution;
- requested result mode resolution;
- capability route decision;
- recipe selection;
- exact MCP query execution;
- materialization;
- scoped filtering;
- future/temporal guards;
- limited/factual reply building.
### 9.2 Что изменилось относительно ранних отчетов
Текущий address runtime уже не является “одним generic execute_query на удачу”.
Сейчас в нем есть:
- capability route guard;
- route expectation audit;
- organization clarification path;
- intent-specific filter layer;
- lifecycle detachment semantics;
- historical/broadened retry layers;
- exact/limited result policy.
То есть ранняя картина из `ARCH/5` уже устарела: exact-capability execution есть и он занимает отдельный крупный слой runtime.
### 9.3 Capability policy
`addressCapabilityPolicy.ts` фиксирует точные capability routes.
На текущем этапе в policy явно присутствуют, в частности:
- inventory:
- `inventory_on_hand_as_of_date`;
- `inventory_purchase_provenance_for_item`;
- `inventory_purchase_documents_for_item`;
- `inventory_supplier_stock_overlap_as_of_date`;
- `inventory_sale_trace_for_item`;
- `inventory_purchase_to_sale_chain`;
- `inventory_aging_by_purchase_date`;
- VAT:
- `vat_payable_confirmed_as_of_date`;
- `vat_liability_confirmed_for_tax_period`.
Это важно зафиксировать отдельно:
- capability layer уже живет как explicit policy map;
- она не должна снова расползаться в “общую умность”.
## 10. Data/domain слой
### 10.1 Domain purity
`assistantDataLayer.ts` продолжает играть роль доменного ограничителя и source gate.
В нем присутствуют:
- `domain_scope`;
- `forbidden_cross_domain_leakage`;
- source gating;
- graph traversal profiles;
- live MCP call planning;
- domain card based filtering.
### 10.2 Почему это важно для текущей архитектуры
Даже если текущая задача решается в address exact lane, система уже опирается на более широкий доменный слой:
- domain cards;
- source purity;
- graph-aware retrieval planning;
- forbidden cross-domain leakage rules.
Следовательно, любые новые hardening-решения нельзя строить как локальные regex-патчи в inventory/VAT ветках, если они конфликтуют с domain purity моделями.
## 11. Data source модель
Текущий runtime работает как минимум с двумя типами источников:
- live MCP / `execute_query` и каталожные резолверы;
- snapshot/canonical/risk материалы, участвующие в более широком assistant/data контуре.
Для address exact lane центральным остается live execution, но:
- orchestration уже знает про data-scope и domain routes;
- в проекте сохраняется split между lightweight live path и более широкими доказательными/аналитическими слоями.
## 12. Debug, contracts и observability
Текущая архитектура сильно опирается на machine-readable debug artifacts.
На runtime-уровне зафиксированы:
- `technical_debug_payload_json`;
- `addressRuntimeMeta`;
- `orchestrationContract`;
- `dialogContinuationContract`;
- `route_expectation_*`;
- `capability_id`;
- `selected_recipe`;
- `limited_reason_category`.
Для проекта это уже не “вспомогательная телеметрия”, а часть архитектуры:
- через эти контракты GUI, аудит и domain loop понимают, что именно решила система;
- без них bounded hardening быстро превращается в непрозрачную серию случайных патчей.
## 13. Feature-flag слой
В текущем runtime существенная часть поведения завязана на feature flags.
Ключевые flags, влияющие на архитектуру:
- `FEATURE_ASSISTANT_ADDRESS_QUERY_V1`;
- `FEATURE_ASSISTANT_ADDRESS_QUERY_LIVE_V1`;
- `FEATURE_ASSISTANT_CAPABILITY_ROUTE_GUARD_V1`;
- `FEATURE_ASSISTANT_ROUTE_EXPECTATION_AUDIT_V1`;
- `FEATURE_ASSISTANT_ROUTE_EXPECTATION_HARD_GUARD_V1`;
- `FEATURE_ASSISTANT_INVESTIGATION_STATE_V1`;
- `FEATURE_ASSISTANT_ADDRESS_NAVIGATION_STATE_V1`;
- `FEATURE_ASSISTANT_LIVING_CHAT_ROUTER_V1`;
- `FEATURE_ASSISTANT_STATE_FOLLOWUP_BINDING_V1`;
- `FEATURE_ASSISTANT_CONTRACTS_V11`;
- `FEATURE_ASSISTANT_ANSWER_POLICY_V11`.
Архитектурно это значит:
- текущая система уже modularized;
- но operational profile зависит от конфигурации flags, а не только от кода.
## 14. Что устарело в ранних архитектурных документах
### 14.1 Что больше нельзя считать точным описанием текущего состояния
Ранние документы `ARCH/5` и частично `ARCH/6_global_report` полезны как история, но не как точный snapshot текущего runtime.
Устаревшими в них являются, в частности, представления о том, что:
- assistant mode в основном сводится к answer composer + session memory;
- retrieval plan еще в основном stubbed;
- routing и follow-up существуют как легкая надстройка поверх ответа.
На текущем этапе это уже не так:
- continuation contracts существуют;
- navigation state существует;
- exact capability runtime существует;
- route expectation / capability guard / organization clarification существуют;
- root/drilldown carryover уже встроен в orchestrator.
### 14.2 Как использовать старые документы теперь
Старые отчеты полезны:
- как описание этапов развития;
- как baseline для исторического сравнения;
- как объяснение происхождения guardrails и audit criteria.
Но для описания того, “как работает ассистент сейчас”, опорным должен считаться уже этот документ.
## 15. Текущие архитектурные инварианты
На момент `2026-04-15` безопасно считать архитектурными инвариантами следующее:
1. Exact business routes должны жить как explicit capability/runtime paths, а не как heuristic chat imitation.
2. Follow-up continuity должна опираться не только на transcript, но и на structured state.
3. `focus_object`, `result_set`, `organization_scope`, `date_scope` являются частью архитектуры, а не UX-деталью.
4. Root context и drilldown context нельзя больше считать одной плоской переменной “контекст разговора”.
5. Machine-readable debug/contracts обязательны для объяснимости и bounded hardening.
6. Domain purity и forbidden cross-domain leakage уже являются встроенными guardrails и должны учитываться при любом расширении.
## 16. Текущие ограничения
Несмотря на значительный сдвиг архитектуры, текущая система еще не должна описываться как полностью закрытая production architecture.
Остаются ограничения:
- часть follow-up semantics еще зависит от LLM predecompose и quality canonicalization;
- часть object-level continuity еще удерживается комбинацией transcript + navigation state, а не единым frame engine;
- не все capability routes одинаково зрелые по depth и proof closure;
- hardening по meta-follow-up, pivot semantics и field admissibility еще остается отдельным слоем работы.
## 17. Практический итог
Текущий ассистент уже нельзя описывать как “чат над 1С”.
Более точная формулировка:
`структурированный orchestration runtime + session/navigation state + exact address capability engine + domain/data guardrails`
Именно в этой рамке должны приниматься следующие решения:
- не через новый общий rewrite;
- не через промптовую переумность;
- а через bounded усиление уже существующих архитектурных блоков.
## 18. Связанные документы
Исторический baseline:
- `docs/ARCH/5 - assistant_mode_architecture_report_2026-03-24.md`
- `docs/ARCH/6 - project_and_stage4_full_report_2026-03-28.md`
- `docs/ARCH/6_global_report/Assistant_Mode_GLOBAL_STATUS_2026-03-24.md`
Аудит и gap-анализ:
- `docs/ARCH/7 - аудит архитектуры на 4 этапе/7 - assistant_runtime_ground_truth_audit_2026-03-28.md`
- `docs/ARCH/8_audit_artifacts/8 - аудит source_to_proof_по_3_контрольным_вопросам_2026-03-29.md`
- `docs/ARCH/9_audit_artifacts/9 - разведка_структуры_1с_и_связей_через_mcp_по_3_контрольным_вопросам_2026-03-29.md`
- `docs/ARCH/9_audit_artifacts/9F - current_runtime_vs_required_runtime.md`
Следующий operational документ:
- `docs/ARCH/10A - current_assistant_hardening_plan_2026-04-15.md`
@@ -0,0 +1,247 @@
# 10A - План bounded hardening текущей архитектуры на 2026-04-15
## 1. Назначение документа
Этот документ фиксирует не общий wishlist и не разовый разбор отдельного прогона, а bounded hardening plan для текущей архитектуры ассистента.
Цель:
- усилить существующие блоки;
- не снести рабочий baseline;
- не ввести решения, противоречащие уже внедренным architectural rails.
Документ опирается на текущий runtime, зафиксированный в:
- `docs/ARCH/10 - current_assistant_architecture_2026-04-15.md`
- `graphify-out/GRAPH_REPORT.md`
## 2. Принципы выполнения
Все дальнейшие изменения должны проходить по следующим правилам:
1. Не переписывать runtime foundations.
2. Не растворять exact capability routes обратно в “общую умность”.
3. Не ломать working baseline ради одного edge-case.
4. Укреплять сначала orchestration/state/policy слой, а не маскировать проблемы answer wording-ом.
5. Любой новый hardening должен быть выражен либо как:
- новый guard;
- новая policy;
- новый state invariant;
- новый regression test.
## 3. Что уже считается baseline и не должно деградировать
На текущем этапе надо считать защищаемым baseline следующее:
- living router между `address_data`, `assistant_data_scope` и `chat`;
- `AddressQueryService` как отдельный exact execution lane;
- `addressNavigationState` с `result_set`, `focus_object`, `organization_scope`, `date_scope`;
- `dialogContinuationContractV2`;
- `capability route guard` и `route expectation audit`;
- inventory selected-object follow-up как отдельный сценарный класс;
- organization clarification path;
- limited mode вместо ложного “подтвержденного” ответа при незакрытом proof path.
Любой фикс, который делает систему “умнее”, но при этом размывает эти элементы, считается архитектурно спорным.
## 4. Главные линии bounded hardening
### 4.1 Явное различение root frame и object frame
Что уже есть:
- `organization_scope`;
- `date_scope`;
- `active_focus_object`;
- `current_frame_kind`;
- `root_context_only`.
Что надо усилить:
- перестать трактовать carryover как один общий пакет фильтров;
- закрепить root-level и object-level continuation как разные режимы;
- не позволять object-intent автоматически переживать любой domain pivot.
Практический смысл:
- `root context` должен переживать больше типов follow-up;
- `object context` должен переноситься только в совместимых сценариях.
### 4.2 Жесткий policy-слой для domain pivot
Текущая архитектура уже содержит:
- `domain_scope`;
- `forbidden_cross_domain_leakage`;
- `assistant_data_scope_query_detected`;
- `non_domain_query_indexed`.
Надо закрепить общий policy:
- если новый вопрос совместим с текущим drilldown domain — можно использовать object carryover;
- если новый вопрос уходит в соседний, но поддержанный домен — переносим только root context;
- если новый вопрос не собрался, нельзя автоматически продолжать предыдущий object route.
Это должен быть orchestration-level guard, а не частный патч в inventory или VAT.
### 4.3 Meta-follow-up как отдельный класс вопросов
В текущем контуре мета-вопросы типа:
- `это много или мало?`
- `это критично?`
- `это нормально?`
- `что из этого важнее?`
не должны притворяться повторным exact business query.
Надо закрепить отдельную политику:
- meta-follow-up не должен слепо replay-ить предыдущий ответ;
- он должен опираться на предыдущий answer object/result, а не запускать старый route без надобности;
- meta-layer должен быть отделен от exact data route.
### 4.4 Admissibility и truthfulness guard для entity/field extraction
Текущий runtime уже умеет:
- отбрасывать часть низкокачественных anchor-ов;
- использовать clarification;
- сохранять limited mode.
Следующий bounded шаг:
- ввести общий admissibility слой для extracted entity values;
- не позволять деградации полного anchor-а до обрубка;
- не позволять generic semantic hint перетирать уже подтвержденный selected object;
- не позволять неподтвержденному полю мимикрировать под бизнес-роль.
Это особенно важно для:
- item/counterparty/contract anchors;
- selected-object lifecycle follow-up;
- purchase/sale provenance chains.
### 4.5 Stabilization слоя selected-object continuity
Selected-object continuity уже является частью реальной архитектуры, а не UX-дополнением.
Нужно закрепить инварианты:
- выбранный объект не должен теряться из-за слабого rewrite;
- короткий follow-up не должен автоматически сбрасывать focus;
- новый явно выбранный объект должен приоритетно заменять старый;
- `focus_object` и `previous_anchor` не должны конфликтовать.
Это должно проверяться не на одном кейсе, а на классе сценариев:
- canonical wording;
- colloquial wording;
- UI selected-object wording;
- короткий follow-up;
- follow-up после limited answer.
### 4.6 Оркестрационный разрыв между supported route и unsupported carryover
Одна из основных зон риска — когда:
- route поддержан;
- но carryover прилетает в неправильной форме;
- и система либо уходит в wrong-route, либо в generic partial.
Надо усиливать границу:
- carryover policy и route policy должны быть согласованы;
- если carryover сомнителен, exact route не должен получать мусорный anchor;
- если route валиден, generic conversational fallback не должен подменять его без явной причины.
## 5. Что нельзя делать в рамках этого плана
Чтобы не войти в архитектурный конфликт с текущей системой, в bounded hardening нельзя:
1. Вводить новый “универсальный супер-классификатор”, который обходил бы `AssistantService` и `AddressQueryService`.
2. Дублировать domain purity правила в локальных regex-патчах конкретных capability.
3. Переносить session/navigation state обратно в transcript-only memory.
4. Сливать `root context` и `focus object` обратно в один плоский набор фильтров.
5. Чинить системные проблемы через answer wording без policy/runtime изменения.
6. Маскировать `empty_match`, `missing_anchor`, `recipe_visibility_gap`, `execution_error` под “подтвержденный ответ”.
## 6. Приоритетный порядок внедрения
### P0. Сохранение архитектурной формы
Сначала должны усиливаться те места, которые защищают уже сложившуюся форму runtime:
- root vs object carryover policy;
- selected-object continuity;
- domain pivot guard;
- admissible entity carryover.
### P1. Meta и reasoning поверх результата
После этого:
- meta-follow-up policy;
- reuse answer object/result object;
- bounded comparative/explanatory follow-up.
### P2. Глубина доказательного маршрута
После стабилизации orchestration/state слоя:
- расширение object-level proof paths;
- новые exact capability routes;
- deeper provenance/sale/purchase chains;
- richer document relation recovery.
## 7. Обязательные acceptance-invariants
Любое изменение по этому плану должно проверяться по invariants, а не только по “кажется, ответ стал лучше”.
Минимальный набор:
1. `direct_answer_first`
2. `selected_object_memory_survives_short_followup`
3. `new_explicit_selected_object_overrides_old_focus`
4. `root_context_survives_domain_pivot_without_object_leak`
5. `unsupported_new_domain_does_not_replay_previous_exact_answer`
6. `full_anchor_not_degraded_by_canonical_rewrite`
7. `limited_mode_remains_truthful`
8. `exact_supported_route_not_shadowed_by_generic_chat_fallback`
## 8. Требуемые классы автотестов
### 8.1 Orchestration/state tests
Нужны отдельные регрессии на:
- `carry_root_context`;
- `root_context_only`;
- `dialogContinuationContractV2`;
- explicit object switch;
- follow-up after limited result.
### 8.2 Address runtime tests
Нужны тесты на:
- full item anchor preservation;
- selected-object sale/purchase routes;
- organization clarification continuity;
- empty-match honesty;
- route expectation consistency.
### 8.3 Router boundary tests
Нужны тесты на переходы:
- `address_data -> assistant_data_scope`;
- `address_data -> chat`;
- `inventory drilldown -> tax/meta pivot`;
- `meta-followup -> no route replay`.
## 9. Документальный результат, который должен остаться после внедрения
Каждый крупный bounded hardening должен оставлять после себя:
- короткий architecture note в `docs/ARCH` или `docs/ADDRESS`;
- regression tests;
- при необходимости — audit addendum;
- обновленный graphify snapshot.
То есть hardening должен завершаться не только кодом, но и явной фиксацией архитектурного состояния.
## 10. Итоговая формула
Правильный способ решать следующие проблемы в проекте:
`не rewrite системы`
а
`bounded hardening существующих блоков`
через:
- orchestration policy;
- structured state;
- domain compatibility;
- admissible carryover;
- exact capability discipline.
Именно эта рамка считается безопасной для текущей архитектуры проекта.