Этап 4 / Пакет по РБП восстановление живого контура сбора данных и доказательной базы
This commit is contained in:
parent
095e74ad3b
commit
133b6dca3c
|
|
@ -0,0 +1,448 @@
|
|||
разведку структуры 1С и связей через MCP по 3 контрольным кейсам.md
|
||||
|
||||
---
|
||||
|
||||
# ТЗ для Codex
|
||||
|
||||
## Этап 4 — разведка структуры 1С и связей через MCP по 3 контрольным кейсам
|
||||
|
||||
## Цель: понять, какие сущности, регистры, документы и переходы реально нужны для доказательного ответа
|
||||
|
||||
### 1. Контекст
|
||||
|
||||
Текущая проблема выглядит не как чисто текстовый дефект, а как сбой в контуре:
|
||||
|
||||
**вопрос → якоря → маршрут → данные 1С → связи между сущностями → evidence → ответ**
|
||||
|
||||
Есть подозрение, что система:
|
||||
|
||||
* не до конца понимает, какие объекты 1С нужны для ответа на конкретный тип вопроса;
|
||||
* не до конца понимает, как эти объекты связаны;
|
||||
* не всегда идёт в нужные документы/регистры через MCP;
|
||||
* даже когда данные приходят, не всегда умеет собрать из них admissible evidence.
|
||||
|
||||
Эта работа не про новый prompt и не про wording.
|
||||
Это **разведка структуры данных и зависимостей**.
|
||||
|
||||
---
|
||||
|
||||
## 2. Главная цель задания
|
||||
|
||||
Нужно не “починить ответы” и не “сделать ещё один rerun”, а:
|
||||
|
||||
### **Построить доказательную карту связей 1С по 3 типовым вопросам**
|
||||
|
||||
И ответить на вопросы:
|
||||
|
||||
1. какие сущности 1С реально участвуют в каждом кейсе;
|
||||
2. какие связи между ними обязательны;
|
||||
3. какие регистры и документы надо проходить;
|
||||
4. какие MCP-вызовы нужны, чтобы это собрать;
|
||||
5. где контур сейчас рвётся:
|
||||
|
||||
* источник,
|
||||
* маршрут,
|
||||
* mapping структуры 1С,
|
||||
* evidence materialization,
|
||||
* answer handoff.
|
||||
|
||||
---
|
||||
|
||||
## 3. Source of truth — 3 контрольных вопроса
|
||||
|
||||
### Вопрос 1 — НДС
|
||||
|
||||
**13 июля проведено поступление товаров, а 15 июля — реализация этих же мебельных позиций. НДС-цепочка по этим движениям у нас полная или где-то есть выпадение между документом, проводкой и налоговым отражением?**
|
||||
|
||||
### Вопрос 2 — РБП
|
||||
|
||||
**31 июля прошло “Списание РБП за Июль 2020 г.”, в том числе на 5 000 и ещё несколько сумм. Есть ли в базе признаки, что часть РБП к концу июля всё ещё живёт дольше ожидаемого?**
|
||||
|
||||
### Вопрос 3 — Амортизация
|
||||
|
||||
**31 июля начислена амортизация тремя суммами — 2 471,52, 2 465,28 и 849,83. Это похоже на полное начисление по всем нужным объектам за июль или есть риск, что какой-то объект ОС в июле не попал в амортизацию?**
|
||||
|
||||
Эти 3 вопроса являются **единственной обязательной базой** для текущей разведки.
|
||||
|
||||
---
|
||||
|
||||
## 4. Что нельзя делать
|
||||
|
||||
1. Не пытаться описать “всю 1С целиком”.
|
||||
2. Не делать общую энциклопедию регистров.
|
||||
3. Не уходить в redesign архитектуры.
|
||||
4. Не строить новый proof engine.
|
||||
5. Не ограничиваться пересказом старых отчётов.
|
||||
6. Не делать выводы без артефактов.
|
||||
7. Не “гулять по базе” без цели — только от вопроса к связанным сущностям.
|
||||
|
||||
---
|
||||
|
||||
## 5. Что нужно сделать
|
||||
|
||||
Работу нужно провести по 5 узлам.
|
||||
|
||||
---
|
||||
|
||||
# Узел A — Построить карту обязательных сущностей для каждого вопроса
|
||||
|
||||
Для каждого из 3 вопросов определить:
|
||||
|
||||
### A1. Seed entities
|
||||
|
||||
С чего начинается поиск:
|
||||
|
||||
* документ;
|
||||
* контрагент;
|
||||
* договор;
|
||||
* объект расчётов;
|
||||
* объект РБП;
|
||||
* объект ОС;
|
||||
* номенклатура;
|
||||
* проводка;
|
||||
* регистр.
|
||||
|
||||
### A2. Required entities
|
||||
|
||||
Какие сущности обязательно нужны для ответа.
|
||||
|
||||
#### Для НДС-кейса
|
||||
|
||||
Минимально проверить:
|
||||
|
||||
* документ поступления;
|
||||
* документ реализации;
|
||||
* счёт-фактура;
|
||||
* движения по НДС;
|
||||
* проводки;
|
||||
* запись книги покупок / продаж;
|
||||
* связь между документами и регистрами;
|
||||
* мебельные позиции / номенклатура / объект товара;
|
||||
* контрагент / договор / документная цепочка.
|
||||
|
||||
#### Для РБП-кейса
|
||||
|
||||
Минимально проверить:
|
||||
|
||||
* документ списания РБП;
|
||||
* объект РБП;
|
||||
* движения по РБП;
|
||||
* остаток/хвост на конец июля;
|
||||
* основание и график списания;
|
||||
* связанный month-close контур;
|
||||
* проводки / регистры / документы подтверждения.
|
||||
|
||||
#### Для амортизации
|
||||
|
||||
Минимально проверить:
|
||||
|
||||
* объекты ОС;
|
||||
* документ начисления амортизации;
|
||||
* движения начисления;
|
||||
* expected set объектов на июль;
|
||||
* фактическое попадание в начисление;
|
||||
* проводки;
|
||||
* остаточные хвосты / пропуски по объектам.
|
||||
|
||||
### A3. Expected transitions
|
||||
|
||||
Для каждого вопроса зафиксировать:
|
||||
|
||||
* какие переходы между сущностями **обязательны**,
|
||||
* какие переходы являются “смежным контуром”,
|
||||
* какие missing transitions означают реальную проблему.
|
||||
|
||||
---
|
||||
|
||||
# Узел B — Проверить, что из этого реально есть в snapshot и что реально доступно через MCP
|
||||
|
||||
### B1. Snapshot coverage
|
||||
|
||||
Для каждого вопроса определить:
|
||||
|
||||
* какие snapshot-источники реально содержат нужные сущности;
|
||||
* достаточно ли snapshot-only для ответа;
|
||||
* какие части цепочки snapshot не покрывает.
|
||||
|
||||
### B2. MCP/live coverage
|
||||
|
||||
Для каждого вопроса определить:
|
||||
|
||||
* какие MCP-методы/запросы позволяют добыть нужные сущности;
|
||||
* что доступно напрямую;
|
||||
* что доступно только через несколько переходов;
|
||||
* где нужны пошаговые адресные вызовы.
|
||||
|
||||
### B3. Coverage verdict
|
||||
|
||||
По каждому вопросу дать жёсткий ответ:
|
||||
|
||||
* `snapshot_sufficient`
|
||||
* `live_required`
|
||||
* `snapshot_plus_live_required`
|
||||
* `data_not_reachable_in_current_runtime`
|
||||
|
||||
---
|
||||
|
||||
# Узел C — Построить карту связей между элементами 1С
|
||||
|
||||
Это ключевая часть задания.
|
||||
|
||||
Нужно не просто перечислить сущности, а построить **relation map**.
|
||||
|
||||
### Для каждого вопроса определить:
|
||||
|
||||
1. какие связи прямые:
|
||||
|
||||
* документ → проводка
|
||||
* документ → счёт-фактура
|
||||
* документ → регистр
|
||||
* объект → начисление
|
||||
* списание → остаток
|
||||
2. какие связи косвенные:
|
||||
|
||||
* договор → расчёты → документ
|
||||
* номенклатура → документ поступления → реализация
|
||||
* объект ОС → амортизационный контур
|
||||
3. какие связи обязательны для доказательства;
|
||||
4. какие связи являются “смежным контуром”, но не ядром ответа;
|
||||
5. какие связи невозможно восстановить текущими средствами.
|
||||
|
||||
### Формат
|
||||
|
||||
Не “словесное описание”, а нормальная матрица:
|
||||
|
||||
* `entity_A`
|
||||
* `entity_B`
|
||||
* `relation_type`
|
||||
* `required_for_claim`
|
||||
* `reachable_via_snapshot`
|
||||
* `reachable_via_live`
|
||||
* `current_runtime_uses_it`
|
||||
* `notes`
|
||||
|
||||
---
|
||||
|
||||
# Узел D — Проверить реальные маршруты через MCP
|
||||
|
||||
Codex должен не гадать, а **пройти по MCP/1С и проверить**.
|
||||
|
||||
### Для каждого вопроса:
|
||||
|
||||
1. какие вызовы реально нужны;
|
||||
2. в каком порядке их нужно делать;
|
||||
3. какие аргументы нужны;
|
||||
4. какие из них сейчас реально используются runtime;
|
||||
5. каких вызовов не хватает;
|
||||
6. какие вызовы возвращают шум вместо полезной опоры;
|
||||
7. где вызов правильный, но не хватает связи к следующему узлу.
|
||||
|
||||
### Нужен результат в форме:
|
||||
|
||||
* `question`
|
||||
* `required_live_calls`
|
||||
* `current_live_calls`
|
||||
* `missing_live_calls`
|
||||
* `wrong_live_calls`
|
||||
* `call_sequence_for_proof`
|
||||
|
||||
---
|
||||
|
||||
# Узел E — Построить source-to-proof failure map
|
||||
|
||||
Для каждого из 3 вопросов нужно финально ответить:
|
||||
|
||||
### Что система должна была сделать
|
||||
|
||||
Например:
|
||||
|
||||
* для НДС — собрать цепочку документ → проводка → НДС-регистр → книга;
|
||||
* для РБП — доказать, что часть РБП осталась жить дольше ожидаемого;
|
||||
* для амортизации — доказать полноту/неполноту охвата объектов ОС.
|
||||
|
||||
### Что система реально смогла поднять
|
||||
|
||||
* какие объекты;
|
||||
* какие регистры;
|
||||
* какие связи;
|
||||
* какие evidence items.
|
||||
|
||||
### Где контур рвётся
|
||||
|
||||
Использовать такие категории:
|
||||
|
||||
* `missing_source_data`
|
||||
* `source_exists_but_runtime_does_not_use_it`
|
||||
* `wrong_route_selection`
|
||||
* `wrong_entity_mapping`
|
||||
* `missing_relation_reconstruction`
|
||||
* `live_call_insufficient_for_proof`
|
||||
* `evidence_not_materialized`
|
||||
* `claim_anchor_coverage_insufficient`
|
||||
* `answer_layer_cannot_close_proof`
|
||||
|
||||
---
|
||||
|
||||
## 6. Как выполнять работу
|
||||
|
||||
### Этап 1 — Статический проход по коду
|
||||
|
||||
Понять:
|
||||
|
||||
* какие модули отвечают за source selection;
|
||||
* какие — за MCP/live;
|
||||
* какие — за mapping сущностей;
|
||||
* какие — за evidence packaging;
|
||||
* какие — за admissibility и answer mode.
|
||||
|
||||
### Этап 2 — Инвентаризация данных
|
||||
|
||||
Проверить:
|
||||
|
||||
* какие snapshot-файлы реально участвуют;
|
||||
* что в них лежит;
|
||||
* какие live endpoints/методы реально доступны.
|
||||
|
||||
### Этап 3 — Целевая разведка по 3 вопросам
|
||||
|
||||
Не общая прогулка по базе, а **управляемое движение от вопроса к связанным объектам**.
|
||||
|
||||
### Этап 4 — Relation reconstruction
|
||||
|
||||
Построить карту обязательных связей по каждому вопросу.
|
||||
|
||||
### Этап 5 — Failure classification
|
||||
|
||||
Показать, на каком узле реальный обрыв.
|
||||
|
||||
---
|
||||
|
||||
## 7. Что нужно создать
|
||||
|
||||
Создать новый комплект в `docs/ARCH`.
|
||||
|
||||
### Основной отчёт
|
||||
|
||||
`docs/ARCH/9 - разведка_структуры_1с_и_связей_через_mcp_по_3_контрольным_вопросам_2026-03-29.md`
|
||||
|
||||
---
|
||||
|
||||
## 8. Обязательные приложения
|
||||
|
||||
### `9A - entity_seed_map.md`
|
||||
|
||||
Для каждого вопроса:
|
||||
|
||||
* seed entities
|
||||
* required entities
|
||||
* expected transitions
|
||||
|
||||
### `9B - snapshot_vs_live_coverage_map.md`
|
||||
|
||||
Что реально есть в snapshot и что реально добывается через live.
|
||||
|
||||
### `9C - relation_map_1c_entities.md`
|
||||
|
||||
Карта связей между сущностями 1С по 3 кейсам.
|
||||
|
||||
### `9D - mcp_query_recipes.md`
|
||||
|
||||
Какие MCP-вызовы нужны для доказательного ответа по каждому кейсу.
|
||||
|
||||
### `9E - source_to_proof_failure_map.md`
|
||||
|
||||
Где именно рвётся контур по каждому вопросу.
|
||||
|
||||
### `9F - current_runtime_vs_required_runtime.md`
|
||||
|
||||
Сравнение:
|
||||
|
||||
* что нужно было сделать;
|
||||
* что делает текущий runtime.
|
||||
|
||||
---
|
||||
|
||||
## 9. Папка артефактов
|
||||
|
||||
`docs/ARCH/9_audit_artifacts/`
|
||||
|
||||
Обязательно положить:
|
||||
|
||||
* `chat_export_3_questions.md`
|
||||
* `debug_payloads/`
|
||||
* `raw_live_calls/`
|
||||
* `snapshot_samples/`
|
||||
* `relation_probe_logs/`
|
||||
* `query_recipe_examples/`
|
||||
* `replay_logs/`
|
||||
|
||||
---
|
||||
|
||||
## 10. Главные вопросы, на которые отчёт обязан ответить
|
||||
|
||||
### По НДС
|
||||
|
||||
* какие сущности и регистры реально нужны;
|
||||
* как они связаны;
|
||||
* почему positive path уже работает или где ещё шум;
|
||||
* что ещё надо дочистить.
|
||||
|
||||
### По РБП
|
||||
|
||||
* есть ли в source нужные данные вообще;
|
||||
* есть ли путь к ним через MCP;
|
||||
* где рвётся связка `source coverage + route + evidence materialization`.
|
||||
|
||||
### По амортизации
|
||||
|
||||
* какие объекты ОС должны участвовать;
|
||||
* как понять expected coverage;
|
||||
* почему admissible evidence уже есть, но proof не замыкается;
|
||||
* где именно не хватает mapping/anchors.
|
||||
|
||||
---
|
||||
|
||||
## 11. Итоговый общий verdict
|
||||
|
||||
В конце основного отчёта обязательно выдать один из вердиктов:
|
||||
|
||||
* `SOURCE_COVERAGE_IS_PRIMARY_PROBLEM`
|
||||
* `MCP_ROUTE_IS_PRIMARY_PROBLEM`
|
||||
* `ONE_C_RELATION_MAPPING_IS_PRIMARY_PROBLEM`
|
||||
* `EVIDENCE_MATERIALIZATION_IS_PRIMARY_PROBLEM`
|
||||
* `MULTI_NODE_FAILURE_CONFIRMED`
|
||||
|
||||
И отдельно по каждому из 3 вопросов дать свой локальный verdict.
|
||||
|
||||
---
|
||||
|
||||
## 12. Критерий качества
|
||||
|
||||
После выполнения этой работы должно стать **невозможно** говорить расплывчато:
|
||||
“кажется, плохо работаем с источником”.
|
||||
|
||||
Вместо этого должно быть ясно:
|
||||
|
||||
* какие данные нужны;
|
||||
* где они лежат;
|
||||
* как они связаны;
|
||||
* как до них идти через MCP;
|
||||
* где текущий runtime теряет их;
|
||||
* что конкретно чинить следующим пакетом.
|
||||
|
||||
---
|
||||
|
||||
## 13. Что должно получиться на выходе
|
||||
|
||||
Не новая волна фиксов, а **карта реальных зависимостей** и **точная карта поломки** по трём кейсам.
|
||||
|
||||
После этого должно быть понятно:
|
||||
|
||||
1. надо ли делать отдельный pack на source coverage;
|
||||
2. надо ли делать pack на relation mapping 1С;
|
||||
3. надо ли делать pack на evidence materialization;
|
||||
4. можно ли РБП и амортизацию чинить отдельно, а НДС только дочищать.
|
||||
|
||||
---
|
||||
|
||||
Если хочешь, следующим сообщением я дам ещё **короткое русское название этой работы для коммита/задачи** и **сверхкороткую версию промпта для Codex** без длинного ТЗ.
|
||||
|
|
@ -0,0 +1,388 @@
|
|||
Этап 4 — пакет по РБП: покрытие источника, live-маршрут и материализация доказательной базы
|
||||
|
||||
### 1. Контекст
|
||||
|
||||
Этот пакет делается **узко под кейс РБП**, а не как новая общая волна по всей системе.
|
||||
Вопрос про РБП уже зафиксирован как company-specific тест на lifecycle anomaly без выхода в полный Stage 5:
|
||||
**“31 июля прошло “Списание РБП за Июль 2020 г.”, в том числе на 5 000 и ещё несколько сумм. Есть ли в базе признаки, что часть РБП к концу июля всё ещё живёт дольше ожидаемого?”**
|
||||
|
||||
По живому прогону видно, что сейчас кейс остаётся в `partial_coverage`, живёт на snapshot-логике, live-путь слабый, admissible evidence до ответа не доезжает, а среди ограничений прямо фигурируют:
|
||||
|
||||
* snapshot 2020 read-only;
|
||||
* live probe как ограниченный выборочный запрос;
|
||||
* `matched_rows = 0`;
|
||||
* live evidence исключён из grounded answer;
|
||||
* admissibility gate убирает non-admissible evidence.
|
||||
|
||||
Stage 4 по-прежнему держим в рамках `P0-only`:
|
||||
|
||||
* без новых доменов,
|
||||
* без graph/schema expansion,
|
||||
* без Stage 5/6 как нового core path,
|
||||
* без больших транспортных рефакторингов.
|
||||
|
||||
---
|
||||
|
||||
## 2. Цель пакета
|
||||
|
||||
Нужно **не улучшить wording**, а восстановить для РБП нормальный путь:
|
||||
|
||||
**вопрос про РБП → правильные seed-объекты → правильный source coverage → правильный live route → admissible evidence → внятный proof-style ответ**
|
||||
|
||||
Итогом пакета должно стать:
|
||||
|
||||
1. понимание, какие данные по РБП реально нужны;
|
||||
2. понимание, где они лежат в snapshot/live;
|
||||
3. рабочий live/source path до этих данных;
|
||||
4. non-zero admissible evidence по РБП-кейсу;
|
||||
5. ответ, который ограничивается только если данных реально нет, а не потому что контур не дошёл до нужных сущностей.
|
||||
|
||||
---
|
||||
|
||||
## 3. Source of truth для пакета
|
||||
|
||||
### Базовый вопрос
|
||||
|
||||
**31 июля прошло “Списание РБП за Июль 2020 г.”, в том числе на 5 000 и ещё несколько сумм. Есть ли в базе признаки, что часть РБП к концу июля всё ещё живёт дольше ожидаемого?**
|
||||
|
||||
### Текущее живое поведение
|
||||
|
||||
По живому прогону для этого вопроса зафиксировано:
|
||||
|
||||
* `business_scope = generic_accounting`;
|
||||
* `entity_hints = ["РБП"]`;
|
||||
* `document_hints = ["Списание РБП"]`;
|
||||
* `time_scope = "июль 2020"`;
|
||||
* режим ответа — `partial_coverage`;
|
||||
* в uncertainties присутствуют snapshot-only, ограниченный live probe, `matched_rows=0`, live evidence excluded, admissibility gate removed evidence.
|
||||
|
||||
Это и есть исходная точка, от которой строится пакет.
|
||||
|
||||
---
|
||||
|
||||
## 4. Главная рабочая гипотеза
|
||||
|
||||
Для РБП-кейса проблема сейчас не в одном месте, а в связке:
|
||||
|
||||
* **source coverage**: runtime не поднимает нужный набор сущностей по РБП;
|
||||
* **route gap**: live path либо не выбирается, либо не ведёт к нужным данным;
|
||||
* **evidence materialization**: даже если часть сигнала есть, он не превращается в admissible evidence.
|
||||
|
||||
Эта гипотеза должна быть либо подтверждена, либо опровергнута артефактами этого пакета.
|
||||
|
||||
---
|
||||
|
||||
# 5. Что нужно сделать
|
||||
|
||||
Пакет выполнить по 4 узлам.
|
||||
|
||||
---
|
||||
|
||||
# Узел A — восстановить минимальную предметную модель РБП
|
||||
|
||||
## Задача
|
||||
|
||||
Понять, **какие сущности и переходы вообще обязательны** для ответа на вопрос о “живущем дольше ожидаемого” РБП.
|
||||
|
||||
## Что сделать
|
||||
|
||||
Для кейса РБП определить:
|
||||
|
||||
### A1. Seed entities
|
||||
|
||||
* документ “Списание РБП за Июль 2020 г.”;
|
||||
* суммы списания, включая 5 000;
|
||||
* объект РБП / карточка РБП;
|
||||
* период July 2020.
|
||||
|
||||
### A2. Required entities
|
||||
|
||||
Минимально установить, какие сущности нужны для доказательного ответа:
|
||||
|
||||
* документ списания РБП;
|
||||
* объект(ы) РБП;
|
||||
* движения/остатки по РБП;
|
||||
* основание списания;
|
||||
* expected schedule/lifecycle списания;
|
||||
* хвост/остаток на конец июля;
|
||||
* связанные регистры;
|
||||
* проводки;
|
||||
* month-close связка, если она обязательна.
|
||||
|
||||
### A3. Expected transitions
|
||||
|
||||
Зафиксировать обязательные переходы:
|
||||
|
||||
* объект РБП → документ списания;
|
||||
* документ списания → движение/регистр/проводка;
|
||||
* движение/остаток → состояние на конец июля;
|
||||
* expected schedule → фактическое списание;
|
||||
* июльский остаток → признак “живёт дольше ожидаемого”.
|
||||
|
||||
## Acceptance
|
||||
|
||||
* Для РБП должен появиться явный `required_entity_map`, а не общий доменный шум.
|
||||
* Должно быть ясно, **без каких сущностей proof в принципе невозможен**.
|
||||
|
||||
---
|
||||
|
||||
# Узел B — аудит покрытия источника по РБП
|
||||
|
||||
## Задача
|
||||
|
||||
Понять, **есть ли вообще нужные данные**, и где именно они доступны.
|
||||
|
||||
## Что сделать
|
||||
|
||||
Проверить отдельно:
|
||||
|
||||
### B1. Snapshot coverage
|
||||
|
||||
* какие snapshot-файлы реально содержат данные по РБП;
|
||||
* есть ли в них документ списания;
|
||||
* есть ли объекты РБП;
|
||||
* есть ли остатки/движения/проводки;
|
||||
* хватает ли snapshot-only, чтобы ответить на вопрос.
|
||||
|
||||
### B2. Live coverage
|
||||
|
||||
* какие MCP/live методы позволяют добраться до РБП-данных;
|
||||
* есть ли прямой путь до:
|
||||
|
||||
* документа списания,
|
||||
* объекта РБП,
|
||||
* остатка на конец периода,
|
||||
* движения списания,
|
||||
* schedule/основания;
|
||||
* что доступно напрямую, а что только через несколько шагов.
|
||||
|
||||
### B3. Coverage verdict
|
||||
|
||||
Для каждого обязательного элемента указать:
|
||||
|
||||
* `available_in_snapshot`
|
||||
* `available_via_live`
|
||||
* `available_but_not_used_by_runtime`
|
||||
* `not_reachable_in_current_runtime`
|
||||
|
||||
## Acceptance
|
||||
|
||||
* По каждому required entity должно быть ясно, **где оно лежит и как до него дотянуться**.
|
||||
* Должен появиться жёсткий ответ: проблема в отсутствии данных или в том, что runtime их не использует.
|
||||
|
||||
---
|
||||
|
||||
# Узел C — починить live route под РБП
|
||||
|
||||
## Задача
|
||||
|
||||
Сделать так, чтобы runtime **реально шёл** в нужный контур РБП, а не оставался на snapshot-only/semantic profile.
|
||||
|
||||
## Что сделать
|
||||
|
||||
1. Определить корректный `claim_type` для РБП-кейса, например:
|
||||
|
||||
* `prove_rbp_tail_state`
|
||||
* `prove_rbp_lifecycle_overstay`
|
||||
2. Для него прописать required live route:
|
||||
|
||||
* первый вызов на документ списания;
|
||||
* второй на объект РБП;
|
||||
* третий на движения/остатки;
|
||||
* четвёртый на подтверждение конца периода / хвоста.
|
||||
3. Проверить, что runtime действительно выбирает этот путь, а не остаётся в `canonical-only`.
|
||||
4. В debug payload вывести:
|
||||
|
||||
* `claim_type`
|
||||
* `required_live_calls`
|
||||
* `executed_live_calls`
|
||||
* `missing_live_calls`
|
||||
* `route_gap_reason`
|
||||
|
||||
## Acceptance
|
||||
|
||||
* У РБП-кейса должен появиться **непустой и осмысленный live call path**.
|
||||
* Live path должен быть привязан к claim, а не быть декоративным probe.
|
||||
|
||||
---
|
||||
|
||||
# Узел D — materialization: превратить данные по РБП в admissible evidence
|
||||
|
||||
## Задача
|
||||
|
||||
Убрать главный провал: данные/сигналы есть или могут быть, но до admissible evidence они не доезжают.
|
||||
|
||||
## Что сделать
|
||||
|
||||
Для РБП-кейса восстановить полный путь:
|
||||
|
||||
`raw source result -> candidate evidence -> admissible evidence -> answer`
|
||||
|
||||
И по каждому шагу показать:
|
||||
|
||||
* что пришло;
|
||||
* что было отрезано;
|
||||
* почему было отрезано;
|
||||
* что должно было стать admissible evidence, но не стало.
|
||||
|
||||
### Обязательно классифицировать причины reject-а
|
||||
|
||||
Использовать причины вида:
|
||||
|
||||
* `wrong_period`
|
||||
* `wrong_domain`
|
||||
* `weak_source_mapping`
|
||||
* `zero_live_match`
|
||||
* `missing_relation_reconstruction`
|
||||
* `missing_required_anchor`
|
||||
* `insufficient_object_identity`
|
||||
|
||||
### Цель
|
||||
|
||||
Не просто сделать `admissible > 0`, а понять, **какие именно evidence items должны считаться допустимыми для РБП proof**.
|
||||
|
||||
## Acceptance
|
||||
|
||||
* У РБП-кейса должно появиться **non-zero admissible evidence**, либо должно быть строго доказано, почему это невозможно на текущих данных.
|
||||
* Ответ “нет admissible evidence” должен быть объясним именно через materialization path.
|
||||
|
||||
---
|
||||
|
||||
# Узел E — финальный proof contract по РБП
|
||||
|
||||
## Задача
|
||||
|
||||
Сделать так, чтобы answer mode по РБП зависел от фактического proof-path, а не от общей слабой гипотезы.
|
||||
|
||||
## Что сделать
|
||||
|
||||
Финальный ответ по РБП должен собираться так:
|
||||
|
||||
### Если admissible evidence есть
|
||||
|
||||
Ответ должен уметь сказать:
|
||||
|
||||
* какие объекты РБП подтверждены;
|
||||
* по каким из них списание подтверждено;
|
||||
* по каким виден хвост/остаток на конец июля;
|
||||
* почему это похоже на “живёт дольше ожидаемого”.
|
||||
|
||||
### Если admissible evidence всё ещё нет
|
||||
|
||||
Ответ должен честно сказать:
|
||||
|
||||
* какое именно звено не удалось подтвердить;
|
||||
* не просто “сигнал слабый”, а:
|
||||
|
||||
* нет документа,
|
||||
* нет объекта,
|
||||
* нет движения,
|
||||
* нет остатка,
|
||||
* нет связи между ними.
|
||||
|
||||
## Acceptance
|
||||
|
||||
* РБП-кейс должен перестать быть общим lifecycle-туманом.
|
||||
* Answer mode должен быть привязан к реальному состоянию claim-proof.
|
||||
|
||||
---
|
||||
|
||||
## 6. Проверки
|
||||
|
||||
Обязательно выполнить:
|
||||
|
||||
1. replay исходного РБП-вопроса;
|
||||
2. debug/export после фикса;
|
||||
3. live call inventory;
|
||||
4. evidence conversion trace;
|
||||
5. before/after по answer mode.
|
||||
|
||||
Желательно дополнительно:
|
||||
|
||||
* один соседний month-close кейс на sanity-check;
|
||||
* один follow-up по тому же РБП-кейсу.
|
||||
|
||||
---
|
||||
|
||||
## 7. Метрики пакета
|
||||
|
||||
Добавить/обновить:
|
||||
|
||||
* `rbp_required_entity_coverage_rate`
|
||||
* `rbp_live_route_execution_rate`
|
||||
* `rbp_admissible_evidence_nonzero_rate`
|
||||
* `rbp_source_to_proof_completion_rate`
|
||||
* `rbp_partial_coverage_default_rate`
|
||||
* `rbp_false_grounded_answer_rate`
|
||||
|
||||
### Минимальные пороги
|
||||
|
||||
* `rbp_required_entity_coverage_rate >= 0.9`
|
||||
* `rbp_live_route_execution_rate >= 0.9`
|
||||
* `rbp_admissible_evidence_nonzero_rate > 0`
|
||||
* `rbp_false_grounded_answer_rate = 0`
|
||||
* `rbp_partial_coverage_default_rate` должно снизиться относительно текущего live baseline
|
||||
|
||||
---
|
||||
|
||||
## 8. Обязательные артефакты
|
||||
|
||||
В новой run-папке положить:
|
||||
|
||||
1. `README.md`
|
||||
2. `run_summary.json`
|
||||
3. `rbp_source_coverage_report.md`
|
||||
4. `rbp_live_route_report.md`
|
||||
5. `rbp_evidence_materialization_report.md`
|
||||
6. `rbp_claim_proof_report.md`
|
||||
7. `rbp_before_after_matrix.md`
|
||||
8. `chat_export_rbp.md`
|
||||
9. `debug_payloads/`
|
||||
10. `raw_live_calls/`
|
||||
11. `rbp_required_entity_map.json`
|
||||
12. `rbp_admissibility_reject_breakdown.json`
|
||||
|
||||
---
|
||||
|
||||
## 9. Что не делать
|
||||
|
||||
* не трогать НДС как главный фокус;
|
||||
* не расползаться на общую архитектуру;
|
||||
* не идти в новую большую волну по всем P0-доменам;
|
||||
* не закрывать пакет по summary без replay РБП-кейса;
|
||||
* не маскировать отсутствие данных красивым limited-answer.
|
||||
|
||||
---
|
||||
|
||||
## 10. Финальный verdict
|
||||
|
||||
В конце пакета выдать:
|
||||
|
||||
* `RBP_SOURCE_COVERAGE_FIXED / NOT_FIXED`
|
||||
* `RBP_LIVE_ROUTE_FIXED / NOT_FIXED`
|
||||
* `RBP_EVIDENCE_MATERIALIZATION_FIXED / NOT_FIXED`
|
||||
|
||||
И общий статус:
|
||||
|
||||
* `RBP_PACK_ACCEPTED`
|
||||
* или `RBP_PACK_ACCEPTED_WITH_LIMITATIONS`
|
||||
* или `RBP_PACK_NOT_ACCEPTED`
|
||||
|
||||
---
|
||||
|
||||
## 11. Ожидаемый результат
|
||||
|
||||
После этого пакета должно стать ясно:
|
||||
|
||||
* есть ли у вас вообще рабочий proof-path по РБП;
|
||||
* можно ли из текущих данных построить доказательный ответ;
|
||||
* если нельзя — это потому что данных реально нет, или потому что runtime не умеет до них дойти.
|
||||
|
||||
И главное:
|
||||
по РБП должно стать **невозможно** говорить абстрактно “слабая доказательная база”.
|
||||
Должно быть понятно, **что именно не доезжает и на каком узле**.
|
||||
|
||||
Если хочешь, следующим сообщением я дам ещё:
|
||||
|
||||
1. **понятное русское название этой волны**,
|
||||
2. **текст коммита на 3–4 строки**.
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,111 @@
|
|||
# 8 — Аудит source-to-proof по 3 контрольным вопросам (2026-03-29)
|
||||
|
||||
Статус: COMPLETED
|
||||
Этап: Stage 4 (P0-only)
|
||||
|
||||
## 1) Что проверялось
|
||||
|
||||
Главный вопрос аудита:
|
||||
**Есть ли в системе данные и маршруты, достаточные для ответа на 3 контрольных вопроса, и если да — на каком узле они теряются?**
|
||||
|
||||
Контрольные вопросы:
|
||||
1. НДС-цепочка (13/15 июля, мебель).
|
||||
2. РБП-хвост на 31 июля.
|
||||
3. Амортизация 31 июля (2 471,52 / 2 465,28 / 849,83).
|
||||
|
||||
## 2) Источники фактов (не summary-only)
|
||||
|
||||
Аудит выполнен на базе реальных replay-артефактов и code inspection:
|
||||
- `x:\1C\NDC_1C\docs\ARCH\8_audit_artifacts\question_replay_logs\1_live_replay.txt`
|
||||
- `x:\1C\NDC_1C\docs\ARCH\8_audit_artifacts\debug_payloads\*.json`
|
||||
- `x:\1C\NDC_1C\docs\ARCH\8_audit_artifacts\raw_live_calls\live_call_inventory_full_3_cases.json`
|
||||
- `x:\1C\NDC_1C\docs\ARCH\8_audit_artifacts\snapshot_samples\snapshot_inventory_runtime.json`
|
||||
- runtime code path (`assistantService`, `assistantDataLayer`, `assistantRuntimeGuards`, `assistantClaimBoundEvidence`, `answerComposer`)
|
||||
|
||||
## 3) Краткий итог по 3 кейсам
|
||||
|
||||
| Case | Claim | Reply mode | Admissible evidence | Ключевой исход |
|
||||
| --- | --- | --- | ---: | --- |
|
||||
| Q1 VAT (L1) | `prove_vat_chain_completeness` | grounded-positive | 12 | positive path работает |
|
||||
| Q2 RBP (L2) | `prove_rbp_tail_state` | limited | 0 | proof path не замкнут |
|
||||
| Q3 FA (L3) | `prove_month_close_state` | limited | 19 | evidence есть, но eligibility блокирует |
|
||||
|
||||
Сводные replay-метрики:
|
||||
- `live_temporal_contradiction_rate = 0`
|
||||
- `live_company_scope_resolution_rate = 1`
|
||||
- `live_admissible_evidence_nonzero_rate = 0.6667`
|
||||
- `live_partial_coverage_default_rate = 0.6667`
|
||||
|
||||
## 4) Ответ по узлам A–E
|
||||
|
||||
### Узел A — какие данные нужны
|
||||
- Карта обязательных сущностей/связок по каждому вопросу заполнена в `8A`.
|
||||
- Для Q2/Q3 текущий runtime source set не дает полный object-level набор для доказательного закрытия claim.
|
||||
|
||||
### Узел B — что реально есть в snapshot/live
|
||||
- Runtime подключен к ограниченному `2020экспорт` набору (7 JSON файлов).
|
||||
- Monthly as-of corpus физически есть (`2020_monthly_company_asof_full_test`), но не подключен текущим data layer.
|
||||
- Live MCP есть, но запрос broad (generic accounting register probe).
|
||||
|
||||
### Узел C — как реально идет маршрут
|
||||
- Q1: route корректный (`store_canonical + hybrid_store_plus_live`) -> grounded-positive.
|
||||
- Q2: route уходит в `store_canonical + store_canonical`, live verification path не используется.
|
||||
- Q3: route включает live (`store_feature_risk + hybrid_store_plus_live`), но mapping и anchors не закрывают eligibility.
|
||||
|
||||
### Узел D — как live превращается/не превращается в evidence
|
||||
- Q1: `fetched=24, matched=24`, admissible `12` -> live участвует как verification path.
|
||||
- Q2: live call отсутствует (route-level).
|
||||
- Q3: `fetched=24, matched=24`, admissible `19`, но proof блокируется на claim-anchor coverage.
|
||||
|
||||
### Узел E — что именно ломает ответ
|
||||
- Q1: не blocker; остаточный шум admissibility (`wrong_account_scope`, `weak_source_mapping`).
|
||||
- Q2: multi-break на route/source/evidence узлах.
|
||||
- Q3: multi-break на entity mapping + anchor coverage + live targeting specificity.
|
||||
|
||||
## 5) Вердикт по каждому вопросу (требуемый формат)
|
||||
|
||||
### Q1 — НДС
|
||||
Проблема в первую очередь:
|
||||
- **не** в отсутствии данных;
|
||||
- **не** в полном провале маршрута;
|
||||
- в комбинации: `wrong_live_call_target` + `admissibility_reject_not_due_to_data` (residual quality).
|
||||
|
||||
### Q2 — РБП
|
||||
Проблема в комбинации:
|
||||
- `source_not_connected_to_runtime`
|
||||
- `missing_source_data` (для object-level proof в активном source set)
|
||||
- `wrong_route_selection`
|
||||
- `evidence_not_materialized`
|
||||
- `admissibility_reject_not_due_to_data`
|
||||
|
||||
### Q3 — Амортизация
|
||||
Проблема в комбинации:
|
||||
- `wrong_entity_mapping`
|
||||
- `wrong_live_call_target`
|
||||
- `admissibility_reject_not_due_to_data`
|
||||
- `answer_layer_underuses_available_evidence` (через `claim_anchor_coverage_insufficient`)
|
||||
|
||||
## 6) Главный вывод аудита
|
||||
|
||||
**MULTI_NODE_FAILURE_CONFIRMED**
|
||||
|
||||
Почему:
|
||||
1. Один кейс (Q1) уже может идти в grounded-positive, значит контур не сломан тотально.
|
||||
2. Два кейса (Q2/Q3) ломаются в разных местах цепочки.
|
||||
3. Наблюдается не один первичный дефект, а связка: source coverage + routing + mapping + evidence materialization + eligibility handoff.
|
||||
|
||||
## 7) Что это означает для следующей fix-wave
|
||||
|
||||
Без redesign Stage 5/6, в рамках Stage 4 приоритетно чинить:
|
||||
1. Route и source-подключение для RBP/FA claim-path.
|
||||
2. Claim-targeted live query narrowing (не generic `TOP N` probe).
|
||||
3. Entity/anchor mapping для object-level month-close/FA доказательности.
|
||||
4. Admissibility tuning, чтобы уменьшить reject not-due-to-data.
|
||||
|
||||
См. детализацию в:
|
||||
- `8A` (required data map)
|
||||
- `8B` (coverage inventory)
|
||||
- `8C` (runtime replay matrix)
|
||||
- `8D` (live->evidence chain)
|
||||
- `8E` (gap register)
|
||||
- `8F` (code path inventory)
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
# 8A — Source Requirements Map
|
||||
|
||||
Дата: 2026-03-29
|
||||
Контрольные вопросы: Q1 НДС, Q2 РБП, Q3 Амортизация
|
||||
|
||||
## Q1 — НДС цепочка (13/15 июля)
|
||||
|
||||
| Блок доказательства | Что нужно для proof | Минимально обязательно | Что есть в runtime source set |
|
||||
| --- | --- | --- | --- |
|
||||
| Source docs | Поступление + реализация по тем же мебельным позициям | Да | Частично: `05_samples_RealizaciyaTovarovUslug.json`, `06_samples_PostuplenieTovarovUslug.json` |
|
||||
| Invoice layer | Счет-фактура / invoice linkage | Да | Частично через `08_samples_NDS_registers.json`, `09_samples_key_fields_...json` |
|
||||
| Tax/register layer | НДС регистры (покупки/продажи/предъявленный) | Да | Да: `08_samples_NDS_registers.json` |
|
||||
| Book layer | Запись книги покупок/продаж | Да | Частично (по available register records) |
|
||||
| Posting layer | Проводка и связка с документом | Да | Частично: snapshot + live MCP movement probe |
|
||||
| Link integrity | Документ → проводка → регистр → книга | Да | Частично; подтверждается не по всем звеньям без reject |
|
||||
|
||||
**Минимальный набор, без которого ответ всегда гипотетический:**
|
||||
1. Пара документов (receipt + sale) по одной предметной позиции.
|
||||
2. НДС-связка invoice/register/book.
|
||||
3. Подтвержденная posting/link связь на тот же период.
|
||||
|
||||
## Q2 — РБП хвост на 31 июля
|
||||
|
||||
| Блок доказательства | Что нужно для proof | Минимально обязательно | Что есть в runtime source set |
|
||||
| --- | --- | --- | --- |
|
||||
| Write-off document | Документ/операция «Списание РБП за июль» | Да | Неявно/недостаточно в подключенном наборе |
|
||||
| RBP object mapping | Объект РБП + параметр списания | Да | Недостаточно в подключенном snapshot profile |
|
||||
| Lifecycle | Начало/продолжение/списание РБП | Да | Недостаточно в подключенных источниках |
|
||||
| End-of-period residual | Остаток РБП на конец июля | Да | Не подтверждено admissible evidence |
|
||||
| Contradiction check | «нормальный остаток» vs «хвост дольше ожидаемого» | Да | Не подтверждено |
|
||||
|
||||
**Минимальный набор, без которого ответ всегда partial:**
|
||||
1. Явный write-off документ за июль.
|
||||
2. Трассировка по объекту РБП до остатка на конец месяца.
|
||||
3. Признак нормы/аномалии остатка с period-closure контекстом.
|
||||
|
||||
## Q3 — Амортизация (2 471,52 / 2 465,28 / 849,83)
|
||||
|
||||
| Блок доказательства | Что нужно для proof | Минимально обязательно | Что есть в runtime source set |
|
||||
| --- | --- | --- | --- |
|
||||
| Depreciation document | Документ начисления амортизации за июль | Да | Частично/косвенно |
|
||||
| FA object set | Полный expected набор ОС на июль | Да | Нет полного object-level набора в runtime snapshot profile |
|
||||
| Per-object fact | Начисление по каждому объекту ОС | Да | Частично, с weak mapping |
|
||||
| Sum reconciliation | Сверка сумм с объектами и периодом | Да | Частично, anchors по суммам есть, но claim coverage нестабильный |
|
||||
| Tail/risk check | Пропущенный объект vs нормальная картина | Да | Частично, итог limited из-за `claim_anchor_coverage_insufficient` |
|
||||
|
||||
**Минимальный набор, без которого ответ всегда partial:**
|
||||
1. Полный expected set ОС за июль.
|
||||
2. Связка объект ОС → начисление → проводка.
|
||||
3. Объектно-уровневая сверка сумм и пропусков.
|
||||
|
||||
## Cross-question mandatory core
|
||||
|
||||
Для всех трех вопросов обязательны:
|
||||
1. Жесткий периодный anchor (July 2020) как primary basis.
|
||||
2. Claim-bound required checks (не broad retrieval).
|
||||
3. Admissible evidence с source refs, не только candidate signals.
|
||||
4. Явная причина ограничения (какое звено не подтверждено), если proof не закрывается.
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
# 8B — Snapshot and Live Coverage Inventory
|
||||
|
||||
Дата: 2026-03-29
|
||||
Источник фактов: runtime wiring + replay artifacts в `x:\1C\NDC_1C\docs\ARCH\8_audit_artifacts`
|
||||
|
||||
## 1) Snapshot: что реально подключено runtime
|
||||
|
||||
Подключение подтверждено в `assistantDataLayer.ensureData`.
|
||||
|
||||
| Файл | Путь | Размер (байт) | Records | Использование |
|
||||
| --- | --- | ---: | ---: | --- |
|
||||
| `03_snapshot_fragment_problem_cases.json` | `x:\1C\NDC_1C\docs\ARCH\2020экспорт\03_snapshot_fragment_problem_cases.json` | 302520 | 80 | problem/risk signals |
|
||||
| `04_samples_SpisanieSRaschetnogoScheta.json` | `x:\1C\NDC_1C\docs\ARCH\2020экспорт\04_samples_SpisanieSRaschetnogoScheta.json` | 196178 | 27 | settlement/payment docs |
|
||||
| `05_samples_RealizaciyaTovarovUslug.json` | `x:\1C\NDC_1C\docs\ARCH\2020экспорт\05_samples_RealizaciyaTovarovUslug.json` | 132032 | 5 | realization docs |
|
||||
| `06_samples_PostuplenieTovarovUslug.json` | `x:\1C\NDC_1C\docs\ARCH\2020экспорт\06_samples_PostuplenieTovarovUslug.json` | 181409 | 10 | receipt docs |
|
||||
| `07_samples_DocumentJournals.json` | `x:\1C\NDC_1C\docs\ARCH\2020экспорт\07_samples_DocumentJournals.json` | 292931 | 80 | document journals |
|
||||
| `08_samples_NDS_registers.json` | `x:\1C\NDC_1C\docs\ARCH\2020экспорт\08_samples_NDS_registers.json` | 291547 | 80 | VAT registers |
|
||||
| `09_samples_key_fields_Recorder_Ref_Supplier_Buyer_Responsible.json` | `x:\1C\NDC_1C\docs\ARCH\2020экспорт\09_samples_key_fields_Recorder_Ref_Supplier_Buyer_Responsible.json` | 511133 | 140 | recorder/ref key fields |
|
||||
|
||||
## 2) Snapshot: что физически существует, но не подключено в текущий runtime path
|
||||
|
||||
| Набор | Путь | Состояние |
|
||||
| --- | --- | --- |
|
||||
| Monthly as-of corpus (12 файлов) | `x:\1C\NDC_1C\docs\ARCH\2020_monthly_company_asof_full_test` | Есть, файлы `snapshot_2020-01..12_asof_full.json` (42–46 MB каждый), но не подключены `assistantDataLayer` |
|
||||
| Monthly manifest | `x:\1C\NDC_1C\docs\ARCH\2020_monthly_company_asof_full_test\manifest_2020_monthly_company_asof_full.json` | Есть, показывает `entity_sets_total=2` (AccountingRegister only) |
|
||||
| `2020_monthly_company_asof_full` | `x:\1C\NDC_1C\docs\ARCH\2020_monthly_company_asof_full` | Папка есть, runtime ее не читает |
|
||||
|
||||
## 3) Live MCP/toolkit фактическое покрытие
|
||||
|
||||
| Параметр | Факт |
|
||||
| --- | --- |
|
||||
| Runtime live endpoint | `/api/execute_query` через MCP proxy |
|
||||
| Query template | Generic выборка из `РегистрБухгалтерии.Хозрасчетный` (`TOP __LIMIT__`, без claim-specific where) |
|
||||
| Фильтрация по account_scope в live query | Не задана (`account_scope: []` в live cases L1/L3) |
|
||||
| Роль live в текущем контуре | Overlay enrichment + post-filter через admissibility gate |
|
||||
|
||||
## 4) Coverage verdict по 3 вопросам
|
||||
|
||||
| Вопрос | Данные есть в принципе | Доступны runtime | Использованы runtime | Ключевой вывод |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Q1 VAT | Да (snapshot + live) | Да | Да | Positive grounding достижим, но с высоким reject шумом |
|
||||
| Q2 RBP | Частично | Частично | Ограниченно | Для proof path покрытие недостаточно, кейс остается limited |
|
||||
| Q3 FA amortization | Частично | Частично | Да, но нестабильно | Есть admissible evidence, но claim/object proof не замыкается |
|
||||
|
||||
## 5) Узел B — ответ в требуемом формате
|
||||
|
||||
- Q1 (НДС): данные есть и доступны; используются; узкое место — admissibility noise + generic live targeting.
|
||||
- Q2 (РБП): часть данных либо не в активном source set, либо не доезжает через текущий route; runtime usage недостаточен для proof.
|
||||
- Q3 (Амортизация): данные частично есть и используются, но не в форме, достаточной для object-complete proof.
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# 8C — Runtime Route Replay Matrix
|
||||
|
||||
Дата: 2026-03-29
|
||||
Replay база: `x:\1C\NDC_1C\docs\ARCH\8_audit_artifacts\question_replay_logs\1_live_replay.txt`
|
||||
|
||||
## Matrix (3 control questions)
|
||||
|
||||
| Поле | Q1 VAT (L1) | Q2 RBP (L2) | Q3 FA amortization (L3) |
|
||||
| --- | --- | --- | --- |
|
||||
| Raw user question | Поступление 13 июля + реализация 15 июля, полнота НДС-цепочки | Списание РБП 31 июля (в т.ч. 5 000), есть ли хвост | Амортизация 31 июля по 3 суммам, полный ли охват ОС |
|
||||
| Extracted anchors (ключевые) | period `2020-07-13`, `vat_signal`, `chain_signal` | period `2020-07-31`, amount `5 000`, `rbp_signal`, `writeoff_signal` | period `2020-07-31`, amounts `2 471,52/2 465,28/849,83` |
|
||||
| Claim / question type | `prove_vat_chain_completeness`, `which_chains_are_complete_vs_incomplete` | `prove_rbp_tail_state`, `what_is_it_grounded_on` | `prove_month_close_state`, `why_breaks` |
|
||||
| Business scope | raw/resolved: `company_specific_accounting` | raw/resolved: `company_specific_accounting` | raw/resolved: `company_specific_accounting` |
|
||||
| Temporal basis | raw `2020-07` → resolved `2020-07-13`, guard `passed` | raw `2020-07` → resolved `2020-07-31`, guard `passed` | raw `2020-07` → resolved `2020-07-31`, guard `passed` |
|
||||
| Selected route | `store_canonical` + `hybrid_store_plus_live` | `store_canonical` + `store_canonical` | `store_feature_risk` + `hybrid_store_plus_live` |
|
||||
| Selected source profile (semantic) | `settlements` + `vat,taxes` | `deferred_expense,period_close` | `fixed_assets,period_close` |
|
||||
| Snapshot source selection | Domain gate + semantic narrowing; docs + nds registers + key fields | Canonical docs/journals/key fields, без live | Risk + hybrid domain gate; problemCases/docs/journals/key fields |
|
||||
| Live call selection | Да (F2): `execute_query`, fetched 24, matched 24 | Нет (оба фрагмента canonical) | Да (F2): `execute_query`, fetched 24, matched 24 |
|
||||
| Retrieved raw entities (факт) | Документы поступления/реализации/списания | Нет material items в финальном normalized result | Преимущественно `NDFL` регистры + журналы + часть документов |
|
||||
| Candidate evidence total | 30 | 12 | 35 |
|
||||
| Admissible evidence | 12 | 0 | 19 |
|
||||
| Eligibility | `grounded_allowed` | `limited_or_insufficient_evidence` | `limited_or_insufficient_evidence` |
|
||||
| Final answer mode | `factual_with_explanation` / `grounded_positive` | `partial_coverage` / `limited_or_insufficient_evidence` | `partial_coverage` / `limited_or_insufficient_evidence` |
|
||||
|
||||
## Дополнительные наблюдения по маршруту
|
||||
|
||||
1. Q1: route корректный для chain-case, positive path сработал, но reject шум высокий (`weak_source_mapping`, `wrong_account_scope`).
|
||||
2. Q2: route не включает live claim-bound путь; фактически pipeline закрывается на canonical snapshot и обнуляется в admissibility.
|
||||
3. Q3: route включает live, но entity-level mapping уходит в нерелевантные регистры; claim anchors не покрыты, eligibility блокирует grounded.
|
||||
|
||||
## Узел C — требуемый ответ
|
||||
|
||||
- Есть случаи, где route правильный, но evidence не дожимается до полного proof (Q3).
|
||||
- Есть случай, где route в текущей конфигурации не выводит в verification path (Q2).
|
||||
- Есть случай, где route+source дают grounded-positive (Q1), но с остаточным качественным шумом по admissibility.
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
# 8D — Live Call to Evidence Matrix
|
||||
|
||||
Дата: 2026-03-29
|
||||
Источник:
|
||||
- `x:\1C\NDC_1C\docs\ARCH\8_audit_artifacts\raw_live_calls\live_mcp_to_evidence_handoff.json`
|
||||
- `x:\1C\NDC_1C\docs\ARCH\8_audit_artifacts\evidence_conversion_traces\L*_evidence_trace.json`
|
||||
|
||||
## Матрица live -> evidence
|
||||
|
||||
| Case | Live call | Method | Query subject | Fetched | Matched | Returned | Candidate evidence | Admissible evidence | Final mode |
|
||||
| --- | --- | --- | --- | ---: | ---: | ---: | ---: | ---: | --- |
|
||||
| Q1 VAT (L1) | Yes | `execute_query` | `vat_chain_conflict` | 24 | 24 | 12 | 30 | 12 | `grounded_positive` |
|
||||
| Q2 RBP (L2) | No | — | — | 0 | 0 | 0 | 12 | 0 | `limited_or_insufficient_evidence` |
|
||||
| Q3 FA (L3) | Yes | `execute_query` | `fixed_asset_card_mismatch` | 24 | 24 | 12 | 35 | 19 | `limited_or_insufficient_evidence` |
|
||||
|
||||
## Evidence conversion breakdown
|
||||
|
||||
### Q1 VAT
|
||||
- `raw source result`: live rows + snapshot chain candidates.
|
||||
- `candidate -> admissible`: `30 -> 12`.
|
||||
- `reject reasons`: `wrong_account_scope=12`, `weak_source_mapping=14`.
|
||||
- `роль live`: verification path (не purely decorative), потому что кейс вышел в grounded-positive.
|
||||
|
||||
### Q2 RBP
|
||||
- `raw source result`: live route не выбран (оба фрагмента `store_canonical`).
|
||||
- `candidate -> admissible`: `12 -> 0`.
|
||||
- `reject reasons`: `wrong_period=36`, `weak_source_mapping=12`.
|
||||
- `роль live`: отсутствует в этом кейсе из-за route selection, не из-за MCP downtime.
|
||||
|
||||
### Q3 FA
|
||||
- `raw source result`: live rows есть, плюс snapshot risk/hybrid источники.
|
||||
- `candidate -> admissible`: `35 -> 19`.
|
||||
- `reject reasons`: `wrong_domain=8`, `wrong_account_scope=8`, `weak_source_mapping=16`, `future_dated_or_out_of_window=8`.
|
||||
- `роль live`: частично verification, но admissible evidence не конвертируется в grounded из-за claim-anchor gap.
|
||||
|
||||
## Узел D — ответы в требуемом формате
|
||||
|
||||
1. Был ли live декоративным enrichment или verification path?
|
||||
- Q1: verification path.
|
||||
- Q2: live path не был выбран.
|
||||
- Q3: частично verification, но недожатый до proof.
|
||||
|
||||
2. Если строки пришли, почему не стали admissible evidence полностью?
|
||||
- Из-за `wrong_account_scope`, `wrong_domain`, `weak_source_mapping`, `future_dated_or_out_of_window`.
|
||||
|
||||
3. Если строки не пришли (или call отсутствует), где проблема?
|
||||
- В Q2 проблема в route selection + source profile, а не в технической недоступности MCP.
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
# 8E — Source-to-Proof Gap Register
|
||||
|
||||
Дата: 2026-03-29
|
||||
|
||||
## Severity scale
|
||||
- `blocker`: без исправления невозможно закрыть proof path по целевому вопросу.
|
||||
- `high`: сильно влияет на grounded eligibility и стабильность.
|
||||
- `medium`: не блокирует всегда, но создает деградации/шум.
|
||||
|
||||
## Gap table
|
||||
|
||||
| Gap ID | Вопрос | Категория | Severity | Где рвется | Доказательство |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| GAP-8E-01 | Q2, Q3 | `source_not_connected_to_runtime` | blocker | Runtime читает ограниченный `2020экспорт`; monthly as-of corpus не включен в data layer | `8B`, `8F`, `snapshot_inventory_runtime.json` |
|
||||
| GAP-8E-02 | Q2 | `missing_source_data` | high | Для RBP не подтверждаются object-level writeoff/residual звенья в активном source set | `L2_evidence_trace.json`, `8A` |
|
||||
| GAP-8E-03 | Q2 | `wrong_route_selection` | high | Оба фрагмента routed в `store_canonical`, live verification path не включается | `runtime_route_snapshot.json`, `8C` |
|
||||
| GAP-8E-04 | Q3 | `wrong_entity_mapping` | high | FA claim тянет нерелевантные сущности (NDFL-регистры) как опору | `L3_evidence_trace.json`, `8C` |
|
||||
| GAP-8E-05 | Q1, Q3 | `wrong_live_call_target` | high | Live `execute_query` идет без claim/account фильтра (`account_scope=[]`) | `live_call_inventory_full_3_cases.json`, `8F` |
|
||||
| GAP-8E-06 | Q2 | `evidence_not_materialized` | high | `candidate_evidence_total=12`, `admissible_evidence_count=0` | `L2_evidence_trace.json`, `8D` |
|
||||
| GAP-8E-07 | Q2, Q3 | `admissibility_reject_not_due_to_data` | high | Существенный reject из-за gate mismatch (`wrong_period`, `wrong_domain`, `wrong_account_scope`, `weak_source_mapping`) | `admissibility_reject_breakdown_live.json` |
|
||||
| GAP-8E-08 | Q3 | `answer_layer_underuses_available_evidence` | medium | При `admissible_evidence_count=19` ответ остается limited из-за `claim_anchor_coverage_insufficient` | `L3_evidence_trace.json`, `8C` |
|
||||
|
||||
## Question-specific final failure map
|
||||
|
||||
### Q1 VAT
|
||||
- Что надо доказать: полнота НДС-цепочки document -> posting -> tax/register -> book.
|
||||
- Что найдено: admissible evidence есть (`12`), кейс grounded-positive.
|
||||
- Где остается риск: высокий reject шум и generic live target.
|
||||
- Типы разрыва: `wrong_live_call_target`, `admissibility_reject_not_due_to_data` (residual).
|
||||
|
||||
### Q2 RBP
|
||||
- Что надо доказать: наличие/отсутствие хвоста РБП на конец июля по объектам.
|
||||
- Что найдено: targeted checks `not_found`, admissible `0`.
|
||||
- Где рвется: route + source coverage + evidence materialization.
|
||||
- Типы разрыва: `source_not_connected_to_runtime`, `missing_source_data`, `wrong_route_selection`, `evidence_not_materialized`, `admissibility_reject_not_due_to_data`.
|
||||
|
||||
### Q3 Амортизация
|
||||
- Что надо доказать: полный object-level охват амортизации за июль.
|
||||
- Что найдено: admissible `19`, но eligibility blocked (`claim_anchor_coverage_insufficient`).
|
||||
- Где рвется: entity mapping + claim anchor coverage + live target specificity.
|
||||
- Типы разрыва: `wrong_entity_mapping`, `wrong_live_call_target`, `admissibility_reject_not_due_to_data`, `answer_layer_underuses_available_evidence`.
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
# 8F — Code Path Inventory
|
||||
|
||||
Дата: 2026-03-29
|
||||
Scope: Stage 4 P0 source-to-proof аудит по 3 контрольным вопросам (VAT / RBP / FA)
|
||||
|
||||
## 1) Основной runtime path (end-to-end)
|
||||
|
||||
| Узел | Файл | Ключевые функции / точки | Роль в source-to-proof |
|
||||
| --- | --- | --- | --- |
|
||||
| Normalization | `x:\1C\NDC_1C\llm_normalizer\backend\src\services\normalizerService.ts` | `inferTimeScope` (360), `business_scope` extraction (428, 490), `normalize` (1036) | Разбивка вопроса, базовые anchors, route hint summary input. |
|
||||
| Route decision | `x:\1C\NDC_1C\llm_normalizer\backend\src\services\routeHintAdapter.ts` | deterministic v2 summary (422, 458), route/no-route status (327-377) | Детальный выбор маршрута по fragment-ам. |
|
||||
| Orchestration | `x:\1C\NDC_1C\llm_normalizer\backend\src\services\assistantService.ts` | `AssistantService` (1338), вызовы guard/claim/data/composer (1397-1536), debug export (1588-1734) | Склейка всех стадий: normalize → route → fetch → evidence gates → answer mode. |
|
||||
| Snapshot/Live fetch | `x:\1C\NDC_1C\llm_normalizer\backend\src\services\assistantDataLayer.ts` | `executeRouteRuntime` (2522), `executeHybrid` (2893), `executeCanonical` (3683), `executeRisk` (3352), `ensureData` (2856), MCP query template (140, 2591-2592) | Реальный data access к snapshot + live MCP overlay. |
|
||||
| Claim anchors | `x:\1C\NDC_1C\llm_normalizer\backend\src\services\assistantClaimBoundEvidence.ts` | `resolveClaimBoundAnchors` (201), `requiredChecksByClaim` (305), `applyTargetedEvidenceAcquisition` (540) | Claim-type и required checks для P0 цепочек доказательства. |
|
||||
| Temporal/polarity/admissibility | `x:\1C\NDC_1C\llm_normalizer\backend\src\services\assistantRuntimeGuards.ts` | `resolveTemporalGuard` (633), `resolveDomainPolarityGuard` (754), `applyDomainPolarityGuardToRetrievalResults` (934), `applyEvidenceAdmissibilityGate` (1273), `evaluateGroundedAnswerEligibility` (1421) | Где candidate evidence отсекается и где решается eligibility. |
|
||||
| Evidence normalization | `x:\1C\NDC_1C\llm_normalizer\backend\src\services\retrievalResultNormalizer.ts` | `normalizeEvidenceItems` (457), `normalizeRetrievalResult` (508) | Перевод raw fetch в unified evidence/candidate structure. |
|
||||
| Final answer mode | `x:\1C\NDC_1C\llm_normalizer\backend\src\services\answerComposer.ts` | `composeAssistantAnswer` (4451), `partial_coverage` ветки (1833, 4531, 4557), `coverage_partial_or_limited` (2908, 4368) | Финальное решение grounded vs partial и what/why/limitations слой. |
|
||||
|
||||
## 2) Source inventory wiring (факт подключения)
|
||||
|
||||
`assistantDataLayer.ensureData` (2856+) подключает только:
|
||||
- `03_snapshot_fragment_problem_cases.json`
|
||||
- `04_samples_SpisanieSRaschetnogoScheta.json`
|
||||
- `05_samples_RealizaciyaTovarovUslug.json`
|
||||
- `06_samples_PostuplenieTovarovUslug.json`
|
||||
- `07_samples_DocumentJournals.json`
|
||||
- `08_samples_NDS_registers.json`
|
||||
- `09_samples_key_fields_Recorder_Ref_Supplier_Buyer_Responsible.json`
|
||||
|
||||
Root для этих файлов: `ARCH_EXPORT_2020_DIR` из `config.ts` (`x:\1C\NDC_1C\docs\ARCH\2020экспорт`).
|
||||
|
||||
## 3) Live MCP wiring (факт вызова)
|
||||
|
||||
- В `assistantDataLayer.ts` live overlay строится через `/api/execute_query`.
|
||||
- Текущий live query template (`MCP_LIVE_MOVEMENTS_QUERY_TEMPLATE`, строка 140+) — generic запрос в `РегистрБухгалтерии.Хозрасчетный` с `TOP __LIMIT__`, без claim-specific фильтров по document/object/account.
|
||||
- Значит live path есть, но он broad и требует сильного post-filter/admissibility, иначе evidence не доезжает до proof.
|
||||
|
||||
## 4) Где формально рвется source-to-proof
|
||||
|
||||
- Q2 (RBP): разрыв раньше live path (route в canonical, live call не выбран), далее admissibility обнуляет evidence.
|
||||
- Q3 (FA): source/evidence есть, но claim anchor coverage и entity mapping не дотягивают до eligibility.
|
||||
- Q1 (VAT): positive path работает, но с высоким объемом reject (`weak_source_mapping`, `wrong_account_scope`).
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
# Chat Export (3 Control Questions)
|
||||
|
||||
Источник replay: `x:\1C\NDC_1C\docs\ARCH\8_audit_artifacts\question_replay_logs\1_live_replay.txt`
|
||||
|
||||
## Q1 — НДС (L1)
|
||||
**User question**
|
||||
13 июля проведено поступление товаров, а 15 июля — реализация этих же мебельных позиций. НДС-цепочка по этим движениям у нас полная или где-то есть выпадение между документом, проводкой и налоговым отражением?
|
||||
|
||||
**Runtime outcome**
|
||||
- `reply_type`: `factual_with_explanation`
|
||||
- `claim_type`: `prove_vat_chain_completeness`
|
||||
- `grounding_mode`: `grounded_positive`
|
||||
- `admissible_evidence_count`: `12`
|
||||
- `eligibility_outcome`: `grounded_allowed`
|
||||
- `reason_codes`: none
|
||||
|
||||
## Q2 — РБП (L2)
|
||||
**User question**
|
||||
31 июля прошло «Списание РБП за Июль 2020 г.», в том числе на 5 000 и ещё несколько сумм. Есть ли в базе признаки, что часть РБП к концу июля всё ещё живёт дольше ожидаемого?
|
||||
|
||||
**Runtime outcome**
|
||||
- `reply_type`: `partial_coverage`
|
||||
- `claim_type`: `prove_rbp_tail_state`
|
||||
- `grounding_mode`: `limited_or_insufficient_evidence`
|
||||
- `admissible_evidence_count`: `0`
|
||||
- `eligibility_outcome`: `limited_or_insufficient_evidence`
|
||||
- `reason_codes`: `admissible_evidence_count_zero`, `targeted_evidence_hit_rate_zero`
|
||||
|
||||
## Q3 — Амортизация (L3)
|
||||
**User question**
|
||||
31 июля начислена амортизация тремя суммами — 2 471,52, 2 465,28 и 849,83. Это похоже на полное начисление по всем нужным объектам за июль или есть риск, что какой-то объект ОС в июле не попал в амортизацию?
|
||||
|
||||
**Runtime outcome**
|
||||
- `reply_type`: `partial_coverage`
|
||||
- `claim_type`: `prove_month_close_state`
|
||||
- `grounding_mode`: `limited_or_insufficient_evidence`
|
||||
- `admissible_evidence_count`: `19`
|
||||
- `eligibility_outcome`: `limited_or_insufficient_evidence`
|
||||
- `reason_codes`: `claim_anchor_coverage_insufficient`
|
||||
|
||||
## Быстрый итог по 3 вопросам
|
||||
- 1 кейс вышел в `grounded_positive`.
|
||||
- 2 кейса остались в `partial_coverage`.
|
||||
- Основные причины ограничения: `admissible_evidence_count_zero` (Q2) и `claim_anchor_coverage_insufficient` (Q3).
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,127 @@
|
|||
{
|
||||
"case_id": "L1",
|
||||
"label": "vat_chain_furniture_13_15_july",
|
||||
"reply_type": "factual_with_explanation",
|
||||
"question_type_class": "which_chains_are_complete_vs_incomplete",
|
||||
"claim_type": "prove_vat_chain_completeness",
|
||||
"claim_anchor_audit": {
|
||||
"required_anchors": [
|
||||
"period",
|
||||
"document_types",
|
||||
"vat_signal",
|
||||
"chain_signal"
|
||||
],
|
||||
"missing_anchors": [
|
||||
"document_types"
|
||||
],
|
||||
"claim_anchor_resolution_rate": 0.75,
|
||||
"primary_period": {
|
||||
"from": "2020-07-13",
|
||||
"to": "2020-07-13",
|
||||
"granularity": "day"
|
||||
},
|
||||
"allowed_context_window": {
|
||||
"from": "2019-07-14",
|
||||
"to": "2021-07-13",
|
||||
"granularity": "month"
|
||||
}
|
||||
},
|
||||
"targeted_evidence_acquisition": {
|
||||
"required_checks": [
|
||||
"source_document_found",
|
||||
"invoice_found",
|
||||
"tax_register_entry_found",
|
||||
"book_entry_found",
|
||||
"chain_linkage_status"
|
||||
],
|
||||
"check_status": {
|
||||
"source_document_found": "found",
|
||||
"invoice_found": "found",
|
||||
"tax_register_entry_found": "found",
|
||||
"book_entry_found": "found",
|
||||
"chain_linkage_status": "found"
|
||||
},
|
||||
"targeted_item_hits": 20,
|
||||
"targeted_evidence_hits": 30,
|
||||
"targeted_evidence_hit_rate": 1
|
||||
},
|
||||
"evidence_gate": {
|
||||
"candidate_evidence_total": 30,
|
||||
"admissible_evidence_count": 12,
|
||||
"rejected_evidence_count": 18,
|
||||
"reject_breakdown": {
|
||||
"wrong_period": 0,
|
||||
"wrong_domain": 0,
|
||||
"wrong_account_scope": 12,
|
||||
"weak_source_mapping": 14,
|
||||
"zero_live_match": 0,
|
||||
"future_dated_or_out_of_window": 0
|
||||
},
|
||||
"category_breakdown": {
|
||||
"hard_evidence": 4,
|
||||
"supporting_signal": 8,
|
||||
"inadmissible_noise": 18
|
||||
}
|
||||
},
|
||||
"eligibility": {
|
||||
"eligible": true,
|
||||
"grounding_mode": "grounded_positive",
|
||||
"outcome": "grounded_allowed",
|
||||
"reason_codes": [
|
||||
|
||||
],
|
||||
"temporal_passed": true,
|
||||
"business_scope_passed": true,
|
||||
"claim_anchors_passed": true,
|
||||
"admissible_evidence_count": 12
|
||||
},
|
||||
"temporal": {
|
||||
"raw_time_scope": "2020-07",
|
||||
"resolved_time_anchor": "2020-07-13",
|
||||
"effective_primary_period": {
|
||||
"from": "2020-07-13",
|
||||
"to": "2020-07-13",
|
||||
"granularity": "day"
|
||||
},
|
||||
"temporal_alignment_status": "corrected",
|
||||
"temporal_guard_basis": "resolved_primary_period",
|
||||
"temporal_guard_outcome": "passed",
|
||||
"eligibility_time_basis": "resolved_primary_period"
|
||||
},
|
||||
"business_scope": {
|
||||
"raw": [
|
||||
"company_specific_accounting"
|
||||
],
|
||||
"resolved": [
|
||||
"company_specific_accounting"
|
||||
],
|
||||
"company_scope_resolution_reason": [
|
||||
"temporal_claim_bound_company_scope_recovery"
|
||||
]
|
||||
},
|
||||
"numeric_anchor_cleanup": {
|
||||
"raw_numeric_tokens": [
|
||||
"13",
|
||||
"15"
|
||||
],
|
||||
"classified_numeric_tokens": [
|
||||
{
|
||||
"token": "13",
|
||||
"classification": "account_token"
|
||||
},
|
||||
{
|
||||
"token": "15",
|
||||
"classification": "other_numeric"
|
||||
}
|
||||
],
|
||||
"rejected_as_non_accounts": [
|
||||
"15"
|
||||
],
|
||||
"resolved_account_anchors": [
|
||||
"13"
|
||||
],
|
||||
"normalized_primary_accounts": [
|
||||
null
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
{
|
||||
"case_id": "L2",
|
||||
"label": "rbp_tail_31_july_5000",
|
||||
"reply_type": "partial_coverage",
|
||||
"question_type_class": "what_is_it_grounded_on",
|
||||
"claim_type": "prove_rbp_tail_state",
|
||||
"claim_anchor_audit": {
|
||||
"required_anchors": [
|
||||
"period",
|
||||
"rbp_signal",
|
||||
"writeoff_signal"
|
||||
],
|
||||
"missing_anchors": [
|
||||
|
||||
],
|
||||
"claim_anchor_resolution_rate": 1,
|
||||
"primary_period": {
|
||||
"from": "2020-07-31",
|
||||
"to": "2020-07-31",
|
||||
"granularity": "day"
|
||||
},
|
||||
"allowed_context_window": {
|
||||
"from": "2019-08-01",
|
||||
"to": "2021-07-31",
|
||||
"granularity": "month"
|
||||
}
|
||||
},
|
||||
"targeted_evidence_acquisition": {
|
||||
"required_checks": [
|
||||
"rbp_writeoff_lifecycle_confirmed",
|
||||
"residual_tail_found",
|
||||
"close_contradiction_or_normal_residual"
|
||||
],
|
||||
"check_status": {
|
||||
"rbp_writeoff_lifecycle_confirmed": "not_found",
|
||||
"residual_tail_found": "not_found",
|
||||
"close_contradiction_or_normal_residual": "not_found"
|
||||
},
|
||||
"targeted_item_hits": 0,
|
||||
"targeted_evidence_hits": 0,
|
||||
"targeted_evidence_hit_rate": 0
|
||||
},
|
||||
"evidence_gate": {
|
||||
"candidate_evidence_total": 12,
|
||||
"admissible_evidence_count": 0,
|
||||
"rejected_evidence_count": 12,
|
||||
"reject_breakdown": {
|
||||
"wrong_period": 36,
|
||||
"wrong_domain": 0,
|
||||
"wrong_account_scope": 0,
|
||||
"weak_source_mapping": 12,
|
||||
"zero_live_match": 0,
|
||||
"future_dated_or_out_of_window": 0
|
||||
},
|
||||
"category_breakdown": {
|
||||
"hard_evidence": 0,
|
||||
"supporting_signal": 0,
|
||||
"inadmissible_noise": 12
|
||||
}
|
||||
},
|
||||
"eligibility": {
|
||||
"eligible": false,
|
||||
"grounding_mode": "limited_or_insufficient_evidence",
|
||||
"outcome": "limited_or_insufficient_evidence",
|
||||
"reason_codes": [
|
||||
"admissible_evidence_count_zero",
|
||||
"targeted_evidence_hit_rate_zero"
|
||||
],
|
||||
"temporal_passed": true,
|
||||
"business_scope_passed": true,
|
||||
"claim_anchors_passed": true,
|
||||
"admissible_evidence_count": 0
|
||||
},
|
||||
"temporal": {
|
||||
"raw_time_scope": "2020-07",
|
||||
"resolved_time_anchor": "2020-07-31",
|
||||
"effective_primary_period": {
|
||||
"from": "2020-07-31",
|
||||
"to": "2020-07-31",
|
||||
"granularity": "day"
|
||||
},
|
||||
"temporal_alignment_status": "corrected",
|
||||
"temporal_guard_basis": "resolved_primary_period",
|
||||
"temporal_guard_outcome": "passed",
|
||||
"eligibility_time_basis": "resolved_primary_period"
|
||||
},
|
||||
"business_scope": {
|
||||
"raw": [
|
||||
"company_specific_accounting"
|
||||
],
|
||||
"resolved": [
|
||||
"company_specific_accounting"
|
||||
],
|
||||
"company_scope_resolution_reason": [
|
||||
"temporal_claim_bound_company_scope_recovery"
|
||||
]
|
||||
},
|
||||
"numeric_anchor_cleanup": {
|
||||
"raw_numeric_tokens": [
|
||||
"31",
|
||||
"2020",
|
||||
"5",
|
||||
"000"
|
||||
],
|
||||
"classified_numeric_tokens": [
|
||||
{
|
||||
"token": "31",
|
||||
"classification": "other_numeric"
|
||||
}
|
||||
],
|
||||
"rejected_as_non_accounts": [
|
||||
"31"
|
||||
],
|
||||
"resolved_account_anchors": [
|
||||
|
||||
],
|
||||
"normalized_primary_accounts": [
|
||||
null
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
{
|
||||
"case_id": "L3",
|
||||
"label": "fa_amortization_2471_2465_849",
|
||||
"reply_type": "partial_coverage",
|
||||
"question_type_class": "why_breaks",
|
||||
"claim_type": "prove_month_close_state",
|
||||
"claim_anchor_audit": {
|
||||
"required_anchors": [
|
||||
"period",
|
||||
"close_signal",
|
||||
"cost_scope"
|
||||
],
|
||||
"missing_anchors": [
|
||||
"close_signal",
|
||||
"cost_scope"
|
||||
],
|
||||
"claim_anchor_resolution_rate": 0.3333,
|
||||
"primary_period": {
|
||||
"from": "2020-07-31",
|
||||
"to": "2020-07-31",
|
||||
"granularity": "day"
|
||||
},
|
||||
"allowed_context_window": {
|
||||
"from": "2019-08-01",
|
||||
"to": "2021-07-31",
|
||||
"granularity": "month"
|
||||
}
|
||||
},
|
||||
"targeted_evidence_acquisition": {
|
||||
"required_checks": [
|
||||
"close_operation_found",
|
||||
"distribution_step_found",
|
||||
"residual_tail_found"
|
||||
],
|
||||
"check_status": {
|
||||
"close_operation_found": "found",
|
||||
"distribution_step_found": "found",
|
||||
"residual_tail_found": "found"
|
||||
},
|
||||
"targeted_item_hits": 23,
|
||||
"targeted_evidence_hits": 35,
|
||||
"targeted_evidence_hit_rate": 1
|
||||
},
|
||||
"evidence_gate": {
|
||||
"candidate_evidence_total": 35,
|
||||
"admissible_evidence_count": 19,
|
||||
"rejected_evidence_count": 16,
|
||||
"reject_breakdown": {
|
||||
"wrong_period": 0,
|
||||
"wrong_domain": 8,
|
||||
"wrong_account_scope": 8,
|
||||
"weak_source_mapping": 16,
|
||||
"zero_live_match": 0,
|
||||
"future_dated_or_out_of_window": 8
|
||||
},
|
||||
"category_breakdown": {
|
||||
"hard_evidence": 8,
|
||||
"supporting_signal": 11,
|
||||
"inadmissible_noise": 16
|
||||
}
|
||||
},
|
||||
"eligibility": {
|
||||
"eligible": false,
|
||||
"grounding_mode": "limited_or_insufficient_evidence",
|
||||
"outcome": "limited_or_insufficient_evidence",
|
||||
"reason_codes": [
|
||||
"claim_anchor_coverage_insufficient"
|
||||
],
|
||||
"temporal_passed": true,
|
||||
"business_scope_passed": true,
|
||||
"claim_anchors_passed": false,
|
||||
"admissible_evidence_count": 19
|
||||
},
|
||||
"temporal": {
|
||||
"raw_time_scope": "2020-07",
|
||||
"resolved_time_anchor": "2020-07-31",
|
||||
"effective_primary_period": {
|
||||
"from": "2020-07-31",
|
||||
"to": "2020-07-31",
|
||||
"granularity": "day"
|
||||
},
|
||||
"temporal_alignment_status": "corrected",
|
||||
"temporal_guard_basis": "resolved_primary_period",
|
||||
"temporal_guard_outcome": "passed",
|
||||
"eligibility_time_basis": "resolved_primary_period"
|
||||
},
|
||||
"business_scope": {
|
||||
"raw": [
|
||||
"company_specific_accounting"
|
||||
],
|
||||
"resolved": [
|
||||
"company_specific_accounting"
|
||||
],
|
||||
"company_scope_resolution_reason": [
|
||||
"temporal_claim_bound_company_scope_recovery"
|
||||
]
|
||||
},
|
||||
"numeric_anchor_cleanup": {
|
||||
"raw_numeric_tokens": [
|
||||
"31",
|
||||
"2",
|
||||
"471,52",
|
||||
"465,28",
|
||||
"849,83"
|
||||
],
|
||||
"classified_numeric_tokens": [
|
||||
{
|
||||
"token": "31",
|
||||
"classification": "other_numeric"
|
||||
},
|
||||
{
|
||||
"token": "52",
|
||||
"classification": "amount_token"
|
||||
},
|
||||
{
|
||||
"token": "28",
|
||||
"classification": "amount_token"
|
||||
},
|
||||
{
|
||||
"token": "83",
|
||||
"classification": "amount_token"
|
||||
}
|
||||
],
|
||||
"rejected_as_non_accounts": [
|
||||
"31",
|
||||
"52",
|
||||
"28",
|
||||
"83"
|
||||
],
|
||||
"resolved_account_anchors": [
|
||||
|
||||
],
|
||||
"normalized_primary_accounts": [
|
||||
null
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"generated_at": "2026-03-29T05:48:19.981Z",
|
||||
"aggregate": {
|
||||
"wrong_period": 36,
|
||||
"wrong_domain": 8,
|
||||
"wrong_account_scope": 20,
|
||||
"weak_source_mapping": 42,
|
||||
"zero_live_match": 0,
|
||||
"future_dated_or_out_of_window": 8
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "L1",
|
||||
"label": "vat_chain_furniture_13_15_july",
|
||||
"reject_breakdown": {
|
||||
"wrong_period": 0,
|
||||
"wrong_domain": 0,
|
||||
"wrong_account_scope": 12,
|
||||
"weak_source_mapping": 14,
|
||||
"zero_live_match": 0,
|
||||
"future_dated_or_out_of_window": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "L2",
|
||||
"label": "rbp_tail_31_july_5000",
|
||||
"reject_breakdown": {
|
||||
"wrong_period": 36,
|
||||
"wrong_domain": 0,
|
||||
"wrong_account_scope": 0,
|
||||
"weak_source_mapping": 12,
|
||||
"zero_live_match": 0,
|
||||
"future_dated_or_out_of_window": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "L3",
|
||||
"label": "fa_amortization_2471_2465_849",
|
||||
"reject_breakdown": {
|
||||
"wrong_period": 0,
|
||||
"wrong_domain": 8,
|
||||
"wrong_account_scope": 8,
|
||||
"weak_source_mapping": 16,
|
||||
"zero_live_match": 0,
|
||||
"future_dated_or_out_of_window": 8
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,7 @@
|
|||
# Live Case Matrix
|
||||
|
||||
| Case | Label | Reply | Claim Type | Admissible Evidence | Grounding Mode | Scope | Temporal |
|
||||
| --- | --- | --- | --- | ---: | --- | --- | --- |
|
||||
| L1 | vat_chain_furniture_13_15_july | factual_with_explanation | prove_vat_chain_completeness | 12 | grounded_positive | company_specific_accounting | passed |
|
||||
| L2 | rbp_tail_31_july_5000 | partial_coverage | prove_rbp_tail_state | 0 | limited_or_insufficient_evidence | company_specific_accounting | passed |
|
||||
| L3 | fa_amortization_2471_2465_849 | partial_coverage | prove_month_close_state | 19 | limited_or_insufficient_evidence | company_specific_accounting | passed |
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# Live Replay Report (Wave 19.2)
|
||||
|
||||
## Source
|
||||
- Source of truth replayed from: `X:\1C\NDC_1C\llm_normalizer\docs\runs\2026-03-29_Stage_04_Wave_19_1_Live_Alignment_Fix_Claim_Bound_Runtime\1.txt`
|
||||
- Replayed exactly 3 user turns from the original export.
|
||||
- Runtime path: MCP ON, useMock=true.
|
||||
|
||||
## Metrics
|
||||
- live_temporal_contradiction_rate: 0
|
||||
- live_company_scope_resolution_rate: 1
|
||||
- live_admissible_evidence_nonzero_rate: 0.6667
|
||||
- live_partial_coverage_default_rate: 0.6667
|
||||
- baseline_partial_coverage_default_rate: 1
|
||||
- live_claim_path_completion_rate: 0.6667
|
||||
- live_false_grounded_answer_rate: 0
|
||||
|
||||
## Verdict
|
||||
- LIVE_TEMPORAL_ALIGNMENT_FIXED: FIXED
|
||||
- LIVE_COMPANY_SCOPE_FIXED: FIXED
|
||||
- LIVE_EVIDENCE_PATH_FIXED: FIXED
|
||||
- LIVE_PARTIAL_COVERAGE_DEFAULT_REDUCED: REDUCED
|
||||
- Overall: WAVE19_2_ACCEPTED
|
||||
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"generated_at": "2026-03-29T09:22:59",
|
||||
"cases": [
|
||||
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"run_id": "2026-03-29_Stage_04_Wave_19_2_Live_Runtime_Fix_Replay_1txt",
|
||||
"stage": "Stage_04",
|
||||
"wave": "Wave_19_2",
|
||||
"scope": "live_runtime_fix_by_replay_1txt",
|
||||
"source_of_truth": "X:\\1C\\NDC_1C\\llm_normalizer\\docs\\runs\\2026-03-29_Stage_04_Wave_19_1_Live_Alignment_Fix_Claim_Bound_Runtime\\1.txt",
|
||||
"execution": {
|
||||
"replay_mode": "exact_questions_from_1_txt",
|
||||
"runtime_path": "assistant_message_with_mcp_runtime_on",
|
||||
"normalizer_mode": "useMock=true",
|
||||
"session_id": "asst-wave19_2-1774763298275"
|
||||
},
|
||||
"thresholds": {
|
||||
"live_temporal_contradiction_rate": 0,
|
||||
"live_company_scope_resolution_rate": 1,
|
||||
"live_false_grounded_answer_rate": 0,
|
||||
"live_admissible_evidence_nonzero_min_cases": 2
|
||||
},
|
||||
"metrics": {
|
||||
"case_count": 3,
|
||||
"baseline_partial_coverage_default_rate": 1,
|
||||
"live_temporal_contradiction_rate": 0,
|
||||
"live_company_scope_resolution_rate": 1,
|
||||
"live_admissible_evidence_nonzero_rate": 0.6667,
|
||||
"live_partial_coverage_default_rate": 0.6667,
|
||||
"live_claim_path_completion_rate": 0.6667,
|
||||
"live_false_grounded_answer_rate": 0
|
||||
},
|
||||
"verdicts": {
|
||||
"LIVE_TEMPORAL_ALIGNMENT_FIXED": "FIXED",
|
||||
"LIVE_COMPANY_SCOPE_FIXED": "FIXED",
|
||||
"LIVE_EVIDENCE_PATH_FIXED": "FIXED",
|
||||
"LIVE_PARTIAL_COVERAGE_DEFAULT_REDUCED": "REDUCED",
|
||||
"overall_status": "WAVE19_2_ACCEPTED"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
[
|
||||
{
|
||||
"case_id": "L1",
|
||||
"label": "vat_chain_furniture_13_15_july",
|
||||
"claim_type": "prove_vat_chain_completeness",
|
||||
"routes": "store_canonical -\u003e hybrid_store_plus_live",
|
||||
"business_scope_resolved": "company_specific_accounting",
|
||||
"resolved_time_anchor": "2020-07-13",
|
||||
"temporal_guard_outcome": "passed",
|
||||
"admissible_evidence_count": 12,
|
||||
"grounding_mode": "grounded_positive",
|
||||
"reply_type": "factual_with_explanation"
|
||||
},
|
||||
{
|
||||
"case_id": "L2",
|
||||
"label": "rbp_tail_31_july_5000",
|
||||
"claim_type": "prove_rbp_tail_state",
|
||||
"routes": "store_canonical -\u003e store_canonical",
|
||||
"business_scope_resolved": "company_specific_accounting",
|
||||
"resolved_time_anchor": "2020-07-31",
|
||||
"temporal_guard_outcome": "passed",
|
||||
"admissible_evidence_count": 0,
|
||||
"grounding_mode": "limited_or_insufficient_evidence",
|
||||
"reply_type": "partial_coverage"
|
||||
},
|
||||
{
|
||||
"case_id": "L3",
|
||||
"label": "fa_amortization_2471_2465_849",
|
||||
"claim_type": "prove_month_close_state",
|
||||
"routes": "store_feature_risk -\u003e hybrid_store_plus_live",
|
||||
"business_scope_resolved": "company_specific_accounting",
|
||||
"resolved_time_anchor": "2020-07-31",
|
||||
"temporal_guard_outcome": "passed",
|
||||
"admissible_evidence_count": 19,
|
||||
"grounding_mode": "limited_or_insufficient_evidence",
|
||||
"reply_type": "partial_coverage"
|
||||
}
|
||||
]
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
[
|
||||
{
|
||||
"case_id": "L1",
|
||||
"label": "vat_chain_furniture_13_15_july",
|
||||
"claim_type": "prove_vat_chain_completeness",
|
||||
"method": "execute_query",
|
||||
"route": "hybrid_store_plus_live",
|
||||
"query_subject": "vat_chain_conflict",
|
||||
"fetched_rows": 24,
|
||||
"returned_rows": 12,
|
||||
"matched_rows": 24,
|
||||
"account_scope": "",
|
||||
"status": "ok",
|
||||
"admissible_evidence_count": 12,
|
||||
"used_for_grounding": true,
|
||||
"eligibility_outcome": "grounded_allowed",
|
||||
"eligibility_mode": "grounded_positive"
|
||||
},
|
||||
{
|
||||
"case_id": "L3",
|
||||
"label": "fa_amortization_2471_2465_849",
|
||||
"claim_type": "prove_month_close_state",
|
||||
"method": "execute_query",
|
||||
"route": "hybrid_store_plus_live",
|
||||
"query_subject": "fixed_asset_card_mismatch",
|
||||
"fetched_rows": 24,
|
||||
"returned_rows": 12,
|
||||
"matched_rows": 24,
|
||||
"account_scope": "",
|
||||
"status": "ok",
|
||||
"admissible_evidence_count": 19,
|
||||
"used_for_grounding": true,
|
||||
"eligibility_outcome": "limited_or_insufficient_evidence",
|
||||
"eligibility_mode": "limited_or_insufficient_evidence"
|
||||
}
|
||||
]
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
[
|
||||
{
|
||||
"case_id": "L1",
|
||||
"label": "vat_chain_furniture_13_15_july",
|
||||
"claim_type": "prove_vat_chain_completeness",
|
||||
"call_present": true,
|
||||
"method": "execute_query",
|
||||
"route": "hybrid_store_plus_live",
|
||||
"args_summary": null,
|
||||
"query_subject": "vat_chain_conflict",
|
||||
"fetched_rows": 24,
|
||||
"returned_rows": 12,
|
||||
"matched_rows": 24,
|
||||
"account_scope": "",
|
||||
"used_for_admissible_evidence": true,
|
||||
"rejection_or_block_reason": "n/a",
|
||||
"admissible_evidence_count": 12,
|
||||
"eligibility_outcome": "grounded_allowed",
|
||||
"eligibility_mode": "grounded_positive",
|
||||
"eligibility_reason_codes": ""
|
||||
},
|
||||
{
|
||||
"case_id": "L2",
|
||||
"label": "rbp_tail_31_july_5000",
|
||||
"claim_type": "prove_rbp_tail_state",
|
||||
"call_present": false,
|
||||
"method": null,
|
||||
"route": null,
|
||||
"args_summary": null,
|
||||
"query_subject": null,
|
||||
"fetched_rows": 0,
|
||||
"returned_rows": 0,
|
||||
"matched_rows": 0,
|
||||
"account_scope": "",
|
||||
"used_for_admissible_evidence": false,
|
||||
"rejection_or_block_reason": "no_live_call_selected_for_case",
|
||||
"admissible_evidence_count": 0,
|
||||
"eligibility_outcome": "limited_or_insufficient_evidence",
|
||||
"eligibility_mode": "limited_or_insufficient_evidence",
|
||||
"eligibility_reason_codes": "admissible_evidence_count_zero,targeted_evidence_hit_rate_zero"
|
||||
},
|
||||
{
|
||||
"case_id": "L3",
|
||||
"label": "fa_amortization_2471_2465_849",
|
||||
"claim_type": "prove_month_close_state",
|
||||
"call_present": true,
|
||||
"method": "execute_query",
|
||||
"route": "hybrid_store_plus_live",
|
||||
"args_summary": null,
|
||||
"query_subject": "fixed_asset_card_mismatch",
|
||||
"fetched_rows": 24,
|
||||
"returned_rows": 12,
|
||||
"matched_rows": 24,
|
||||
"account_scope": "",
|
||||
"used_for_admissible_evidence": true,
|
||||
"rejection_or_block_reason": "n/a",
|
||||
"admissible_evidence_count": 19,
|
||||
"eligibility_outcome": "limited_or_insufficient_evidence",
|
||||
"eligibility_mode": "limited_or_insufficient_evidence",
|
||||
"eligibility_reason_codes": "claim_anchor_coverage_insufficient"
|
||||
}
|
||||
]
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
{
|
||||
"generated_at": "2026-03-29T05:48:19.981Z",
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "L1",
|
||||
"label": "vat_chain_furniture_13_15_july",
|
||||
"claim_type": "prove_vat_chain_completeness",
|
||||
"admissible_evidence_count": 12,
|
||||
"live_calls": [
|
||||
{
|
||||
"fragment_id": "F2",
|
||||
"route": "hybrid_store_plus_live",
|
||||
"method": "execute_query",
|
||||
"args_summary": null,
|
||||
"query_subject": "vat_chain_conflict",
|
||||
"account_scope": [],
|
||||
"fetched_rows": 24,
|
||||
"returned_rows": 12,
|
||||
"matched_rows": 24,
|
||||
"status": "ok"
|
||||
}
|
||||
],
|
||||
"claim_targeted_hit_rate": 1,
|
||||
"eligibility": {
|
||||
"eligible": true,
|
||||
"grounding_mode": "grounded_positive",
|
||||
"outcome": "grounded_allowed",
|
||||
"reason_codes": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "L2",
|
||||
"label": "rbp_tail_31_july_5000",
|
||||
"claim_type": "prove_rbp_tail_state",
|
||||
"admissible_evidence_count": 0,
|
||||
"live_calls": [],
|
||||
"claim_targeted_hit_rate": 0,
|
||||
"eligibility": {
|
||||
"eligible": false,
|
||||
"grounding_mode": "limited_or_insufficient_evidence",
|
||||
"outcome": "limited_or_insufficient_evidence",
|
||||
"reason_codes": [
|
||||
"admissible_evidence_count_zero",
|
||||
"targeted_evidence_hit_rate_zero"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "L3",
|
||||
"label": "fa_amortization_2471_2465_849",
|
||||
"claim_type": "prove_month_close_state",
|
||||
"admissible_evidence_count": 19,
|
||||
"live_calls": [
|
||||
{
|
||||
"fragment_id": "F2",
|
||||
"route": "hybrid_store_plus_live",
|
||||
"method": "execute_query",
|
||||
"args_summary": null,
|
||||
"query_subject": "fixed_asset_card_mismatch",
|
||||
"account_scope": [],
|
||||
"fetched_rows": 24,
|
||||
"returned_rows": 12,
|
||||
"matched_rows": 24,
|
||||
"status": "ok"
|
||||
}
|
||||
],
|
||||
"claim_targeted_hit_rate": 1,
|
||||
"eligibility": {
|
||||
"eligible": false,
|
||||
"grounding_mode": "limited_or_insufficient_evidence",
|
||||
"outcome": "limited_or_insufficient_evidence",
|
||||
"reason_codes": [
|
||||
"claim_anchor_coverage_insufficient"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
# 2020 экспорт: состав выгрузки
|
||||
|
||||
Папка собрана автоматически для ручного анализа текущего состояния.
|
||||
|
||||
## Файлы
|
||||
|
||||
1. `01_ontology_mapping_layer.md` — текущая онтология/мэппинг и метрики среза.
|
||||
2. `02_canonical_relation_rules.md` — правила построения canonical relations.
|
||||
3. `03_snapshot_fragment_problem_cases.json` — проблемный фрагмент snapshot июня 2020.
|
||||
4. `04_samples_SpisanieSRaschetnogoScheta.json` — реальные записи по `СписаниеСРасчетногоСчета`.
|
||||
5. `05_samples_RealizaciyaTovarovUslug.json` — реальные записи по `РеализацияТоваровУслуг`.
|
||||
6. `06_samples_PostuplenieTovarovUslug.json` — реальные записи по `ПоступлениеТоваровУслуг`.
|
||||
7. `07_samples_DocumentJournals.json` — реальные записи по журналам документов.
|
||||
8. `08_samples_NDS_registers.json` — реальные записи по НДС-регистрам.
|
||||
9. `09_samples_key_fields_Recorder_Ref_Supplier_Buyer_Responsible.json` — записи с ключевыми полями.
|
||||
|
||||
## Ключевые поля: фактическая встречаемость в snapshot
|
||||
|
||||
| field | count |
|
||||
| --- | --- |
|
||||
| Ответственный_Key | 187 |
|
||||
| Ref | 168 |
|
||||
| Recorder | 147 |
|
||||
| Ref_Key | 93 |
|
||||
| Поставщик_Key | 78 |
|
||||
| Покупатель_Key | 46 |
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,112 @@
|
|||
{
|
||||
"status": "success",
|
||||
"snapshot_mode": "cumulative_asof",
|
||||
"year": 2020,
|
||||
"service_root": "http://localhost/buh_test/odata/standard.odata/",
|
||||
"entity_sets_total": 2,
|
||||
"entity_sets": [
|
||||
"AccountingRegister_Хозрасчетный",
|
||||
"AccountingRegister_Хозрасчетный_RecordType"
|
||||
],
|
||||
"page_size": 500,
|
||||
"max_pages_per_set": 0,
|
||||
"include_undated": "all_months",
|
||||
"truncated_entity_sets_count": 0,
|
||||
"truncated_entity_sets": [],
|
||||
"records_exported_per_month": {
|
||||
"2020-01": 15113,
|
||||
"2020-02": 15211,
|
||||
"2020-03": 15508,
|
||||
"2020-04": 15578,
|
||||
"2020-05": 15648,
|
||||
"2020-06": 15953,
|
||||
"2020-07": 16039,
|
||||
"2020-08": 16122,
|
||||
"2020-09": 16175,
|
||||
"2020-10": 16212,
|
||||
"2020-11": 16308,
|
||||
"2020-12": 16377
|
||||
},
|
||||
"dated_records_exported_per_month": {
|
||||
"2020-01": 10644,
|
||||
"2020-02": 10742,
|
||||
"2020-03": 11039,
|
||||
"2020-04": 11109,
|
||||
"2020-05": 11179,
|
||||
"2020-06": 11484,
|
||||
"2020-07": 11570,
|
||||
"2020-08": 11653,
|
||||
"2020-09": 11706,
|
||||
"2020-10": 11743,
|
||||
"2020-11": 11839,
|
||||
"2020-12": 11908
|
||||
},
|
||||
"undated_records_exported_per_month": {
|
||||
"2020-01": 4469,
|
||||
"2020-02": 4469,
|
||||
"2020-03": 4469,
|
||||
"2020-04": 4469,
|
||||
"2020-05": 4469,
|
||||
"2020-06": 4469,
|
||||
"2020-07": 4469,
|
||||
"2020-08": 4469,
|
||||
"2020-09": 4469,
|
||||
"2020-10": 4469,
|
||||
"2020-11": 4469,
|
||||
"2020-12": 4469
|
||||
},
|
||||
"links_exported_per_month": {
|
||||
"2020-01": 47623,
|
||||
"2020-02": 48036,
|
||||
"2020-03": 49243,
|
||||
"2020-04": 49539,
|
||||
"2020-05": 49834,
|
||||
"2020-06": 51071,
|
||||
"2020-07": 51426,
|
||||
"2020-08": 51769,
|
||||
"2020-09": 51992,
|
||||
"2020-10": 52151,
|
||||
"2020-11": 52545,
|
||||
"2020-12": 52831
|
||||
},
|
||||
"entity_set_stats": {
|
||||
"AccountingRegister_Хозрасчетный": {
|
||||
"pages_read": 9,
|
||||
"records_scanned": 4469,
|
||||
"records_mapped": 4469,
|
||||
"records_with_datetime": 0,
|
||||
"records_without_datetime": 4469,
|
||||
"records_skipped_future": 0,
|
||||
"mapping_errors": 0,
|
||||
"truncated_by_limit_or_guard": false,
|
||||
"pagination_repeat_guard_hits": 0
|
||||
},
|
||||
"AccountingRegister_Хозрасчетный_RecordType": {
|
||||
"pages_read": 26,
|
||||
"records_scanned": 12659,
|
||||
"records_mapped": 11908,
|
||||
"records_with_datetime": 12659,
|
||||
"records_without_datetime": 0,
|
||||
"records_skipped_future": 751,
|
||||
"mapping_errors": 0,
|
||||
"truncated_by_limit_or_guard": false,
|
||||
"pagination_repeat_guard_hits": 0
|
||||
}
|
||||
},
|
||||
"snapshot_files": [
|
||||
"snapshot_2020-01_asof_full.json",
|
||||
"snapshot_2020-02_asof_full.json",
|
||||
"snapshot_2020-03_asof_full.json",
|
||||
"snapshot_2020-04_asof_full.json",
|
||||
"snapshot_2020-05_asof_full.json",
|
||||
"snapshot_2020-06_asof_full.json",
|
||||
"snapshot_2020-07_asof_full.json",
|
||||
"snapshot_2020-08_asof_full.json",
|
||||
"snapshot_2020-09_asof_full.json",
|
||||
"snapshot_2020-10_asof_full.json",
|
||||
"snapshot_2020-11_asof_full.json",
|
||||
"snapshot_2020-12_asof_full.json"
|
||||
],
|
||||
"output_dir": "x:\\1C\\NDC_1C\\docs\\ARCH\\2020_monthly_company_asof_full_test",
|
||||
"generated_at_utc": "2026-03-27T21:34:24.669751+00:00"
|
||||
}
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
{
|
||||
"runtime_snapshot_root": "x:\\1C\\NDC_1C\\docs\\ARCH\\2020экспорт",
|
||||
"runtime_snapshot_files": [
|
||||
{
|
||||
"file": "03_snapshot_fragment_problem_cases.json",
|
||||
"path": "x:\\1C\\NDC_1C\\docs\\ARCH\\2020экспорт\\03_snapshot_fragment_problem_cases.json",
|
||||
"size_bytes": 302520,
|
||||
"records_count": 80,
|
||||
"top_entities": [
|
||||
{
|
||||
"entity": "AccumulationRegister_НДСЗаписиКнигиПродаж_RecordType",
|
||||
"count": 46
|
||||
},
|
||||
{
|
||||
"entity": "AccumulationRegister_НДСПредъявленный_RecordType",
|
||||
"count": 21
|
||||
},
|
||||
{
|
||||
"entity": "AccumulationRegister_НДСЗаписиКнигиПокупок_RecordType",
|
||||
"count": 12
|
||||
},
|
||||
{
|
||||
"entity": "AccumulationRegister_НДСВключенныйВСтоимость_RecordType",
|
||||
"count": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"file": "04_samples_SpisanieSRaschetnogoScheta.json",
|
||||
"path": "x:\\1C\\NDC_1C\\docs\\ARCH\\2020экспорт\\04_samples_SpisanieSRaschetnogoScheta.json",
|
||||
"size_bytes": 196178,
|
||||
"records_count": 27,
|
||||
"top_entities": {
|
||||
"entity": "Document_СписаниеСРасчетногоСчета",
|
||||
"count": 27
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "05_samples_RealizaciyaTovarovUslug.json",
|
||||
"path": "x:\\1C\\NDC_1C\\docs\\ARCH\\2020экспорт\\05_samples_RealizaciyaTovarovUslug.json",
|
||||
"size_bytes": 132032,
|
||||
"records_count": 5,
|
||||
"top_entities": {
|
||||
"entity": "Document_РеализацияТоваровУслуг",
|
||||
"count": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "06_samples_PostuplenieTovarovUslug.json",
|
||||
"path": "x:\\1C\\NDC_1C\\docs\\ARCH\\2020экспорт\\06_samples_PostuplenieTovarovUslug.json",
|
||||
"size_bytes": 181409,
|
||||
"records_count": 10,
|
||||
"top_entities": {
|
||||
"entity": "Document_ПоступлениеТоваровУслуг",
|
||||
"count": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "07_samples_DocumentJournals.json",
|
||||
"path": "x:\\1C\\NDC_1C\\docs\\ARCH\\2020экспорт\\07_samples_DocumentJournals.json",
|
||||
"size_bytes": 292931,
|
||||
"records_count": 80,
|
||||
"top_entities": [
|
||||
{
|
||||
"entity": "DocumentJournal_ДокументыПоставщиков",
|
||||
"count": 30
|
||||
},
|
||||
{
|
||||
"entity": "DocumentJournal_БанковскиеВыписки",
|
||||
"count": 30
|
||||
},
|
||||
{
|
||||
"entity": "DocumentJournal_ДокументыПокупателей",
|
||||
"count": 16
|
||||
},
|
||||
{
|
||||
"entity": "DocumentJournal_ДокументыПоУчетуЗарплаты",
|
||||
"count": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"file": "08_samples_NDS_registers.json",
|
||||
"path": "x:\\1C\\NDC_1C\\docs\\ARCH\\2020экспорт\\08_samples_NDS_registers.json",
|
||||
"size_bytes": 291547,
|
||||
"records_count": 80,
|
||||
"top_entities": [
|
||||
{
|
||||
"entity": "AccumulationRegister_НДСЗаписиКнигиПродаж_RecordType",
|
||||
"count": 46
|
||||
},
|
||||
{
|
||||
"entity": "AccumulationRegister_НДСПредъявленный_RecordType",
|
||||
"count": 21
|
||||
},
|
||||
{
|
||||
"entity": "AccumulationRegister_НДСЗаписиКнигиПокупок_RecordType",
|
||||
"count": 12
|
||||
},
|
||||
{
|
||||
"entity": "AccumulationRegister_НДСВключенныйВСтоимость_RecordType",
|
||||
"count": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"file": "09_samples_key_fields_Recorder_Ref_Supplier_Buyer_Responsible.json",
|
||||
"path": "x:\\1C\\NDC_1C\\docs\\ARCH\\2020экспорт\\09_samples_key_fields_Recorder_Ref_Supplier_Buyer_Responsible.json",
|
||||
"size_bytes": 511133,
|
||||
"records_count": 140,
|
||||
"top_entities": [
|
||||
{
|
||||
"entity": "AccumulationRegister_НДСПредъявленный_RecordType",
|
||||
"count": 65
|
||||
},
|
||||
{
|
||||
"entity": "AccumulationRegister_НДСЗаписиКнигиПродаж_RecordType",
|
||||
"count": 46
|
||||
},
|
||||
{
|
||||
"entity": "AccumulationRegister_НДСЗаписиКнигиПокупок_RecordType",
|
||||
"count": 12
|
||||
},
|
||||
{
|
||||
"entity": "AccumulationRegister_НДФЛРасчетыСБюджетом_RecordType",
|
||||
"count": 7
|
||||
},
|
||||
{
|
||||
"entity": "AccumulationRegister_НДФЛСведенияОДоходах_RecordType",
|
||||
"count": 3
|
||||
},
|
||||
{
|
||||
"entity": "AccumulationRegister_РасчетыНалоговыхАгентовСБюджетомПоНДФЛ_RecordType",
|
||||
"count": 3
|
||||
},
|
||||
{
|
||||
"entity": "AccumulationRegister_РеализацияУслуг_RecordType",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"entity": "AccumulationRegister_РасчетыПоСтраховымВзносам_RecordType",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"entity": "AccumulationRegister_НДСВключенныйВСтоимость_RecordType",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"entity": "AccumulationRegister_НДФЛПредоставленныеСтандартныеВычетыФизЛиц_RecordType",
|
||||
"count": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"monthly_asof_root": "x:\\1C\\NDC_1C\\docs\\ARCH\\2020_monthly_company_asof_full_test",
|
||||
"monthly_asof_files": [
|
||||
{
|
||||
"Name": "snapshot_2020-01_asof_full.json",
|
||||
"Length": 42476280,
|
||||
"FullName": "X:\\1C\\NDC_1C\\docs\\ARCH\\2020_monthly_company_asof_full_test\\snapshot_2020-01_asof_full.json"
|
||||
},
|
||||
{
|
||||
"Name": "snapshot_2020-02_asof_full.json",
|
||||
"Length": 42750865,
|
||||
"FullName": "X:\\1C\\NDC_1C\\docs\\ARCH\\2020_monthly_company_asof_full_test\\snapshot_2020-02_asof_full.json"
|
||||
},
|
||||
{
|
||||
"Name": "snapshot_2020-03_asof_full.json",
|
||||
"Length": 43556064,
|
||||
"FullName": "X:\\1C\\NDC_1C\\docs\\ARCH\\2020_monthly_company_asof_full_test\\snapshot_2020-03_asof_full.json"
|
||||
},
|
||||
{
|
||||
"Name": "snapshot_2020-04_asof_full.json",
|
||||
"Length": 43751598,
|
||||
"FullName": "X:\\1C\\NDC_1C\\docs\\ARCH\\2020_monthly_company_asof_full_test\\snapshot_2020-04_asof_full.json"
|
||||
},
|
||||
{
|
||||
"Name": "snapshot_2020-05_asof_full.json",
|
||||
"Length": 43947779,
|
||||
"FullName": "X:\\1C\\NDC_1C\\docs\\ARCH\\2020_monthly_company_asof_full_test\\snapshot_2020-05_asof_full.json"
|
||||
},
|
||||
{
|
||||
"Name": "snapshot_2020-06_asof_full.json",
|
||||
"Length": 44770832,
|
||||
"FullName": "X:\\1C\\NDC_1C\\docs\\ARCH\\2020_monthly_company_asof_full_test\\snapshot_2020-06_asof_full.json"
|
||||
},
|
||||
{
|
||||
"Name": "snapshot_2020-07_asof_full.json",
|
||||
"Length": 45007595,
|
||||
"FullName": "X:\\1C\\NDC_1C\\docs\\ARCH\\2020_monthly_company_asof_full_test\\snapshot_2020-07_asof_full.json"
|
||||
},
|
||||
{
|
||||
"Name": "snapshot_2020-08_asof_full.json",
|
||||
"Length": 45237062,
|
||||
"FullName": "X:\\1C\\NDC_1C\\docs\\ARCH\\2020_monthly_company_asof_full_test\\snapshot_2020-08_asof_full.json"
|
||||
},
|
||||
{
|
||||
"Name": "snapshot_2020-09_asof_full.json",
|
||||
"Length": 45384277,
|
||||
"FullName": "X:\\1C\\NDC_1C\\docs\\ARCH\\2020_monthly_company_asof_full_test\\snapshot_2020-09_asof_full.json"
|
||||
},
|
||||
{
|
||||
"Name": "snapshot_2020-10_asof_full.json",
|
||||
"Length": 45489151,
|
||||
"FullName": "X:\\1C\\NDC_1C\\docs\\ARCH\\2020_monthly_company_asof_full_test\\snapshot_2020-10_asof_full.json"
|
||||
},
|
||||
{
|
||||
"Name": "snapshot_2020-11_asof_full.json",
|
||||
"Length": 45753055,
|
||||
"FullName": "X:\\1C\\NDC_1C\\docs\\ARCH\\2020_monthly_company_asof_full_test\\snapshot_2020-11_asof_full.json"
|
||||
},
|
||||
{
|
||||
"Name": "snapshot_2020-12_asof_full.json",
|
||||
"Length": 45942785,
|
||||
"FullName": "X:\\1C\\NDC_1C\\docs\\ARCH\\2020_monthly_company_asof_full_test\\snapshot_2020-12_asof_full.json"
|
||||
}
|
||||
],
|
||||
"monthly_manifest": "x:\\1C\\NDC_1C\\docs\\ARCH\\2020_monthly_company_asof_full_test\\manifest_2020_monthly_company_asof_full.json"
|
||||
}
|
||||
Binary file not shown.
|
|
@ -0,0 +1,115 @@
|
|||
# 9 — Разведка структуры 1С и связей через MCP по 3 контрольным вопросам (2026-03-29)
|
||||
|
||||
Статус: COMPLETED
|
||||
Scope: Stage 4, P0-only, без redesign/proof-engine расширения
|
||||
|
||||
## 1) Цель и границы
|
||||
|
||||
Цель этой работы: не чинить wording, а построить доказательную карту:
|
||||
`вопрос -> anchors -> route -> 1C entities/relations -> evidence -> answer`.
|
||||
|
||||
Source of truth:
|
||||
1. Q1 VAT (13/15 июля, мебель).
|
||||
2. Q2 RBP (31 июля, 5 000).
|
||||
3. Q3 FA amortization (31 июля, 2 471,52 / 2 465,28 / 849,83).
|
||||
|
||||
## 2) Что использовано как фактическая база
|
||||
|
||||
- Replay/live артефакты: `docs/ARCH/9_audit_artifacts/replay_logs/*`
|
||||
- Debug payloads 3 кейсов: `docs/ARCH/9_audit_artifacts/debug_payloads/*`
|
||||
- Live inventory: `docs/ARCH/9_audit_artifacts/raw_live_calls/*`
|
||||
- Snapshot probes: `docs/ARCH/9_audit_artifacts/snapshot_samples/*`
|
||||
- Relation probes: `docs/ARCH/9_audit_artifacts/relation_probe_logs/*`
|
||||
- Query recipes: `docs/ARCH/9_audit_artifacts/query_recipe_examples/*`
|
||||
- Code paths: `assistantService`, `assistantDataLayer`, `assistantRuntimeGuards`, `assistantClaimBoundEvidence`, `answerComposer`
|
||||
|
||||
## 3) Узел A — обязательные сущности и переходы
|
||||
|
||||
Результат: см. `9A - entity_seed_map.md`.
|
||||
|
||||
Коротко:
|
||||
- Q1 VAT: обязательна цепочка doc->invoice->register->book + posting consistency.
|
||||
- Q2 RBP: обязательна object-level цепочка writeoff->movement->close->residual.
|
||||
- Q3 FA: обязательна object-level цепочка FA object->depreciation->posting + expected-set coverage.
|
||||
|
||||
## 4) Узел B — snapshot vs live coverage
|
||||
|
||||
Результат: см. `9B - snapshot_vs_live_coverage_map.md`.
|
||||
|
||||
Жесткий verdict по coverage:
|
||||
- Q1 VAT: `snapshot_plus_live_required`
|
||||
- Q2 RBP: `data_not_reachable_in_current_runtime`
|
||||
- Q3 FA: `snapshot_plus_live_required`
|
||||
|
||||
Причина:
|
||||
- runtime использует ограниченный `2020экспорт` subset;
|
||||
- live path сейчас broad (`execute_query` generic probe), без claim-specific call sequence;
|
||||
- object-level reconstruction для RBP/FA не замыкается.
|
||||
|
||||
## 5) Узел C — relation map 1С
|
||||
|
||||
Результат: см. `9C - relation_map_1c_entities.md`.
|
||||
|
||||
Ключевой вывод:
|
||||
- VAT relation skeleton в текущих источниках есть и partially operational.
|
||||
- RBP/FA critical relations либо не реконструируются, либо не используются в current runtime path.
|
||||
- На FA есть cross-domain contamination (нерелевантные связи попадают в evidence path).
|
||||
|
||||
## 6) Узел D — реальные MCP маршруты
|
||||
|
||||
Результат: см. `9D - mcp_query_recipes.md`.
|
||||
|
||||
Фактическая картина:
|
||||
- Q1: есть live call, но это broad probe.
|
||||
- Q2: live call отсутствует (route canonical-only).
|
||||
- Q3: live call есть, но без object scope.
|
||||
|
||||
Missing layer:
|
||||
- claim-bound call sequence per question (required_live_calls) отсутствует во всех 3 кейсах.
|
||||
|
||||
## 7) Узел E — source-to-proof failure map
|
||||
|
||||
Результат: см. `9E - source_to_proof_failure_map.md`.
|
||||
|
||||
### Локальные verdict
|
||||
- Q1 VAT: `EVIDENCE_MATERIALIZATION_IS_PRIMARY_PROBLEM` (residual)
|
||||
- Q2 RBP: `SOURCE_COVERAGE_IS_PRIMARY_PROBLEM` (в связке с route gap)
|
||||
- Q3 FA: `ONE_C_RELATION_MAPPING_IS_PRIMARY_PROBLEM`
|
||||
|
||||
### Общий verdict
|
||||
`MULTI_NODE_FAILURE_CONFIRMED`
|
||||
|
||||
## 8) Ответы на главные вопросы ТЗ
|
||||
|
||||
### По НДС
|
||||
- Какие сущности нужны: docs receipt/sale, invoice links, VAT registers, postings, book linkage.
|
||||
- Почему positive path уже работает: relation skeleton для VAT реально доступен.
|
||||
- Где шум: broad live probe + admissibility reject шум.
|
||||
|
||||
### По РБП
|
||||
- Есть ли данные в source: частично.
|
||||
- Есть ли путь через MCP в current runtime: практически нет (route не включает live).
|
||||
- Где рвется: `source coverage + route + relation reconstruction + evidence materialization`.
|
||||
|
||||
### По амортизации
|
||||
- Какие объекты должны участвовать: полный expected set ОС за июль.
|
||||
- Почему admissible evidence уже есть, но proof не закрывается: object-level relation/anchor closure не достигается.
|
||||
- Где не хватает mapping/anchors: `wrong_entity_mapping` + `claim_anchor_coverage_insufficient`.
|
||||
|
||||
## 9) Что конкретно чинить следующим пакетом
|
||||
|
||||
1. Добавить claim-specific MCP call sequences per question (вместо generic live probe).
|
||||
2. Закрыть object-level relation reconstruction для RBP и FA.
|
||||
3. Подключить/использовать source layers, которые сейчас физически есть, но runtime не использует.
|
||||
4. Снизить reject not-due-to-data в evidence gate.
|
||||
|
||||
## 10) Финальный результат разведки
|
||||
|
||||
Размытая формулировка «слабая доказательная база» снята.
|
||||
|
||||
Теперь зафиксировано:
|
||||
- какие данные нужны;
|
||||
- какие связи обязательны;
|
||||
- какие вызовы MCP должны быть;
|
||||
- где текущий runtime теряет source-to-proof контур;
|
||||
- какие узлы приоритетно чинить следующим execution pack.
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
# 9A — Entity Seed Map
|
||||
|
||||
Дата: 2026-03-29
|
||||
Scope: 3 контрольных вопроса (НДС / РБП / Амортизация)
|
||||
|
||||
## Q1 — НДС (13/15 июля, мебель)
|
||||
|
||||
### Seed entities
|
||||
- Поступление товаров (документ, 13 июля)
|
||||
- Реализация товаров (документ, 15 июля)
|
||||
- Номенклатура/позиции мебели
|
||||
- Контрагент + договор
|
||||
- Счет-фактура
|
||||
- НДС-регистры
|
||||
- Проводки/движения по хозрасчетному регистру
|
||||
|
||||
### Required entities
|
||||
- `Document_ПоступлениеТоваровУслуг`
|
||||
- `Document_РеализацияТоваровУслуг`
|
||||
- Invoice-linked document refs
|
||||
- `AccumulationRegister_НДС*` records (purchase/sales/tax chain)
|
||||
- Book-layer records (книга покупок/продаж в терминах register linkage)
|
||||
- Posting/movement records for doc confirmation
|
||||
|
||||
### Expected transitions (обязательные)
|
||||
1. `receipt_document -> invoice_link`
|
||||
2. `sale_document -> invoice_link`
|
||||
3. `invoice_link -> vat_register_entry`
|
||||
4. `vat_register_entry -> book_entry`
|
||||
5. `document -> posting`
|
||||
6. `item_scope(receipt) -> item_scope(sale)`
|
||||
|
||||
### Смежный контур (не ядро claim)
|
||||
- Currency/warehouse/responsible fields.
|
||||
- Broad journal references без цепочки invoice/register/book.
|
||||
|
||||
## Q2 — РБП (31 июля, 5 000)
|
||||
|
||||
### Seed entities
|
||||
- Документ списания РБП за июль
|
||||
- Объект РБП
|
||||
- Движения по счету/регистрам РБП
|
||||
- Month-close записи
|
||||
- Остаток на конец июля
|
||||
|
||||
### Required entities
|
||||
- RBP write-off document record
|
||||
- RBP object card / object identifier
|
||||
- RBP movements (дебет/кредит/period bound)
|
||||
- Month-close linked entries
|
||||
- End-period residual per object
|
||||
|
||||
### Expected transitions (обязательные)
|
||||
1. `rbp_writeoff_document -> rbp_object`
|
||||
2. `rbp_object -> movement_records`
|
||||
3. `movement_records -> month_close_entries`
|
||||
4. `month_close_entries -> end_period_residual`
|
||||
5. `end_period_residual -> normal_vs_tail_state`
|
||||
|
||||
### Смежный контур (не ядро claim)
|
||||
- Общие bank/payment journals без object-level RBP linkage.
|
||||
|
||||
## Q3 — Амортизация (31 июля, 2 471,52 / 2 465,28 / 849,83)
|
||||
|
||||
### Seed entities
|
||||
- Объекты ОС (expected set за июль)
|
||||
- Документы начисления амортизации
|
||||
- Проводки по амортизации
|
||||
- Периодные month-close записи
|
||||
- Суммовые anchors из вопроса
|
||||
|
||||
### Required entities
|
||||
- FA object identifiers (expected set)
|
||||
- Depreciation documents for July 2020
|
||||
- Object-to-posting linkage
|
||||
- Posting accounts relevant to depreciation flow
|
||||
- Missed-object detector (object without depreciation row)
|
||||
|
||||
### Expected transitions (обязательные)
|
||||
1. `fa_object -> depreciation_document`
|
||||
2. `depreciation_document -> posting`
|
||||
3. `posting -> account_scope(02/20/44 and linked)`
|
||||
4. `expected_fa_set -> covered_fa_set`
|
||||
5. `set_diff -> missing_object_risk`
|
||||
|
||||
### Смежный контур (не ядро claim)
|
||||
- Non-FA tax/personnel registers (например NDFL-related records), если не дают object-level FA proof.
|
||||
|
||||
## Seed/required summary
|
||||
|
||||
| Question | Seed quality in current runtime | Required transitions fully reconstructable now |
|
||||
| --- | --- | --- |
|
||||
| Q1 VAT | medium-high | partial-high |
|
||||
| Q2 RBP | low-medium | low |
|
||||
| Q3 FA | medium | medium-low |
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
# 9B — Snapshot vs Live Coverage Map
|
||||
|
||||
Дата: 2026-03-29
|
||||
|
||||
## 1) Snapshot coverage (факт)
|
||||
|
||||
Текущий runtime подключает только `docs/ARCH/2020экспорт` subset:
|
||||
- `03_snapshot_fragment_problem_cases.json`
|
||||
- `04_samples_SpisanieSRaschetnogoScheta.json`
|
||||
- `05_samples_RealizaciyaTovarovUslug.json`
|
||||
- `06_samples_PostuplenieTovarovUslug.json`
|
||||
- `07_samples_DocumentJournals.json`
|
||||
- `08_samples_NDS_registers.json`
|
||||
- `09_samples_key_fields_Recorder_Ref_Supplier_Buyer_Responsible.json`
|
||||
|
||||
Дополнительно физически существует monthly as-of corpus (`2020_monthly_company_asof_full_test`), но current runtime его не использует.
|
||||
|
||||
## 2) Live coverage (факт)
|
||||
|
||||
Current runtime live path:
|
||||
- method: `execute_query`
|
||||
- endpoint: MCP proxy `/api/execute_query`
|
||||
- запрос: generic accounting register probe (`TOP N`, без claim-specific filters)
|
||||
|
||||
## 3) Coverage by question
|
||||
|
||||
| Question | Snapshot needed entities reachable | Live needed entities reachable | Current runtime uses required route | Coverage verdict |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Q1 VAT | Yes (docs + VAT registers + key links) | Partially (generic postings probe) | Yes (`store_canonical + hybrid_store_plus_live`) | `snapshot_plus_live_required` |
|
||||
| Q2 RBP | Partially (RBP object-level chain не подтверждается) | Not in current route (no live call selected) | No (canonical-only route) | `data_not_reachable_in_current_runtime` |
|
||||
| Q3 FA | Partially (object-level FA chain неполная) | Partially (generic probe without object scope) | Partially (live есть, но не claim-targeted) | `snapshot_plus_live_required` |
|
||||
|
||||
## 4) Why these verdicts
|
||||
|
||||
### Q1
|
||||
- Snapshot покрывает ключевой VAT relation skeleton.
|
||||
- Live помогает подтвердить movement-level signals.
|
||||
- Без связки snapshot+live цепочка доказательства хуже по устойчивости.
|
||||
|
||||
### Q2
|
||||
- В текущем runtime path live verification не запускается.
|
||||
- Snapshot subset не дает стабильный object-level RBP residual proof.
|
||||
- Поэтому данные не являются достижимыми для полного proof в текущем контуре.
|
||||
|
||||
### Q3
|
||||
- Есть часть snapshot/live сигналов, но object-level FA coverage не закрывается.
|
||||
- Нужны адресные live calls по объектам ОС, которых сейчас нет.
|
||||
|
||||
## 5) B3 verdict (жесткая форма)
|
||||
|
||||
- Q1 VAT: `snapshot_plus_live_required`
|
||||
- Q2 RBP: `data_not_reachable_in_current_runtime`
|
||||
- Q3 FA: `snapshot_plus_live_required`
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
# 9C — Relation Map 1C Entities
|
||||
|
||||
Дата: 2026-03-29
|
||||
Формат: `entity_A`, `entity_B`, `relation_type`, `required_for_claim`, `reachable_via_snapshot`, `reachable_via_live`, `current_runtime_uses_it`, `notes`
|
||||
|
||||
## Q1 — VAT chain completeness
|
||||
|
||||
| entity_A | entity_B | relation_type | required_for_claim | reachable_via_snapshot | reachable_via_live | current_runtime_uses_it | notes |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| `Document_ПоступлениеТоваровУслуг` | `Counterparty/Contract` | `document_has_counterparty` | yes | yes | no | yes | подтверждается links в sample docs |
|
||||
| `Document_РеализацияТоваровУслуг` | `Counterparty/Contract` | `document_has_counterparty` | yes | yes | no | yes | есть в snapshot links |
|
||||
| `Document_*` | `Posting` | `document_to_posting` | yes | partial | partial | partial | live probe broad, без doc filter |
|
||||
| `VAT Register Record` | `Document (Recorder)` | `register_recorded_by_document` | yes | yes | no | yes | есть в `08_samples_NDS_registers` |
|
||||
| `VAT Register Record` | `Invoice Document` | `register_relates_to_invoice` | yes | yes | no | yes | ключевой переход для claim |
|
||||
| `VAT Register Record` | `Book Entry layer` | `register_to_book` | yes | partial | no | partial | собирается косвенно через chain signals |
|
||||
| `Receipt Item Scope` | `Sale Item Scope` | `item_scope_match` | yes | partial | no | partial | прямой item-level реконструкции не хватает |
|
||||
|
||||
## Q2 — RBP tail state
|
||||
|
||||
| entity_A | entity_B | relation_type | required_for_claim | reachable_via_snapshot | reachable_via_live | current_runtime_uses_it | notes |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| `RBP Writeoff Document` | `RBP Object` | `writeoff_to_object` | yes | partial | partial | no | current route не выходит в live |
|
||||
| `RBP Object` | `RBP Movements` | `object_to_movement` | yes | partial | partial | no | object-level mapping не реконструируется |
|
||||
| `RBP Movements` | `Month Close Entry` | `movement_to_close` | yes | low | partial | no | нет явной цепочки в current runtime |
|
||||
| `Month Close Entry` | `End Period Residual` | `close_to_residual` | yes | low | partial | no | ключевое звено для tail verdict отсутствует |
|
||||
| `Residual` | `Tail Classification` | `residual_to_tail_state` | yes | low | low | no | claim check остается `not_found` |
|
||||
|
||||
## Q3 — FA amortization completeness
|
||||
|
||||
| entity_A | entity_B | relation_type | required_for_claim | reachable_via_snapshot | reachable_via_live | current_runtime_uses_it | notes |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| `FA Object` | `Depreciation Document` | `object_to_depreciation_doc` | yes | partial | partial | partial | в runtime нет устойчивого object-level bind |
|
||||
| `Depreciation Document` | `Posting` | `depreciation_to_posting` | yes | partial | partial | partial | live call generic, object scope отсутствует |
|
||||
| `Posting` | `Account Scope` | `posting_to_account_scope` | yes | yes | yes | partial | часть evidence режется gate по account/domain mismatch |
|
||||
| `Expected FA Set` | `Covered FA Set` | `coverage_set_comparison` | yes | low | low | no | нет полноценного expected-set reconstruction |
|
||||
| `Set Difference` | `Missing Object Risk` | `set_diff_to_risk` | yes | low | low | no | финальный proof не закрывается |
|
||||
| `Non-FA Registers` | `FA Claim` | `cross_domain_noise` | no | yes | yes | yes (undesired) | в replay есть нерелевантные NDFL entities |
|
||||
|
||||
## Relation map conclusions
|
||||
|
||||
1. VAT relation skeleton в snapshot реально существует и частично закрывается текущим runtime.
|
||||
2. Для RBP и FA критичные object-level transitions либо не реконструируются, либо не используются runtime.
|
||||
3. На FA наблюдается cross-domain contamination: runtime использует связи, не обязательные для claim, что мешает proof closure.
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
# 9D — MCP Query Recipes
|
||||
|
||||
Дата: 2026-03-29
|
||||
Основание: replay + текущий `assistantDataLayer` (`execute_query` generic probe)
|
||||
|
||||
## Q1 — VAT
|
||||
|
||||
- `question`: 13/15 июля, полнота НДС-цепочки
|
||||
- `required_live_calls`:
|
||||
1. `execute_query:find_receipt_document_by_date_item`
|
||||
2. `execute_query:find_sale_document_by_date_item`
|
||||
3. `execute_query:find_invoice_links_for_receipt_sale`
|
||||
4. `execute_query:find_vat_register_entries_by_invoice`
|
||||
5. `execute_query:find_sales_purchase_book_entries`
|
||||
6. `execute_query:cross_check_document_postings`
|
||||
- `current_live_calls`:
|
||||
1. `execute_query:generic_accounting_register_probe`
|
||||
- `missing_live_calls`: все 6 required calls выше
|
||||
- `wrong_live_calls`:
|
||||
1. `execute_query:generic_accounting_register_probe_without_claim_filters`
|
||||
- `call_sequence_for_proof`:
|
||||
1. seed receipt/sale docs
|
||||
2. resolve invoice links
|
||||
3. resolve VAT register rows
|
||||
4. resolve book entries
|
||||
5. cross-check postings
|
||||
6. build admissible chain verdict
|
||||
|
||||
## Q2 — RBP
|
||||
|
||||
- `question`: есть ли хвост РБП на конец июля
|
||||
- `required_live_calls`:
|
||||
1. `execute_query:find_rbp_writeoff_documents_in_period`
|
||||
2. `execute_query:find_rbp_object_movements_account_97`
|
||||
3. `execute_query:find_month_close_entries_linked_to_rbp`
|
||||
4. `execute_query:compute_end_period_residual_by_rbp_object`
|
||||
5. `execute_query:classify_normal_vs_abnormal_residual`
|
||||
- `current_live_calls`: none
|
||||
- `missing_live_calls`: все 5 required calls выше
|
||||
- `wrong_live_calls`:
|
||||
1. `no_live_call_selected_due_to_canonical_route`
|
||||
- `call_sequence_for_proof`:
|
||||
1. seed writeoff doc
|
||||
2. bind RBP object
|
||||
3. collect 97 movements
|
||||
4. collect close entries
|
||||
5. compute residual tail
|
||||
6. classify tail state
|
||||
|
||||
## Q3 — FA amortization
|
||||
|
||||
- `question`: полнота охвата объектов ОС амортизацией за июль
|
||||
- `required_live_calls`:
|
||||
1. `execute_query:find_fa_objects_expected_in_period`
|
||||
2. `execute_query:find_depreciation_documents_2020_07`
|
||||
3. `execute_query:map_fa_object_to_depreciation_rows`
|
||||
4. `execute_query:cross_check_postings_accounts_02_20_44`
|
||||
5. `execute_query:detect_missing_fa_objects_without_depreciation`
|
||||
- `current_live_calls`:
|
||||
1. `execute_query:generic_accounting_register_probe`
|
||||
- `missing_live_calls`: все 5 required calls выше
|
||||
- `wrong_live_calls`:
|
||||
1. `execute_query:generic_accounting_register_probe_without_object_scope`
|
||||
- `call_sequence_for_proof`:
|
||||
1. seed by period + known amounts
|
||||
2. resolve expected FA set
|
||||
3. resolve depreciation docs
|
||||
4. map object-level postings
|
||||
5. detect missing objects
|
||||
6. produce completeness verdict
|
||||
|
||||
## Current vs required MCP profile
|
||||
|
||||
| Question | Current live profile | Gap type |
|
||||
| --- | --- | --- |
|
||||
| Q1 VAT | Generic movement probe | claim-specific live calls missing |
|
||||
| Q2 RBP | Live path absent | wrong route + missing live chain |
|
||||
| Q3 FA | Generic movement probe | object-scoped live chain missing |
|
||||
|
||||
## Query recipe examples in artifacts
|
||||
|
||||
- `docs/ARCH/9_audit_artifacts/query_recipe_examples/mcp_query_recipe_matrix.json`
|
||||
- `docs/ARCH/9_audit_artifacts/query_recipe_examples/Q1_VAT_recipe.md`
|
||||
- `docs/ARCH/9_audit_artifacts/query_recipe_examples/Q2_RBP_recipe.md`
|
||||
- `docs/ARCH/9_audit_artifacts/query_recipe_examples/Q3_FA_recipe.md`
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
# 9E — Source-to-Proof Failure Map
|
||||
|
||||
Дата: 2026-03-29
|
||||
|
||||
## Категории классификации
|
||||
- `missing_source_data`
|
||||
- `source_exists_but_runtime_does_not_use_it`
|
||||
- `wrong_route_selection`
|
||||
- `wrong_entity_mapping`
|
||||
- `missing_relation_reconstruction`
|
||||
- `live_call_insufficient_for_proof`
|
||||
- `evidence_not_materialized`
|
||||
- `claim_anchor_coverage_insufficient`
|
||||
- `answer_layer_cannot_close_proof`
|
||||
|
||||
## Q1 — VAT
|
||||
|
||||
### Что система должна была сделать
|
||||
Собрать и доказать цепочку: `receipt/sale doc -> invoice -> VAT register -> book entry -> posting consistency`.
|
||||
|
||||
### Что реально поднято
|
||||
- claim path собран, `admissible_evidence_count=12`, grounded-positive достигнут.
|
||||
- live call есть (`execute_query`, matched_rows=24).
|
||||
|
||||
### Где рвется/шумит
|
||||
- `live_call_insufficient_for_proof` (частично): live probe broad, не claim-targeted.
|
||||
- `evidence_not_materialized` (частично): высокий reject (`weak_source_mapping`, `wrong_account_scope`).
|
||||
|
||||
### Локальный verdict Q1
|
||||
`EVIDENCE_MATERIALIZATION_IS_PRIMARY_PROBLEM` (residual cleanup mode, non-blocking).
|
||||
|
||||
## Q2 — RBP
|
||||
|
||||
### Что система должна была сделать
|
||||
Доказать/опровергнуть хвост РБП к 31.07 через object-level цепочку `writeoff -> movements -> close -> residual`.
|
||||
|
||||
### Что реально поднято
|
||||
- route: canonical-only.
|
||||
- live calls: отсутствуют.
|
||||
- targeted checks: все `not_found`.
|
||||
- admissible evidence: `0`.
|
||||
|
||||
### Где рвется
|
||||
- `wrong_route_selection`
|
||||
- `source_exists_but_runtime_does_not_use_it`
|
||||
- `missing_relation_reconstruction`
|
||||
- `live_call_insufficient_for_proof`
|
||||
- `evidence_not_materialized`
|
||||
|
||||
### Локальный verdict Q2
|
||||
`SOURCE_COVERAGE_IS_PRIMARY_PROBLEM` (в комбинации с route gap).
|
||||
|
||||
## Q3 — FA amortization
|
||||
|
||||
### Что система должна была сделать
|
||||
Построить object-level proof полноты амортизации: expected FA set, per-object posting coverage, missing-object detection.
|
||||
|
||||
### Что реально поднято
|
||||
- live call есть, admissible evidence `19`.
|
||||
- итог всё равно limited: `claim_anchor_coverage_insufficient`.
|
||||
- в evidence встречается cross-domain noise (нерелевантные сущности для FA claim).
|
||||
|
||||
### Где рвется
|
||||
- `wrong_entity_mapping`
|
||||
- `missing_relation_reconstruction`
|
||||
- `live_call_insufficient_for_proof`
|
||||
- `claim_anchor_coverage_insufficient`
|
||||
- `answer_layer_cannot_close_proof`
|
||||
|
||||
### Локальный verdict Q3
|
||||
`ONE_C_RELATION_MAPPING_IS_PRIMARY_PROBLEM` (с evidence/anchor side-effects).
|
||||
|
||||
## Сводный failure map
|
||||
|
||||
| Question | Primary break nodes | Result mode |
|
||||
| --- | --- | --- |
|
||||
| Q1 VAT | evidence materialization residuals | grounded-positive |
|
||||
| Q2 RBP | source coverage + route + missing relation reconstruction | limited |
|
||||
| Q3 FA | relation mapping + claim-anchor closure | limited |
|
||||
|
||||
## Общий verdict
|
||||
|
||||
`MULTI_NODE_FAILURE_CONFIRMED`
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
# 9F — Current Runtime vs Required Runtime
|
||||
|
||||
Дата: 2026-03-29
|
||||
|
||||
## 1) Сравнение по этапам контура
|
||||
|
||||
| Stage | Required runtime behavior | Current runtime behavior | Gap |
|
||||
| --- | --- | --- | --- |
|
||||
| Anchor extraction | Claim-specific anchors (period + entity/object + account/doc links) | Есть claim layer, но coverage нестабильный на FA/RBP | partial gap |
|
||||
| Route selection | Выбор route по required proof path | Для RBP уходит в canonical-only | high gap |
|
||||
| Source selection | Targeted source scope per claim | Ограниченный snapshot subset + broad fallback patterns | high gap |
|
||||
| Relation reconstruction | Object-level relation chain reconstruction | Частично (VAT лучше, RBP/FA хуже) | high gap |
|
||||
| Live call plan | Sequence of claim-bound MCP calls | 0 или 1 generic `execute_query` probe | blocker/high gap |
|
||||
| Evidence materialization | Candidate -> admissible aligned with claim links | Часто высокий reject шум | high gap |
|
||||
| Answer handoff | Grounded when claim proof closed, limited when not | Работает, но Q3 блокируется при non-zero admissible из-за anchor closure | medium-high gap |
|
||||
|
||||
## 2) Required vs current per question
|
||||
|
||||
### Q1 VAT
|
||||
- Required: цепочка doc->invoice->register->book + posting proof.
|
||||
- Current: в целом закрывает positive path.
|
||||
- Gap: current live query слишком broad, admissibility много отбрасывает.
|
||||
|
||||
### Q2 RBP
|
||||
- Required: object-level RBP lifecycle + residual classification.
|
||||
- Current: canonical route, live path не включен, admissible=0.
|
||||
- Gap: route/source/relation/live одновременно недожаты.
|
||||
|
||||
### Q3 FA
|
||||
- Required: expected FA set + per-object depreciation coverage.
|
||||
- Current: live есть, admissible есть, но proof closure нет.
|
||||
- Gap: relation/object mapping и claim-anchor closure.
|
||||
|
||||
## 3) Что должен делать required runtime (минимум)
|
||||
|
||||
1. Для каждого claim строить relation-aware execution graph.
|
||||
2. Подключать claim-specific live call sequence, а не одиночный broad probe.
|
||||
3. Материализовать evidence в object-level chain links.
|
||||
4. Закрывать eligibility на claim-level coverage, а не на сигнальном surrogate.
|
||||
|
||||
## 4) Что делает current runtime сейчас
|
||||
|
||||
1. Имеет рабочий positive path на VAT.
|
||||
2. Сохраняет limited mode честно, но часто из-за pipeline-level разрывов (не только из-за отсутствия данных).
|
||||
3. Не имеет стабильного object-level proof path для RBP и FA.
|
||||
|
||||
## 5) Runtime delta verdict
|
||||
|
||||
- Q1: near-required with residual materialization cleanup.
|
||||
- Q2: far-from-required.
|
||||
- Q3: mid-gap (data/evidence есть, closure нет).
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
# Chat Export (3 Control Questions)
|
||||
|
||||
Источник replay: `x:\1C\NDC_1C\docs\ARCH\8_audit_artifacts\question_replay_logs\1_live_replay.txt`
|
||||
|
||||
## Q1 — НДС (L1)
|
||||
**User question**
|
||||
13 июля проведено поступление товаров, а 15 июля — реализация этих же мебельных позиций. НДС-цепочка по этим движениям у нас полная или где-то есть выпадение между документом, проводкой и налоговым отражением?
|
||||
|
||||
**Runtime outcome**
|
||||
- `reply_type`: `factual_with_explanation`
|
||||
- `claim_type`: `prove_vat_chain_completeness`
|
||||
- `grounding_mode`: `grounded_positive`
|
||||
- `admissible_evidence_count`: `12`
|
||||
- `eligibility_outcome`: `grounded_allowed`
|
||||
- `reason_codes`: none
|
||||
|
||||
## Q2 — РБП (L2)
|
||||
**User question**
|
||||
31 июля прошло «Списание РБП за Июль 2020 г.», в том числе на 5 000 и ещё несколько сумм. Есть ли в базе признаки, что часть РБП к концу июля всё ещё живёт дольше ожидаемого?
|
||||
|
||||
**Runtime outcome**
|
||||
- `reply_type`: `partial_coverage`
|
||||
- `claim_type`: `prove_rbp_tail_state`
|
||||
- `grounding_mode`: `limited_or_insufficient_evidence`
|
||||
- `admissible_evidence_count`: `0`
|
||||
- `eligibility_outcome`: `limited_or_insufficient_evidence`
|
||||
- `reason_codes`: `admissible_evidence_count_zero`, `targeted_evidence_hit_rate_zero`
|
||||
|
||||
## Q3 — Амортизация (L3)
|
||||
**User question**
|
||||
31 июля начислена амортизация тремя суммами — 2 471,52, 2 465,28 и 849,83. Это похоже на полное начисление по всем нужным объектам за июль или есть риск, что какой-то объект ОС в июле не попал в амортизацию?
|
||||
|
||||
**Runtime outcome**
|
||||
- `reply_type`: `partial_coverage`
|
||||
- `claim_type`: `prove_month_close_state`
|
||||
- `grounding_mode`: `limited_or_insufficient_evidence`
|
||||
- `admissible_evidence_count`: `19`
|
||||
- `eligibility_outcome`: `limited_or_insufficient_evidence`
|
||||
- `reason_codes`: `claim_anchor_coverage_insufficient`
|
||||
|
||||
## Быстрый итог по 3 вопросам
|
||||
- 1 кейс вышел в `grounded_positive`.
|
||||
- 2 кейса остались в `partial_coverage`.
|
||||
- Основные причины ограничения: `admissible_evidence_count_zero` (Q2) и `claim_anchor_coverage_insufficient` (Q3).
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,15 @@
|
|||
# Q1 VAT — MCP Query Recipe
|
||||
|
||||
Current runtime call:
|
||||
- `execute_query` generic accounting-register probe (broad, not claim-specific).
|
||||
|
||||
Required proof-oriented call sequence:
|
||||
1. `execute_query:find_receipt_document_by_date_item`
|
||||
2. `execute_query:find_sale_document_by_date_item`
|
||||
3. `execute_query:find_invoice_links_for_receipt_sale`
|
||||
4. `execute_query:find_vat_register_entries_by_invoice`
|
||||
5. `execute_query:find_sales_purchase_book_entries`
|
||||
6. `execute_query:cross_check_document_postings`
|
||||
|
||||
Why current call is insufficient:
|
||||
- returns broad movements without explicit invoice/register/book linkage.
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
# Q2 RBP — MCP Query Recipe
|
||||
|
||||
Current runtime call:
|
||||
- no live call selected (both fragments routed to canonical snapshot path).
|
||||
|
||||
Required proof-oriented call sequence:
|
||||
1. `execute_query:find_rbp_writeoff_documents_in_period`
|
||||
2. `execute_query:find_rbp_object_movements_account_97`
|
||||
3. `execute_query:find_month_close_entries_linked_to_rbp`
|
||||
4. `execute_query:compute_end_period_residual_by_rbp_object`
|
||||
5. `execute_query:classify_normal_vs_abnormal_residual`
|
||||
|
||||
Why current path is insufficient:
|
||||
- object-level RBP lifecycle is not reconstructed in live path.
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
# Q3 FA — MCP Query Recipe
|
||||
|
||||
Current runtime call:
|
||||
- `execute_query` generic accounting-register probe.
|
||||
|
||||
Required proof-oriented call sequence:
|
||||
1. `execute_query:find_fa_objects_expected_in_period`
|
||||
2. `execute_query:find_depreciation_documents_2020_07`
|
||||
3. `execute_query:map_fa_object_to_depreciation_rows`
|
||||
4. `execute_query:cross_check_postings_accounts_02_20_44`
|
||||
5. `execute_query:detect_missing_fa_objects_without_depreciation`
|
||||
|
||||
Why current call is insufficient:
|
||||
- object scope is missing, which causes claim-anchor coverage gap.
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
[
|
||||
{
|
||||
"question_id": "Q1_VAT",
|
||||
"question": "13/15 July VAT chain completeness",
|
||||
"required_live_calls": [
|
||||
"execute_query:find_receipt_document_by_date_item",
|
||||
"execute_query:find_sale_document_by_date_item",
|
||||
"execute_query:find_invoice_links_for_receipt_sale",
|
||||
"execute_query:find_vat_register_entries_by_invoice",
|
||||
"execute_query:find_sales_purchase_book_entries",
|
||||
"execute_query:cross_check_document_postings"
|
||||
],
|
||||
"current_live_calls": [
|
||||
"execute_query:generic_accounting_register_probe"
|
||||
],
|
||||
"missing_live_calls": [
|
||||
"execute_query:find_receipt_document_by_date_item",
|
||||
"execute_query:find_sale_document_by_date_item",
|
||||
"execute_query:find_invoice_links_for_receipt_sale",
|
||||
"execute_query:find_vat_register_entries_by_invoice",
|
||||
"execute_query:find_sales_purchase_book_entries",
|
||||
"execute_query:cross_check_document_postings"
|
||||
],
|
||||
"wrong_live_calls": [
|
||||
"execute_query:generic_accounting_register_probe_without_claim_filters"
|
||||
],
|
||||
"call_sequence_for_proof": [
|
||||
"seed_by_receipt_sale_docs",
|
||||
"resolve_invoice_links",
|
||||
"resolve_vat_register_rows",
|
||||
"resolve_book_entries",
|
||||
"validate_doc_to_posting_chain",
|
||||
"build_admissible_chain_summary"
|
||||
]
|
||||
},
|
||||
{
|
||||
"question_id": "Q2_RBP",
|
||||
"question": "RBP write-off and residual tail at 2020-07-31",
|
||||
"required_live_calls": [
|
||||
"execute_query:find_rbp_writeoff_documents_in_period",
|
||||
"execute_query:find_rbp_object_movements_account_97",
|
||||
"execute_query:find_month_close_entries_linked_to_rbp",
|
||||
"execute_query:compute_end_period_residual_by_rbp_object",
|
||||
"execute_query:classify_normal_vs_abnormal_residual"
|
||||
],
|
||||
"current_live_calls": [
|
||||
|
||||
],
|
||||
"missing_live_calls": [
|
||||
"execute_query:find_rbp_writeoff_documents_in_period",
|
||||
"execute_query:find_rbp_object_movements_account_97",
|
||||
"execute_query:find_month_close_entries_linked_to_rbp",
|
||||
"execute_query:compute_end_period_residual_by_rbp_object",
|
||||
"execute_query:classify_normal_vs_abnormal_residual"
|
||||
],
|
||||
"wrong_live_calls": [
|
||||
"no_live_call_selected_due_to_canonical_route"
|
||||
],
|
||||
"call_sequence_for_proof": [
|
||||
"seed_by_writeoff_doc",
|
||||
"bind_to_rbp_object",
|
||||
"collect_97_movements",
|
||||
"collect_close_entries",
|
||||
"compute_residual_tail",
|
||||
"produce_tail_state_verdict"
|
||||
]
|
||||
},
|
||||
{
|
||||
"question_id": "Q3_FA",
|
||||
"question": "FA amortization completeness for 2020-07 with 3 amounts",
|
||||
"required_live_calls": [
|
||||
"execute_query:find_fa_objects_expected_in_period",
|
||||
"execute_query:find_depreciation_documents_2020_07",
|
||||
"execute_query:map_fa_object_to_depreciation_rows",
|
||||
"execute_query:cross_check_postings_accounts_02_20_44",
|
||||
"execute_query:detect_missing_fa_objects_without_depreciation"
|
||||
],
|
||||
"current_live_calls": [
|
||||
"execute_query:generic_accounting_register_probe"
|
||||
],
|
||||
"missing_live_calls": [
|
||||
"execute_query:find_fa_objects_expected_in_period",
|
||||
"execute_query:find_depreciation_documents_2020_07",
|
||||
"execute_query:map_fa_object_to_depreciation_rows",
|
||||
"execute_query:cross_check_postings_accounts_02_20_44",
|
||||
"execute_query:detect_missing_fa_objects_without_depreciation"
|
||||
],
|
||||
"wrong_live_calls": [
|
||||
"execute_query:generic_accounting_register_probe_without_object_scope"
|
||||
],
|
||||
"call_sequence_for_proof": [
|
||||
"seed_by_fa_amounts_and_period",
|
||||
"resolve_expected_fa_set",
|
||||
"resolve_depreciation_docs",
|
||||
"map_object_level_postings",
|
||||
"detect_missed_objects",
|
||||
"produce_completeness_verdict"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"generated_at": "2026-03-29T05:48:19.981Z",
|
||||
"aggregate": {
|
||||
"wrong_period": 36,
|
||||
"wrong_domain": 8,
|
||||
"wrong_account_scope": 20,
|
||||
"weak_source_mapping": 42,
|
||||
"zero_live_match": 0,
|
||||
"future_dated_or_out_of_window": 8
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "L1",
|
||||
"label": "vat_chain_furniture_13_15_july",
|
||||
"reject_breakdown": {
|
||||
"wrong_period": 0,
|
||||
"wrong_domain": 0,
|
||||
"wrong_account_scope": 12,
|
||||
"weak_source_mapping": 14,
|
||||
"zero_live_match": 0,
|
||||
"future_dated_or_out_of_window": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "L2",
|
||||
"label": "rbp_tail_31_july_5000",
|
||||
"reject_breakdown": {
|
||||
"wrong_period": 36,
|
||||
"wrong_domain": 0,
|
||||
"wrong_account_scope": 0,
|
||||
"weak_source_mapping": 12,
|
||||
"zero_live_match": 0,
|
||||
"future_dated_or_out_of_window": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "L3",
|
||||
"label": "fa_amortization_2471_2465_849",
|
||||
"reject_breakdown": {
|
||||
"wrong_period": 0,
|
||||
"wrong_domain": 8,
|
||||
"wrong_account_scope": 8,
|
||||
"weak_source_mapping": 16,
|
||||
"zero_live_match": 0,
|
||||
"future_dated_or_out_of_window": 8
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"generated_at": "2026-03-29T05:48:19.981Z",
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "L1",
|
||||
"label": "vat_chain_furniture_13_15_july",
|
||||
"business_scope_raw": [
|
||||
"company_specific_accounting"
|
||||
],
|
||||
"business_scope_resolved": [
|
||||
"company_specific_accounting"
|
||||
],
|
||||
"company_scope_resolution_reason": [
|
||||
"temporal_claim_bound_company_scope_recovery"
|
||||
]
|
||||
},
|
||||
{
|
||||
"case_id": "L2",
|
||||
"label": "rbp_tail_31_july_5000",
|
||||
"business_scope_raw": [
|
||||
"company_specific_accounting"
|
||||
],
|
||||
"business_scope_resolved": [
|
||||
"company_specific_accounting"
|
||||
],
|
||||
"company_scope_resolution_reason": [
|
||||
"temporal_claim_bound_company_scope_recovery"
|
||||
]
|
||||
},
|
||||
{
|
||||
"case_id": "L3",
|
||||
"label": "fa_amortization_2471_2465_849",
|
||||
"business_scope_raw": [
|
||||
"company_specific_accounting"
|
||||
],
|
||||
"business_scope_resolved": [
|
||||
"company_specific_accounting"
|
||||
],
|
||||
"company_scope_resolution_reason": [
|
||||
"temporal_claim_bound_company_scope_recovery"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metric": {
|
||||
"live_company_scope_resolution_rate": 1
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
{
|
||||
"generated_at": "2026-03-29T05:48:19.981Z",
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "L1",
|
||||
"label": "vat_chain_furniture_13_15_july",
|
||||
"claim_type": "prove_vat_chain_completeness",
|
||||
"admissible_evidence_count": 12,
|
||||
"live_calls": [
|
||||
{
|
||||
"fragment_id": "F2",
|
||||
"route": "hybrid_store_plus_live",
|
||||
"method": "execute_query",
|
||||
"args_summary": null,
|
||||
"query_subject": "vat_chain_conflict",
|
||||
"account_scope": [],
|
||||
"fetched_rows": 24,
|
||||
"returned_rows": 12,
|
||||
"matched_rows": 24,
|
||||
"status": "ok"
|
||||
}
|
||||
],
|
||||
"claim_targeted_hit_rate": 1,
|
||||
"eligibility": {
|
||||
"eligible": true,
|
||||
"grounding_mode": "grounded_positive",
|
||||
"outcome": "grounded_allowed",
|
||||
"reason_codes": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "L2",
|
||||
"label": "rbp_tail_31_july_5000",
|
||||
"claim_type": "prove_rbp_tail_state",
|
||||
"admissible_evidence_count": 0,
|
||||
"live_calls": [],
|
||||
"claim_targeted_hit_rate": 0,
|
||||
"eligibility": {
|
||||
"eligible": false,
|
||||
"grounding_mode": "limited_or_insufficient_evidence",
|
||||
"outcome": "limited_or_insufficient_evidence",
|
||||
"reason_codes": [
|
||||
"admissible_evidence_count_zero",
|
||||
"targeted_evidence_hit_rate_zero"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "L3",
|
||||
"label": "fa_amortization_2471_2465_849",
|
||||
"claim_type": "prove_month_close_state",
|
||||
"admissible_evidence_count": 19,
|
||||
"live_calls": [
|
||||
{
|
||||
"fragment_id": "F2",
|
||||
"route": "hybrid_store_plus_live",
|
||||
"method": "execute_query",
|
||||
"args_summary": null,
|
||||
"query_subject": "fixed_asset_card_mismatch",
|
||||
"account_scope": [],
|
||||
"fetched_rows": 24,
|
||||
"returned_rows": 12,
|
||||
"matched_rows": 24,
|
||||
"status": "ok"
|
||||
}
|
||||
],
|
||||
"claim_targeted_hit_rate": 1,
|
||||
"eligibility": {
|
||||
"eligible": false,
|
||||
"grounding_mode": "limited_or_insufficient_evidence",
|
||||
"outcome": "limited_or_insufficient_evidence",
|
||||
"reason_codes": [
|
||||
"claim_anchor_coverage_insufficient"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
{
|
||||
"generated_at": "2026-03-29T05:48:19.980Z",
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "L1",
|
||||
"label": "vat_chain_furniture_13_15_july",
|
||||
"raw_time_scope": "2020-07",
|
||||
"resolved_time_anchor": "2020-07-13",
|
||||
"effective_primary_period": {
|
||||
"from": "2020-07-13",
|
||||
"to": "2020-07-13",
|
||||
"granularity": "day"
|
||||
},
|
||||
"temporal_guard_input": "2020-07-13..2020-07-13",
|
||||
"temporal_guard_basis": "resolved_primary_period",
|
||||
"eligibility_time_basis": "resolved_primary_period",
|
||||
"temporal_guard_outcome": "passed",
|
||||
"contradiction": {
|
||||
"has_july_effective_primary_period": true,
|
||||
"temporal_guard_outcome": "passed",
|
||||
"temporal_basis_mismatch": false,
|
||||
"failed_under_july_effective_period": false,
|
||||
"contradiction": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "L2",
|
||||
"label": "rbp_tail_31_july_5000",
|
||||
"raw_time_scope": "2020-07",
|
||||
"resolved_time_anchor": "2020-07-31",
|
||||
"effective_primary_period": {
|
||||
"from": "2020-07-31",
|
||||
"to": "2020-07-31",
|
||||
"granularity": "day"
|
||||
},
|
||||
"temporal_guard_input": "2020-07-31..2020-07-31",
|
||||
"temporal_guard_basis": "resolved_primary_period",
|
||||
"eligibility_time_basis": "resolved_primary_period",
|
||||
"temporal_guard_outcome": "passed",
|
||||
"contradiction": {
|
||||
"has_july_effective_primary_period": true,
|
||||
"temporal_guard_outcome": "passed",
|
||||
"temporal_basis_mismatch": false,
|
||||
"failed_under_july_effective_period": false,
|
||||
"contradiction": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "L3",
|
||||
"label": "fa_amortization_2471_2465_849",
|
||||
"raw_time_scope": "2020-07",
|
||||
"resolved_time_anchor": "2020-07-31",
|
||||
"effective_primary_period": {
|
||||
"from": "2020-07-31",
|
||||
"to": "2020-07-31",
|
||||
"granularity": "day"
|
||||
},
|
||||
"temporal_guard_input": "2020-07-31..2020-07-31",
|
||||
"temporal_guard_basis": "resolved_primary_period",
|
||||
"eligibility_time_basis": "resolved_primary_period",
|
||||
"temporal_guard_outcome": "passed",
|
||||
"contradiction": {
|
||||
"has_july_effective_primary_period": true,
|
||||
"temporal_guard_outcome": "passed",
|
||||
"temporal_basis_mismatch": false,
|
||||
"failed_under_july_effective_period": false,
|
||||
"contradiction": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"metric": {
|
||||
"live_temporal_contradiction_rate": 0
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,139 @@
|
|||
{
|
||||
"generated_at": "2026-03-29T09:50:58",
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "L1",
|
||||
"label": "vat_chain_furniture_13_15_july",
|
||||
"claim_type": "prove_vat_chain_completeness",
|
||||
"question_type_class": "which_chains_are_complete_vs_incomplete",
|
||||
"routes": [
|
||||
{
|
||||
"fragment_id": "F1",
|
||||
"route": "store_canonical",
|
||||
"reason": "Only plain factual lookups are allowed to stay on canonical path. Query class: canonical_fact_lookup. Allowed fallback: no_route. Forbidden fallback: hybrid_store_plus_live."
|
||||
},
|
||||
{
|
||||
"fragment_id": "F2",
|
||||
"route": "hybrid_store_plus_live",
|
||||
"reason": "Lifecycle-first intents are deterministically promoted to hybrid path. Query class: lifecycle_first. Allowed fallback: no_route. Forbidden fallback: store_canonical."
|
||||
}
|
||||
],
|
||||
"required_checks": [
|
||||
"source_document_found",
|
||||
"invoice_found",
|
||||
"tax_register_entry_found",
|
||||
"book_entry_found",
|
||||
"chain_linkage_status"
|
||||
],
|
||||
"check_status": {
|
||||
"source_document_found": "found",
|
||||
"invoice_found": "found",
|
||||
"tax_register_entry_found": "found",
|
||||
"book_entry_found": "found",
|
||||
"chain_linkage_status": "found"
|
||||
},
|
||||
"candidate_evidence_total": 30,
|
||||
"admissible_evidence_count": 12,
|
||||
"reject_breakdown": {
|
||||
"wrong_period": 0,
|
||||
"wrong_domain": 0,
|
||||
"wrong_account_scope": 12,
|
||||
"weak_source_mapping": 14,
|
||||
"zero_live_match": 0,
|
||||
"future_dated_or_out_of_window": 0
|
||||
},
|
||||
"eligibility_outcome": "grounded_allowed",
|
||||
"grounding_mode": "grounded_positive",
|
||||
"reason_codes": [
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
"case_id": "L2",
|
||||
"label": "rbp_tail_31_july_5000",
|
||||
"claim_type": "prove_rbp_tail_state",
|
||||
"question_type_class": "what_is_it_grounded_on",
|
||||
"routes": [
|
||||
{
|
||||
"fragment_id": "F1",
|
||||
"route": "store_canonical",
|
||||
"reason": "Only plain factual lookups are allowed to stay on canonical path. Query class: canonical_fact_lookup. Allowed fallback: no_route. Forbidden fallback: hybrid_store_plus_live."
|
||||
},
|
||||
{
|
||||
"fragment_id": "F2",
|
||||
"route": "store_canonical",
|
||||
"reason": "Only plain factual lookups are allowed to stay on canonical path. Query class: canonical_fact_lookup. Allowed fallback: no_route. Forbidden fallback: hybrid_store_plus_live."
|
||||
}
|
||||
],
|
||||
"required_checks": [
|
||||
"rbp_writeoff_lifecycle_confirmed",
|
||||
"residual_tail_found",
|
||||
"close_contradiction_or_normal_residual"
|
||||
],
|
||||
"check_status": {
|
||||
"rbp_writeoff_lifecycle_confirmed": "not_found",
|
||||
"residual_tail_found": "not_found",
|
||||
"close_contradiction_or_normal_residual": "not_found"
|
||||
},
|
||||
"candidate_evidence_total": 12,
|
||||
"admissible_evidence_count": 0,
|
||||
"reject_breakdown": {
|
||||
"wrong_period": 36,
|
||||
"wrong_domain": 0,
|
||||
"wrong_account_scope": 0,
|
||||
"weak_source_mapping": 12,
|
||||
"zero_live_match": 0,
|
||||
"future_dated_or_out_of_window": 0
|
||||
},
|
||||
"eligibility_outcome": "limited_or_insufficient_evidence",
|
||||
"grounding_mode": "limited_or_insufficient_evidence",
|
||||
"reason_codes": [
|
||||
"admissible_evidence_count_zero",
|
||||
"targeted_evidence_hit_rate_zero"
|
||||
]
|
||||
},
|
||||
{
|
||||
"case_id": "L3",
|
||||
"label": "fa_amortization_2471_2465_849",
|
||||
"claim_type": "prove_month_close_state",
|
||||
"question_type_class": "why_breaks",
|
||||
"routes": [
|
||||
{
|
||||
"fragment_id": "F1",
|
||||
"route": "store_feature_risk",
|
||||
"reason": "Rule checks without symptom/lifecycle signals run via risk profile path. Query class: rule_check_without_symptom. Allowed fallback: no_route. Forbidden fallback: store_canonical."
|
||||
},
|
||||
{
|
||||
"fragment_id": "F2",
|
||||
"route": "hybrid_store_plus_live",
|
||||
"reason": "Lifecycle-first intents are deterministically promoted to hybrid path. Query class: lifecycle_first. Allowed fallback: no_route. Forbidden fallback: store_canonical."
|
||||
}
|
||||
],
|
||||
"required_checks": [
|
||||
"close_operation_found",
|
||||
"distribution_step_found",
|
||||
"residual_tail_found"
|
||||
],
|
||||
"check_status": {
|
||||
"close_operation_found": "found",
|
||||
"distribution_step_found": "found",
|
||||
"residual_tail_found": "found"
|
||||
},
|
||||
"candidate_evidence_total": 35,
|
||||
"admissible_evidence_count": 19,
|
||||
"reject_breakdown": {
|
||||
"wrong_period": 0,
|
||||
"wrong_domain": 8,
|
||||
"wrong_account_scope": 8,
|
||||
"weak_source_mapping": 16,
|
||||
"zero_live_match": 0,
|
||||
"future_dated_or_out_of_window": 8
|
||||
},
|
||||
"eligibility_outcome": "limited_or_insufficient_evidence",
|
||||
"grounding_mode": "limited_or_insufficient_evidence",
|
||||
"reason_codes": [
|
||||
"claim_anchor_coverage_insufficient"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,14 @@
|
|||
# Chat Export Live Replay
|
||||
|
||||
## L1 | vat_chain_furniture_13_15_july
|
||||
user: 13 июля проведено поступление товаров, а 15 июля — реализация этих же мебельных позиций. НДС-цепочка по этим движениям у нас полная или где-то есть выпадение между документом, проводкой и налоговым отражением?
|
||||
assistant(reply_type=factual_with_explanation, trace_id=i2sI02TOEt-jx_): Коротко: Цепочки разделены на подтвержденные, частично подтвержденные и неподтвержденные. Что сломано: - Ожидаемый переход в учетной цепочке не подтвержден; подтверждение пока частичное, вывод ограничен. Почему это похоже на проблему: - Цепочки разделены на завершенные и незавершенные по текущей опоре. - Часть НДС-цепочки подтверждена, но один или несколько переходов документ -> счет-фактура -> регистр -> книга не подтверждены. На чем это основано: - Опора собрана по НДС-звеньям, чтобы разделить полные и неполные переходы. - Опора собрана по звеньям НДС-цепочки, чтобы разделить полные и неполные переходы. - Вывод опирается на 10 подтвержденных наблюдений в текущем срезе. - Проверены связанные документы и проводки по 6 источникам. - Есть связка между основным выводом и подтверждающими записями. - Опора частичная: по НДС-цепочке не подтверждены одно или несколько звеньев. - Цепочки пока не удалось уверенно разделить на полные и неполные. Что проверить первым: - Сначала разложите НДС-цепочку по шагам: документ -> счет-фактура -> регистр -> книга. - Проверьте ОС-контур: объект ОС -> ввод в эксплуатацию -> начисление амортизации по счетам 01/02. - Сверьте параметр амортизации и наличие начисления по каждому объекту ОС в периоде. Ограничения: - Деление на «complete/incomplete» зависит от полноты цепочки в текущем срезе. - Надежность problem-сигнала низкая, поэтому вывод ограничен. - Оценка сделана на snapshot-срезе и может не включать часть цепочки. - Live probe использует ограниченный выборочный read-only запрос к 1С.
|
||||
|
||||
## L2 | rbp_tail_31_july_5000
|
||||
user: 31 июля прошло “Списание РБП за Июль 2020 г.”, в том числе на 5 000 и ещё несколько сумм. Есть ли в базе признаки, что часть РБП к концу июля всё ещё живёт дольше ожидаемого?
|
||||
assistant(reply_type=partial_coverage, trace_id=kDTLdj1FllFHW4): Коротко: Ниже перечислены основания вывода по списание, остаток и подтверждение на конец периода. Что сломано: - Цепочка затрат и закрытия месяца подтверждена только частично; подтверждение пока частичное, вывод ограничен. Почему это похоже на проблему: - Фокус ответа по подтверждение списания и остатка на конец периода, а не общий close-narrative. - Ожидаемая цепочка списания выглядит незавершенной. - По часть списаний к концу периода подтверждена не полностью, поэтому остаток может сохраняться дольше ожидаемого. На чем это основано: - Опора перечислена по РБП-объектам, документам списания и остаткам на конец периода. - Основание собрано по объект списания, документ списания и остаток на конец периода. - Опора частичная: не по всем объектам подтверждено списание к концу периода. - Отдельно не подтверждено или покрыто частично: R1, R2. - В опоре использованы якоря вопроса: 2020, period:2020. Что проверить первым: - Сначала перечислите по объект, документ списания и остаток после списания на конец периода. - Перечислите основание по объект, документ списания, движение по счету 97, остаток на конец периода. Ограничения: - В основание включены только подтвержденные источники; неподтвержденные вынесены в ограничения. - Якоря из вопроса без прямого подтверждения: 5 000. - Надежность problem-сигнала низкая, поэтому вывод ограничен. - Оценка сделана на snapshot-срезе и может не включать часть цепочки. - Canonical output ограничен доменным runtime-контрактом. - Ни одно требование не получило подтвержденного покрытия.
|
||||
|
||||
## L3 | fa_amortization_2471_2465_849
|
||||
user: 31 июля начислена амортизация тремя суммами — 2 471,52, 2 465,28 и 849,83. Это похоже на полное начисление по всем нужным объектам за июль или есть риск, что какой-то объект ОС в июле не попал в амортизацию?
|
||||
assistant(reply_type=partial_coverage, trace_id=tSRTKmvWeBFIig): Коротко: Наиболее вероятный механизм проблемы подтвержден частично и требует первичной проверки. Что сломано: - подтверждение пока частичное, вывод ограничен. Почему это похоже на проблему: - Переход от карточки ОС к начислению амортизации подтвержден не полностью. - По ОС часть переходов к начислению амортизации подтверждена не полностью, поэтому есть риск пропуска отдельных объектов. На чем это основано: - Вывод опирается на 10 подтвержденных наблюдений в текущем срезе. - Проверены связанные документы и проводки по 6 источникам. - Есть связка между основным выводом и подтверждающими записями. - Опора частичная: не по всем объектам ОС подтверждено попадание в начисление амортизации. - Подтверждено по требованиям: R1. Что проверить первым: - Проверьте ОС-контур: объект ОС -> ввод в эксплуатацию -> начисление амортизации по счетам 01/02. - Сверьте параметр амортизации и наличие начисления по каждому объекту ОС в периоде. Ограничения: - Якоря из вопроса без прямого подтверждения: 2 471,52, 2 465,28, 849,83. - Механизм проблемы подтвержден не полностью. - Надежность problem-сигнала низкая, поэтому вывод ограничен. - Риск-факторы определяются эвристикой, а не полным набором бизнес-правил 1С. - Часть нерелевантных записей исключена domain purity фильтром. - Оценка сделана на snapshot-срезе и может не включать часть цепочки.
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
# Live Case Matrix
|
||||
|
||||
| Case | Label | Reply | Claim Type | Admissible Evidence | Grounding Mode | Scope | Temporal |
|
||||
| --- | --- | --- | --- | ---: | --- | --- | --- |
|
||||
| L1 | vat_chain_furniture_13_15_july | factual_with_explanation | prove_vat_chain_completeness | 12 | grounded_positive | company_specific_accounting | passed |
|
||||
| L2 | rbp_tail_31_july_5000 | partial_coverage | prove_rbp_tail_state | 0 | limited_or_insufficient_evidence | company_specific_accounting | passed |
|
||||
| L3 | fa_amortization_2471_2465_849 | partial_coverage | prove_month_close_state | 19 | limited_or_insufficient_evidence | company_specific_accounting | passed |
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# Live Replay Report (Wave 19.2)
|
||||
|
||||
## Source
|
||||
- Source of truth replayed from: `X:\1C\NDC_1C\llm_normalizer\docs\runs\2026-03-29_Stage_04_Wave_19_1_Live_Alignment_Fix_Claim_Bound_Runtime\1.txt`
|
||||
- Replayed exactly 3 user turns from the original export.
|
||||
- Runtime path: MCP ON, useMock=true.
|
||||
|
||||
## Metrics
|
||||
- live_temporal_contradiction_rate: 0
|
||||
- live_company_scope_resolution_rate: 1
|
||||
- live_admissible_evidence_nonzero_rate: 0.6667
|
||||
- live_partial_coverage_default_rate: 0.6667
|
||||
- baseline_partial_coverage_default_rate: 1
|
||||
- live_claim_path_completion_rate: 0.6667
|
||||
- live_false_grounded_answer_rate: 0
|
||||
|
||||
## Verdict
|
||||
- LIVE_TEMPORAL_ALIGNMENT_FIXED: FIXED
|
||||
- LIVE_COMPANY_SCOPE_FIXED: FIXED
|
||||
- LIVE_EVIDENCE_PATH_FIXED: FIXED
|
||||
- LIVE_PARTIAL_COVERAGE_DEFAULT_REDUCED: REDUCED
|
||||
- Overall: WAVE19_2_ACCEPTED
|
||||
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"generated_at": "2026-03-29T09:22:59",
|
||||
"cases": [
|
||||
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"run_id": "2026-03-29_Stage_04_Wave_19_2_Live_Runtime_Fix_Replay_1txt",
|
||||
"stage": "Stage_04",
|
||||
"wave": "Wave_19_2",
|
||||
"scope": "live_runtime_fix_by_replay_1txt",
|
||||
"source_of_truth": "X:\\1C\\NDC_1C\\llm_normalizer\\docs\\runs\\2026-03-29_Stage_04_Wave_19_1_Live_Alignment_Fix_Claim_Bound_Runtime\\1.txt",
|
||||
"execution": {
|
||||
"replay_mode": "exact_questions_from_1_txt",
|
||||
"runtime_path": "assistant_message_with_mcp_runtime_on",
|
||||
"normalizer_mode": "useMock=true",
|
||||
"session_id": "asst-wave19_2-1774763298275"
|
||||
},
|
||||
"thresholds": {
|
||||
"live_temporal_contradiction_rate": 0,
|
||||
"live_company_scope_resolution_rate": 1,
|
||||
"live_false_grounded_answer_rate": 0,
|
||||
"live_admissible_evidence_nonzero_min_cases": 2
|
||||
},
|
||||
"metrics": {
|
||||
"case_count": 3,
|
||||
"baseline_partial_coverage_default_rate": 1,
|
||||
"live_temporal_contradiction_rate": 0,
|
||||
"live_company_scope_resolution_rate": 1,
|
||||
"live_admissible_evidence_nonzero_rate": 0.6667,
|
||||
"live_partial_coverage_default_rate": 0.6667,
|
||||
"live_claim_path_completion_rate": 0.6667,
|
||||
"live_false_grounded_answer_rate": 0
|
||||
},
|
||||
"verdicts": {
|
||||
"LIVE_TEMPORAL_ALIGNMENT_FIXED": "FIXED",
|
||||
"LIVE_COMPANY_SCOPE_FIXED": "FIXED",
|
||||
"LIVE_EVIDENCE_PATH_FIXED": "FIXED",
|
||||
"LIVE_PARTIAL_COVERAGE_DEFAULT_REDUCED": "REDUCED",
|
||||
"overall_status": "WAVE19_2_ACCEPTED"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
[
|
||||
{
|
||||
"case_id": "L1",
|
||||
"label": "vat_chain_furniture_13_15_july",
|
||||
"claim_type": "prove_vat_chain_completeness",
|
||||
"routes": "store_canonical -\u003e hybrid_store_plus_live",
|
||||
"business_scope_resolved": "company_specific_accounting",
|
||||
"resolved_time_anchor": "2020-07-13",
|
||||
"temporal_guard_outcome": "passed",
|
||||
"admissible_evidence_count": 12,
|
||||
"grounding_mode": "grounded_positive",
|
||||
"reply_type": "factual_with_explanation"
|
||||
},
|
||||
{
|
||||
"case_id": "L2",
|
||||
"label": "rbp_tail_31_july_5000",
|
||||
"claim_type": "prove_rbp_tail_state",
|
||||
"routes": "store_canonical -\u003e store_canonical",
|
||||
"business_scope_resolved": "company_specific_accounting",
|
||||
"resolved_time_anchor": "2020-07-31",
|
||||
"temporal_guard_outcome": "passed",
|
||||
"admissible_evidence_count": 0,
|
||||
"grounding_mode": "limited_or_insufficient_evidence",
|
||||
"reply_type": "partial_coverage"
|
||||
},
|
||||
{
|
||||
"case_id": "L3",
|
||||
"label": "fa_amortization_2471_2465_849",
|
||||
"claim_type": "prove_month_close_state",
|
||||
"routes": "store_feature_risk -\u003e hybrid_store_plus_live",
|
||||
"business_scope_resolved": "company_specific_accounting",
|
||||
"resolved_time_anchor": "2020-07-31",
|
||||
"temporal_guard_outcome": "passed",
|
||||
"admissible_evidence_count": 19,
|
||||
"grounding_mode": "limited_or_insufficient_evidence",
|
||||
"reply_type": "partial_coverage"
|
||||
}
|
||||
]
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
# 2020 экспорт: состав выгрузки
|
||||
|
||||
Папка собрана автоматически для ручного анализа текущего состояния.
|
||||
|
||||
## Файлы
|
||||
|
||||
1. `01_ontology_mapping_layer.md` — текущая онтология/мэппинг и метрики среза.
|
||||
2. `02_canonical_relation_rules.md` — правила построения canonical relations.
|
||||
3. `03_snapshot_fragment_problem_cases.json` — проблемный фрагмент snapshot июня 2020.
|
||||
4. `04_samples_SpisanieSRaschetnogoScheta.json` — реальные записи по `СписаниеСРасчетногоСчета`.
|
||||
5. `05_samples_RealizaciyaTovarovUslug.json` — реальные записи по `РеализацияТоваровУслуг`.
|
||||
6. `06_samples_PostuplenieTovarovUslug.json` — реальные записи по `ПоступлениеТоваровУслуг`.
|
||||
7. `07_samples_DocumentJournals.json` — реальные записи по журналам документов.
|
||||
8. `08_samples_NDS_registers.json` — реальные записи по НДС-регистрам.
|
||||
9. `09_samples_key_fields_Recorder_Ref_Supplier_Buyer_Responsible.json` — записи с ключевыми полями.
|
||||
|
||||
## Ключевые поля: фактическая встречаемость в snapshot
|
||||
|
||||
| field | count |
|
||||
| --- | --- |
|
||||
| Ответственный_Key | 187 |
|
||||
| Ref | 168 |
|
||||
| Recorder | 147 |
|
||||
| Ref_Key | 93 |
|
||||
| Поставщик_Key | 78 |
|
||||
| Покупатель_Key | 46 |
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,112 @@
|
|||
{
|
||||
"status": "success",
|
||||
"snapshot_mode": "cumulative_asof",
|
||||
"year": 2020,
|
||||
"service_root": "http://localhost/buh_test/odata/standard.odata/",
|
||||
"entity_sets_total": 2,
|
||||
"entity_sets": [
|
||||
"AccountingRegister_Хозрасчетный",
|
||||
"AccountingRegister_Хозрасчетный_RecordType"
|
||||
],
|
||||
"page_size": 500,
|
||||
"max_pages_per_set": 0,
|
||||
"include_undated": "all_months",
|
||||
"truncated_entity_sets_count": 0,
|
||||
"truncated_entity_sets": [],
|
||||
"records_exported_per_month": {
|
||||
"2020-01": 15113,
|
||||
"2020-02": 15211,
|
||||
"2020-03": 15508,
|
||||
"2020-04": 15578,
|
||||
"2020-05": 15648,
|
||||
"2020-06": 15953,
|
||||
"2020-07": 16039,
|
||||
"2020-08": 16122,
|
||||
"2020-09": 16175,
|
||||
"2020-10": 16212,
|
||||
"2020-11": 16308,
|
||||
"2020-12": 16377
|
||||
},
|
||||
"dated_records_exported_per_month": {
|
||||
"2020-01": 10644,
|
||||
"2020-02": 10742,
|
||||
"2020-03": 11039,
|
||||
"2020-04": 11109,
|
||||
"2020-05": 11179,
|
||||
"2020-06": 11484,
|
||||
"2020-07": 11570,
|
||||
"2020-08": 11653,
|
||||
"2020-09": 11706,
|
||||
"2020-10": 11743,
|
||||
"2020-11": 11839,
|
||||
"2020-12": 11908
|
||||
},
|
||||
"undated_records_exported_per_month": {
|
||||
"2020-01": 4469,
|
||||
"2020-02": 4469,
|
||||
"2020-03": 4469,
|
||||
"2020-04": 4469,
|
||||
"2020-05": 4469,
|
||||
"2020-06": 4469,
|
||||
"2020-07": 4469,
|
||||
"2020-08": 4469,
|
||||
"2020-09": 4469,
|
||||
"2020-10": 4469,
|
||||
"2020-11": 4469,
|
||||
"2020-12": 4469
|
||||
},
|
||||
"links_exported_per_month": {
|
||||
"2020-01": 47623,
|
||||
"2020-02": 48036,
|
||||
"2020-03": 49243,
|
||||
"2020-04": 49539,
|
||||
"2020-05": 49834,
|
||||
"2020-06": 51071,
|
||||
"2020-07": 51426,
|
||||
"2020-08": 51769,
|
||||
"2020-09": 51992,
|
||||
"2020-10": 52151,
|
||||
"2020-11": 52545,
|
||||
"2020-12": 52831
|
||||
},
|
||||
"entity_set_stats": {
|
||||
"AccountingRegister_Хозрасчетный": {
|
||||
"pages_read": 9,
|
||||
"records_scanned": 4469,
|
||||
"records_mapped": 4469,
|
||||
"records_with_datetime": 0,
|
||||
"records_without_datetime": 4469,
|
||||
"records_skipped_future": 0,
|
||||
"mapping_errors": 0,
|
||||
"truncated_by_limit_or_guard": false,
|
||||
"pagination_repeat_guard_hits": 0
|
||||
},
|
||||
"AccountingRegister_Хозрасчетный_RecordType": {
|
||||
"pages_read": 26,
|
||||
"records_scanned": 12659,
|
||||
"records_mapped": 11908,
|
||||
"records_with_datetime": 12659,
|
||||
"records_without_datetime": 0,
|
||||
"records_skipped_future": 751,
|
||||
"mapping_errors": 0,
|
||||
"truncated_by_limit_or_guard": false,
|
||||
"pagination_repeat_guard_hits": 0
|
||||
}
|
||||
},
|
||||
"snapshot_files": [
|
||||
"snapshot_2020-01_asof_full.json",
|
||||
"snapshot_2020-02_asof_full.json",
|
||||
"snapshot_2020-03_asof_full.json",
|
||||
"snapshot_2020-04_asof_full.json",
|
||||
"snapshot_2020-05_asof_full.json",
|
||||
"snapshot_2020-06_asof_full.json",
|
||||
"snapshot_2020-07_asof_full.json",
|
||||
"snapshot_2020-08_asof_full.json",
|
||||
"snapshot_2020-09_asof_full.json",
|
||||
"snapshot_2020-10_asof_full.json",
|
||||
"snapshot_2020-11_asof_full.json",
|
||||
"snapshot_2020-12_asof_full.json"
|
||||
],
|
||||
"output_dir": "x:\\1C\\NDC_1C\\docs\\ARCH\\2020_monthly_company_asof_full_test",
|
||||
"generated_at_utc": "2026-03-27T21:34:24.669751+00:00"
|
||||
}
|
||||
|
|
@ -256,7 +256,15 @@ function requiredChecksByClaim(claimType) {
|
|||
if (claimType === "prove_month_close_state") {
|
||||
return ["close_operation_found", "distribution_step_found", "residual_tail_found"];
|
||||
}
|
||||
return ["rbp_writeoff_lifecycle_confirmed", "residual_tail_found", "close_contradiction_or_normal_residual"];
|
||||
return [
|
||||
"rbp_writeoff_document_found",
|
||||
"rbp_object_identified",
|
||||
"rbp_movement_found",
|
||||
"rbp_period_end_residual_found",
|
||||
"rbp_writeoff_lifecycle_confirmed",
|
||||
"residual_tail_found",
|
||||
"close_contradiction_or_normal_residual"
|
||||
];
|
||||
}
|
||||
function detectChecksForCorpus(corpus, claimType, anchors) {
|
||||
const checks = new Set();
|
||||
|
|
@ -276,6 +284,10 @@ function detectChecksForCorpus(corpus, claimType, anchors) {
|
|||
const hasRbp = /(?:\brbp\b|рбп|account\s*97|счет\s*97|deferred)/i.test(corpus);
|
||||
const hasResidual = /(?:tail|остат|незакры|overdue|period_boundary|terminal_state_gap)/i.test(corpus);
|
||||
const hasContradiction = /(?:contradiction|invalid_transition|normal residual|нормальн)/i.test(corpus);
|
||||
const hasRbpWriteoffDoc = /(?:списани[ея]\s+рбп|rbp_writeoff|deferred_expense_document|writeoff document)/i.test(corpus);
|
||||
const hasRbpObject = /(?:rbp[_\s-]?object|объект\s+рбп|analytics|subkonto|расходыбудущихпериодов)/i.test(corpus);
|
||||
const hasMovement = /(?:movement|движен|хозрасчетный|document_to_posting|posting|проводк)/i.test(corpus);
|
||||
const hasPeriodEndResidual = /(?:period_boundary|end_period|2020-07-31|остат)/i.test(corpus);
|
||||
if (claimType === "prove_settlement_closure_state") {
|
||||
if (hasPayment)
|
||||
checks.add("payment_document_found");
|
||||
|
|
@ -325,6 +337,14 @@ function detectChecksForCorpus(corpus, claimType, anchors) {
|
|||
checks.add("residual_tail_found");
|
||||
}
|
||||
else {
|
||||
if (hasRbpWriteoffDoc || (hasRbp && hasDistribution))
|
||||
checks.add("rbp_writeoff_document_found");
|
||||
if (hasRbpObject || hasRbp)
|
||||
checks.add("rbp_object_identified");
|
||||
if (hasMovement)
|
||||
checks.add("rbp_movement_found");
|
||||
if (hasPeriodEndResidual || hasResidual)
|
||||
checks.add("rbp_period_end_residual_found");
|
||||
if (hasRbp && hasDistribution)
|
||||
checks.add("rbp_writeoff_lifecycle_confirmed");
|
||||
if (hasResidual)
|
||||
|
|
|
|||
|
|
@ -67,6 +67,26 @@ const MCP_LIVE_MOVEMENTS_QUERY_TEMPLATE = `
|
|||
УПОРЯДОЧИТЬ ПО
|
||||
Движения.Период УБЫВ
|
||||
`;
|
||||
const MCP_LIVE_MOVEMENTS_BY_PERIOD_QUERY_TEMPLATE = `
|
||||
ВЫБРАТЬ ПЕРВЫЕ __LIMIT__
|
||||
Движения.Период КАК Период,
|
||||
ПРЕДСТАВЛЕНИЕ(Движения.Регистратор) КАК Регистратор,
|
||||
ПРЕДСТАВЛЕНИЕ(Движения.СчетДт) КАК СчетДт,
|
||||
ПРЕДСТАВЛЕНИЕ(Движения.СчетКт) КАК СчетКт,
|
||||
Движения.Сумма КАК Сумма
|
||||
ИЗ
|
||||
РегистрБухгалтерии.Хозрасчетный КАК Движения
|
||||
ГДЕ
|
||||
Движения.Период МЕЖДУ __FROM_DATETIME__ И __TO_DATETIME__
|
||||
УПОРЯДОЧИТЬ ПО
|
||||
Движения.Период УБЫВ
|
||||
`;
|
||||
const RBP_REQUIRED_LIVE_CALLS = [
|
||||
"find_rbp_writeoff_documents_in_period",
|
||||
"find_rbp_object_movements_account_97",
|
||||
"find_month_close_entries_linked_to_rbp",
|
||||
"compute_end_period_residual_by_rbp_object"
|
||||
];
|
||||
function pushUniqueLine(target, line) {
|
||||
if (!target.includes(line)) {
|
||||
target.push(line);
|
||||
|
|
@ -94,6 +114,129 @@ function parseFiniteNumber(value) {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
function formatIsoDateUtc(date) {
|
||||
const year = date.getUTCFullYear();
|
||||
const month = String(date.getUTCMonth() + 1).padStart(2, "0");
|
||||
const day = String(date.getUTCDate()).padStart(2, "0");
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
function monthEndFromIso(isoDate) {
|
||||
const match = String(isoDate ?? "").match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
const year = Number(match[1]);
|
||||
const month = Number(match[2]);
|
||||
if (!Number.isFinite(year) || !Number.isFinite(month)) {
|
||||
return null;
|
||||
}
|
||||
const end = new Date(Date.UTC(year, month, 0));
|
||||
return formatIsoDateUtc(end);
|
||||
}
|
||||
function shiftIsoDate(isoDate, deltaDays) {
|
||||
const match = String(isoDate ?? "").match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
const date = new Date(Date.UTC(Number(match[1]), Number(match[2]) - 1, Number(match[3])));
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return null;
|
||||
}
|
||||
date.setUTCDate(date.getUTCDate() + deltaDays);
|
||||
return formatIsoDateUtc(date);
|
||||
}
|
||||
function toDateTimeExpr(isoDate, endOfDay) {
|
||||
const match = String(isoDate ?? "").match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
const year = Number(match[1]);
|
||||
const month = Number(match[2]);
|
||||
const day = Number(match[3]);
|
||||
if (!Number.isFinite(year) || !Number.isFinite(month) || !Number.isFinite(day)) {
|
||||
return null;
|
||||
}
|
||||
const hour = endOfDay ? 23 : 0;
|
||||
const minute = endOfDay ? 59 : 0;
|
||||
const second = endOfDay ? 59 : 0;
|
||||
return `ДАТАВРЕМЯ(${year}, ${month}, ${day}, ${hour}, ${minute}, ${second})`;
|
||||
}
|
||||
function buildLiveRangeQuery(fromIso, toIso, limit) {
|
||||
const fromExpr = toDateTimeExpr(fromIso, false);
|
||||
const toExpr = toDateTimeExpr(toIso, true);
|
||||
if (!fromExpr || !toExpr) {
|
||||
return MCP_LIVE_MOVEMENTS_QUERY_TEMPLATE.replace("__LIMIT__", String(limit));
|
||||
}
|
||||
return MCP_LIVE_MOVEMENTS_BY_PERIOD_QUERY_TEMPLATE.replace("__LIMIT__", String(limit))
|
||||
.replace("__FROM_DATETIME__", fromExpr)
|
||||
.replace("__TO_DATETIME__", toExpr);
|
||||
}
|
||||
function hasRbpSignal(text) {
|
||||
return /(?:\brbp\b|рбп|расходы\s+будущих\s+периодов|deferred|writeoff|списани[ея]\s+рбп|account\s*97|счет\s*97)/i.test(String(text ?? "").toLowerCase());
|
||||
}
|
||||
function buildLiveMcpCallPlan(route, fragmentText) {
|
||||
const semanticProfile = buildSemanticRetrievalProfile(fragmentText);
|
||||
const rbpClaim = hasRbpSignal(fragmentText) ||
|
||||
semanticProfile.query_subject === "deferred_expense_lifecycle_anomaly" ||
|
||||
semanticProfile.domain_scope.includes("deferred_expense");
|
||||
if (!rbpClaim) {
|
||||
return {
|
||||
claim_type: null,
|
||||
query_subject: semanticProfile.query_subject,
|
||||
required_live_calls: [],
|
||||
calls: [
|
||||
{
|
||||
call_id: "generic_accounting_register_probe",
|
||||
purpose: "live_overlay_probe",
|
||||
query: MCP_LIVE_MOVEMENTS_QUERY_TEMPLATE.replace("__LIMIT__", String(config_1.ASSISTANT_MCP_LIVE_LIMIT)),
|
||||
required_for_claim: false
|
||||
}
|
||||
],
|
||||
route_gap_reason: null
|
||||
};
|
||||
}
|
||||
const periodScope = inferPeriodScope(fragmentText);
|
||||
const primaryFrom = periodScope.from ?? "2020-07-01";
|
||||
const primaryTo = periodScope.to ?? monthEndFromIso(primaryFrom) ?? "2020-07-31";
|
||||
const carryFrom = shiftIsoDate(primaryFrom, -31) ?? primaryFrom;
|
||||
const carryTo = shiftIsoDate(primaryTo, 31) ?? primaryTo;
|
||||
return {
|
||||
claim_type: "prove_rbp_tail_state",
|
||||
query_subject: "deferred_expense_lifecycle_anomaly",
|
||||
required_live_calls: [...RBP_REQUIRED_LIVE_CALLS],
|
||||
calls: [
|
||||
{
|
||||
call_id: "find_rbp_writeoff_documents_in_period",
|
||||
purpose: "seed_writeoff_documents",
|
||||
query: buildLiveRangeQuery(primaryFrom, primaryTo, config_1.ASSISTANT_MCP_LIVE_LIMIT),
|
||||
required_for_claim: true,
|
||||
account_scope_override: ["97", "20", "25", "26", "44"]
|
||||
},
|
||||
{
|
||||
call_id: "find_rbp_object_movements_account_97",
|
||||
purpose: "collect_rbp_object_movements",
|
||||
query: buildLiveRangeQuery(primaryFrom, primaryTo, config_1.ASSISTANT_MCP_LIVE_LIMIT),
|
||||
required_for_claim: true,
|
||||
account_scope_override: ["97"]
|
||||
},
|
||||
{
|
||||
call_id: "find_month_close_entries_linked_to_rbp",
|
||||
purpose: "link_month_close_to_rbp",
|
||||
query: buildLiveRangeQuery(primaryFrom, primaryTo, config_1.ASSISTANT_MCP_LIVE_LIMIT),
|
||||
required_for_claim: true,
|
||||
account_scope_override: ["97", "20", "25", "26", "44"]
|
||||
},
|
||||
{
|
||||
call_id: "compute_end_period_residual_by_rbp_object",
|
||||
purpose: "collect_residual_tail_signals",
|
||||
query: buildLiveRangeQuery(carryFrom, carryTo, config_1.ASSISTANT_MCP_LIVE_LIMIT),
|
||||
required_for_claim: true,
|
||||
account_scope_override: ["97", "20", "25", "26", "44"]
|
||||
}
|
||||
],
|
||||
route_gap_reason: null
|
||||
};
|
||||
}
|
||||
function detectBroadQuery(fragmentText, route) {
|
||||
const text = String(fragmentText ?? "").trim();
|
||||
const lower = text.toLowerCase();
|
||||
|
|
@ -2024,73 +2167,158 @@ class AssistantDataLayer {
|
|||
return merged;
|
||||
}
|
||||
async fetchLiveMcpOverlay(route, fragmentText) {
|
||||
const accountScope = extractAccountScopeFromText(fragmentText);
|
||||
const endpoint = this.buildMcpUrl("/api/execute_query");
|
||||
const query = MCP_LIVE_MOVEMENTS_QUERY_TEMPLATE.replace("__LIMIT__", String(config_1.ASSISTANT_MCP_LIVE_LIMIT));
|
||||
const livePlan = buildLiveMcpCallPlan(route, fragmentText);
|
||||
const explicitAccountScope = extractAccountScopeFromText(fragmentText);
|
||||
const accountScope = explicitAccountScope.length > 0
|
||||
? explicitAccountScope
|
||||
: livePlan.claim_type === "prove_rbp_tail_state"
|
||||
? ["97", "20", "25", "26", "44"]
|
||||
: [];
|
||||
const callExecutions = [];
|
||||
const collectedRows = [];
|
||||
const errors = [];
|
||||
let fetchedRowsTotal = 0;
|
||||
let matchedRowsTotal = 0;
|
||||
for (const call of livePlan.calls) {
|
||||
const callAccountScope = Array.isArray(call.account_scope_override) && call.account_scope_override.length > 0
|
||||
? call.account_scope_override
|
||||
: accountScope;
|
||||
try {
|
||||
const payload = await this.fetchJsonWithTimeout(endpoint, {
|
||||
query,
|
||||
query: call.query,
|
||||
limit: config_1.ASSISTANT_MCP_LIVE_LIMIT
|
||||
});
|
||||
const parsed = this.parseExecuteQueryPayload(payload);
|
||||
if (parsed.error) {
|
||||
return {
|
||||
errors.push(parsed.error);
|
||||
callExecutions.push({
|
||||
call_id: call.call_id,
|
||||
purpose: call.purpose,
|
||||
required_for_claim: call.required_for_claim,
|
||||
status: "error",
|
||||
items: [],
|
||||
evidence: [],
|
||||
summary: {
|
||||
enabled: true,
|
||||
status: "error",
|
||||
route,
|
||||
channel: config_1.ASSISTANT_MCP_CHANNEL,
|
||||
proxy: config_1.ASSISTANT_MCP_PROXY_URL,
|
||||
account_scope: accountScope,
|
||||
fetched_rows: 0,
|
||||
matched_rows: 0,
|
||||
returned_rows: 0,
|
||||
error: parsed.error
|
||||
},
|
||||
selection_reason: ["Live MCP probe завершился ошибкой, использован snapshot fallback."],
|
||||
limitations: ["Live MCP недоступен или вернул ошибку; результат ограничен локальным snapshot."],
|
||||
errors: [parsed.error]
|
||||
};
|
||||
});
|
||||
continue;
|
||||
}
|
||||
const matchedRows = this.filterLiveRowsByAccountScope(parsed.rows, accountScope);
|
||||
const rowsForAnswer = matchedRows.length > 0 || accountScope.length === 0 ? matchedRows : parsed.rows;
|
||||
const items = this.toLiveOverlayItems(rowsForAnswer.slice(0, 12), route);
|
||||
const evidence = items.slice(0, 8).map((item) => ({
|
||||
const matchedRows = this.filterLiveRowsByAccountScope(parsed.rows, callAccountScope);
|
||||
const rowsForAnswer = callAccountScope.length > 0 ? matchedRows : parsed.rows;
|
||||
fetchedRowsTotal += parsed.rows.length;
|
||||
matchedRowsTotal += matchedRows.length;
|
||||
for (const row of rowsForAnswer) {
|
||||
collectedRows.push({
|
||||
...row,
|
||||
__live_call_id: call.call_id,
|
||||
__live_call_purpose: call.purpose,
|
||||
__claim_type: livePlan.claim_type,
|
||||
__query_subject: livePlan.query_subject,
|
||||
__account_scope_applied: callAccountScope
|
||||
});
|
||||
}
|
||||
callExecutions.push({
|
||||
call_id: call.call_id,
|
||||
purpose: call.purpose,
|
||||
required_for_claim: call.required_for_claim,
|
||||
status: rowsForAnswer.length > 0 ? "ok" : "empty",
|
||||
fetched_rows: parsed.rows.length,
|
||||
matched_rows: matchedRows.length,
|
||||
returned_rows: rowsForAnswer.length,
|
||||
error: null
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
errors.push(errorMessage);
|
||||
callExecutions.push({
|
||||
call_id: call.call_id,
|
||||
purpose: call.purpose,
|
||||
required_for_claim: call.required_for_claim,
|
||||
status: "error",
|
||||
fetched_rows: 0,
|
||||
matched_rows: 0,
|
||||
returned_rows: 0,
|
||||
error: errorMessage
|
||||
});
|
||||
}
|
||||
}
|
||||
const items = this.toLiveOverlayItems(collectedRows.slice(0, 16), route);
|
||||
const evidence = items.slice(0, 12).map((item) => ({
|
||||
source_entity: item.source_entity,
|
||||
source_id: item.source_id,
|
||||
source_namespace: "assistant_derived",
|
||||
period: item.period,
|
||||
account_debit: item.account_debit,
|
||||
account_credit: item.account_credit
|
||||
account_credit: item.account_credit,
|
||||
source_layer: item.source_layer,
|
||||
document_context: item.document_context,
|
||||
relation_pattern_hits: item.relation_pattern_hits,
|
||||
lifecycle_markers: item.lifecycle_markers,
|
||||
live_call_id: item.live_call_id,
|
||||
live_call_purpose: item.live_call_purpose,
|
||||
claim_type: item.claim_type
|
||||
}));
|
||||
const executedRequiredCalls = callExecutions
|
||||
.filter((item) => item.required_for_claim && item.status !== "error")
|
||||
.map((item) => item.call_id);
|
||||
const missingLiveCalls = livePlan.required_live_calls.filter((callId) => !executedRequiredCalls.includes(callId));
|
||||
const liveRouteExecutionRate = livePlan.required_live_calls.length > 0
|
||||
? Number((executedRequiredCalls.length / livePlan.required_live_calls.length).toFixed(4))
|
||||
: 1;
|
||||
const routeGapReason = missingLiveCalls.length > 0
|
||||
? "required_live_calls_not_executed"
|
||||
: livePlan.claim_type && matchedRowsTotal <= 0
|
||||
? "claim_live_calls_executed_but_zero_matches"
|
||||
: livePlan.route_gap_reason;
|
||||
const selectionReason = [
|
||||
`Live MCP probe: ${parsed.rows.length} rows fetched from 1C register.`,
|
||||
livePlan.claim_type
|
||||
? `Claim-bound live path selected for ${livePlan.claim_type}.`
|
||||
: `Live MCP probe: ${fetchedRowsTotal} rows fetched from 1C register.`,
|
||||
accountScope.length > 0
|
||||
? `Account scope filter (${accountScope.join(", ")}) matched ${matchedRows.length} rows.`
|
||||
? `Account scope filter (${accountScope.join(", ")}) matched ${matchedRowsTotal} rows.`
|
||||
: "Account scope filter was not applied."
|
||||
];
|
||||
const limitations = [
|
||||
"Live probe использует ограниченный выборочный read-only запрос к 1С."
|
||||
];
|
||||
if (missingLiveCalls.length > 0) {
|
||||
limitations.push(`Required live calls were not executed: ${missingLiveCalls.join(", ")}.`);
|
||||
}
|
||||
if (items.length === 0) {
|
||||
limitations.push("Live probe не вернул строк, релевантных текущему запросу.");
|
||||
}
|
||||
if (errors.length > 0) {
|
||||
limitations.push("Часть live вызовов завершилась ошибкой; включен ограниченный fallback.");
|
||||
}
|
||||
const status = items.length > 0 ? "ok" : callExecutions.every((item) => item.status === "error") ? "error" : "empty";
|
||||
return {
|
||||
status: items.length > 0 ? "ok" : "empty",
|
||||
status,
|
||||
items,
|
||||
evidence,
|
||||
summary: {
|
||||
enabled: true,
|
||||
status: items.length > 0 ? "ok" : "empty",
|
||||
status,
|
||||
route,
|
||||
channel: config_1.ASSISTANT_MCP_CHANNEL,
|
||||
proxy: config_1.ASSISTANT_MCP_PROXY_URL,
|
||||
source_profile: livePlan.claim_type ? "claim_bound_rbp_live_path" : "generic_live_probe",
|
||||
claim_type: livePlan.claim_type,
|
||||
query_subject: livePlan.query_subject,
|
||||
account_scope: accountScope,
|
||||
fetched_rows: parsed.rows.length,
|
||||
matched_rows: matchedRows.length,
|
||||
returned_rows: items.length
|
||||
fetched_rows: fetchedRowsTotal,
|
||||
matched_rows: matchedRowsTotal,
|
||||
returned_rows: items.length,
|
||||
required_live_calls: livePlan.required_live_calls,
|
||||
executed_live_calls: callExecutions,
|
||||
missing_live_calls: missingLiveCalls,
|
||||
live_route_execution_rate: liveRouteExecutionRate,
|
||||
route_gap_reason: routeGapReason
|
||||
},
|
||||
selection_reason: selectionReason,
|
||||
limitations,
|
||||
errors: []
|
||||
errors
|
||||
};
|
||||
}
|
||||
async fetchJsonWithTimeout(url, body) {
|
||||
|
|
@ -2249,6 +2477,36 @@ class AssistantDataLayer {
|
|||
const baseId = `${route}-mcp-${index + 1}`;
|
||||
const sourceId = periodRaw ? `${baseId}-${periodRaw}` : baseId;
|
||||
const displayName = registrator || `Live movement row #${index + 1}`;
|
||||
const accountContext = uniqueStrings([debit, credit].filter((item) => item.length > 0));
|
||||
const callId = valueAsString(row.__live_call_id ?? "").trim();
|
||||
const callPurpose = valueAsString(row.__live_call_purpose ?? "").trim();
|
||||
const claimType = valueAsString(row.__claim_type ?? "").trim() || null;
|
||||
const querySubject = valueAsString(row.__query_subject ?? "").trim() || null;
|
||||
const registratorLower = registrator.toLowerCase();
|
||||
const hasRbpByDocument = /(?:рбп|deferred|списани[ея]\s+рбп)/i.test(registratorLower);
|
||||
const hasAccount97 = accountContext.some((item) => /^97(?:\.|$)/.test(item));
|
||||
const hasCloseDoc = /(?:закрыти[ея]\s+месяц|period\s*close|month\s*close|close\s+operation)/i.test(registratorLower) ||
|
||||
callId.includes("month_close");
|
||||
const relationPatternHits = uniqueStrings([
|
||||
"document_to_posting",
|
||||
hasRbpByDocument || hasAccount97 ? "deferred_expense_to_writeoff" : "",
|
||||
hasCloseDoc ? "close_operation" : "",
|
||||
callId.includes("residual") ? "residuals_zero_or_explained" : ""
|
||||
]);
|
||||
const documentContext = uniqueStrings([
|
||||
hasRbpByDocument || hasAccount97 ? "deferred_expense_document" : "",
|
||||
hasCloseDoc ? "period_close_document" : "",
|
||||
"posting"
|
||||
]);
|
||||
const graphDomainScope = uniqueStrings([
|
||||
hasRbpByDocument || hasAccount97 ? "deferred_expense" : "",
|
||||
hasCloseDoc ? "period_close" : ""
|
||||
]);
|
||||
const lifecycleMarkers = uniqueStrings([
|
||||
callId.includes("residual") ? "period_boundary" : "",
|
||||
callId.includes("residual") ? "tail_state_observed" : "",
|
||||
hasCloseDoc ? "close_operation" : ""
|
||||
]);
|
||||
return {
|
||||
source_entity: "MCPLiveMovement",
|
||||
source_id: sourceId,
|
||||
|
|
@ -2256,6 +2514,16 @@ class AssistantDataLayer {
|
|||
period: periodRaw || null,
|
||||
account_debit: debit || null,
|
||||
account_credit: credit || null,
|
||||
account_context: accountContext,
|
||||
document_context: documentContext,
|
||||
relation_pattern_hits: relationPatternHits,
|
||||
graph_domain_scope: graphDomainScope,
|
||||
lifecycle_markers: lifecycleMarkers,
|
||||
source_namespace: "assistant_derived",
|
||||
live_call_id: callId || null,
|
||||
live_call_purpose: callPurpose || null,
|
||||
claim_type: claimType,
|
||||
query_subject: querySubject,
|
||||
amount,
|
||||
source_layer: "mcp_live_probe",
|
||||
route
|
||||
|
|
|
|||
|
|
@ -620,6 +620,159 @@ function toExecutionPlan(routeSummary, normalized, userMessage, requirementByFra
|
|||
};
|
||||
});
|
||||
}
|
||||
function enrichRbpFragmentForLive(fragmentText, temporalGuard) {
|
||||
const base = compactWhitespace(String(fragmentText ?? ""));
|
||||
const hints = ["Списание РБП", "объект РБП", "остаток на конец периода", "счет 97"];
|
||||
const effective = temporalGuard && typeof temporalGuard === "object" ? temporalGuard.effective_primary_period : null;
|
||||
if (effective && effective.from && effective.to) {
|
||||
hints.push(`период ${effective.from}..${effective.to}`);
|
||||
}
|
||||
const hintText = hints.filter(Boolean).join(", ");
|
||||
if (!base) {
|
||||
return hintText;
|
||||
}
|
||||
if (/списани[ея]\s+рбп|счет\s*97|account\s*97|остат/i.test(base)) {
|
||||
return base;
|
||||
}
|
||||
return `${base}; ${hintText}`;
|
||||
}
|
||||
function enforceRbpLiveRoutePlan(input) {
|
||||
if (input.claimType !== "prove_rbp_tail_state") {
|
||||
return {
|
||||
executionPlan: input.executionPlan,
|
||||
audit: null
|
||||
};
|
||||
}
|
||||
const requiredLiveCalls = [
|
||||
"find_rbp_writeoff_documents_in_period",
|
||||
"find_rbp_object_movements_account_97",
|
||||
"find_month_close_entries_linked_to_rbp",
|
||||
"compute_end_period_residual_by_rbp_object"
|
||||
];
|
||||
let routeAdjusted = 0;
|
||||
let rescuedNoRoute = 0;
|
||||
const replacedRoutes = [];
|
||||
const adjustedPlan = input.executionPlan.map((item) => {
|
||||
if (!item || typeof item !== "object") {
|
||||
return item;
|
||||
}
|
||||
if (item.should_execute !== true && item.no_route_reason === "insufficient_specificity") {
|
||||
rescuedNoRoute += 1;
|
||||
routeAdjusted += 1;
|
||||
return {
|
||||
...item,
|
||||
route: "live_mcp_drilldown",
|
||||
should_execute: true,
|
||||
no_route_reason: null,
|
||||
clarification_reason: null,
|
||||
fragment_text: enrichRbpFragmentForLive(item.fragment_text, input.temporalGuard)
|
||||
};
|
||||
}
|
||||
if (item.should_execute === true && item.route !== "hybrid_store_plus_live" && item.route !== "live_mcp_drilldown") {
|
||||
routeAdjusted += 1;
|
||||
if (item.route && item.route !== "no_route") {
|
||||
replacedRoutes.push(String(item.route));
|
||||
}
|
||||
return {
|
||||
...item,
|
||||
route: "hybrid_store_plus_live",
|
||||
fragment_text: enrichRbpFragmentForLive(item.fragment_text, input.temporalGuard)
|
||||
};
|
||||
}
|
||||
if (item.should_execute === true) {
|
||||
return {
|
||||
...item,
|
||||
fragment_text: enrichRbpFragmentForLive(item.fragment_text, input.temporalGuard)
|
||||
};
|
||||
}
|
||||
return item;
|
||||
});
|
||||
return {
|
||||
executionPlan: adjustedPlan,
|
||||
audit: {
|
||||
claim_type: "prove_rbp_tail_state",
|
||||
required_live_calls: requiredLiveCalls,
|
||||
route_adjustments_applied: routeAdjusted,
|
||||
rescued_no_route_fragments: rescuedNoRoute,
|
||||
replaced_routes: Array.from(new Set(replacedRoutes)),
|
||||
route_gap_reason: routeAdjusted > 0 ? "rbp_claim_bound_live_route_override_applied" : null
|
||||
}
|
||||
};
|
||||
}
|
||||
function collectRbpLiveRouteAudit(input) {
|
||||
if (input.claimType !== "prove_rbp_tail_state") {
|
||||
return null;
|
||||
}
|
||||
const required = new Set(Array.isArray(input.planAudit?.required_live_calls) ? input.planAudit.required_live_calls : []);
|
||||
const executed = [];
|
||||
const missing = new Set();
|
||||
const routeGaps = [];
|
||||
let matchedRowsTotal = 0;
|
||||
let returnedRowsTotal = 0;
|
||||
let fetchedRowsTotal = 0;
|
||||
for (const result of input.retrievalResults) {
|
||||
if (!result || typeof result !== "object") {
|
||||
continue;
|
||||
}
|
||||
const summary = result.summary && typeof result.summary === "object" ? result.summary : null;
|
||||
const live = summary && typeof summary.live_mcp === "object" && summary.live_mcp ? summary.live_mcp : null;
|
||||
if (!live) {
|
||||
continue;
|
||||
}
|
||||
const requiredCalls = Array.isArray(live.required_live_calls) ? live.required_live_calls : [];
|
||||
for (const callId of requiredCalls) {
|
||||
required.add(String(callId ?? "").trim());
|
||||
}
|
||||
const executedCalls = Array.isArray(live.executed_live_calls) ? live.executed_live_calls : [];
|
||||
for (const call of executedCalls) {
|
||||
if (!call || typeof call !== "object") {
|
||||
continue;
|
||||
}
|
||||
executed.push(call);
|
||||
}
|
||||
const missingCalls = Array.isArray(live.missing_live_calls) ? live.missing_live_calls : [];
|
||||
for (const callId of missingCalls) {
|
||||
const token = String(callId ?? "").trim();
|
||||
if (token) {
|
||||
missing.add(token);
|
||||
}
|
||||
}
|
||||
const routeGapReason = String(live.route_gap_reason ?? "").trim();
|
||||
if (routeGapReason) {
|
||||
routeGaps.push(routeGapReason);
|
||||
}
|
||||
fetchedRowsTotal += Number(live.fetched_rows ?? 0) || 0;
|
||||
matchedRowsTotal += Number(live.matched_rows ?? 0) || 0;
|
||||
returnedRowsTotal += Number(live.returned_rows ?? 0) || 0;
|
||||
}
|
||||
const requiredList = Array.from(required).filter(Boolean);
|
||||
const executedList = executed;
|
||||
const missingFromExecuted = requiredList.filter((callId) => !executedList.some((item) => String(item.call_id ?? "") === callId));
|
||||
for (const callId of missingFromExecuted) {
|
||||
missing.add(callId);
|
||||
}
|
||||
const missingList = Array.from(missing);
|
||||
const routeGapReason = missingList.length > 0
|
||||
? "required_live_calls_not_executed"
|
||||
: matchedRowsTotal <= 0
|
||||
? "claim_live_calls_executed_but_zero_matches"
|
||||
: routeGaps[0] ?? null;
|
||||
const executionRate = requiredList.length > 0
|
||||
? Number(((requiredList.length - missingList.length) / requiredList.length).toFixed(4))
|
||||
: 1;
|
||||
return {
|
||||
claim_type: "prove_rbp_tail_state",
|
||||
required_live_calls: requiredList,
|
||||
executed_live_calls: executedList,
|
||||
missing_live_calls: missingList,
|
||||
route_gap_reason: routeGapReason,
|
||||
live_route_execution_rate: executionRate,
|
||||
fetched_rows_total: fetchedRowsTotal,
|
||||
matched_rows_total: matchedRowsTotal,
|
||||
returned_rows_total: returnedRowsTotal,
|
||||
plan_override: input.planAudit ?? null
|
||||
};
|
||||
}
|
||||
function toDebugRoutes(routeSummary) {
|
||||
if (!routeSummary) {
|
||||
return [];
|
||||
|
|
@ -1471,6 +1624,12 @@ class AssistantService {
|
|||
const resolvedRouteSummary = businessScopeResolution.route_summary_resolved;
|
||||
const requirementExtraction = extractRequirements(resolvedRouteSummary, normalized.normalized, userMessage);
|
||||
let executionPlan = toExecutionPlan(resolvedRouteSummary, normalized.normalized, userMessage, requirementExtraction.byFragment);
|
||||
const rbpRoutePlanEnforcement = enforceRbpLiveRoutePlan({
|
||||
executionPlan,
|
||||
claimType: claimAnchorAudit.claim_type,
|
||||
temporalGuard
|
||||
});
|
||||
executionPlan = rbpRoutePlanEnforcement.executionPlan;
|
||||
executionPlan = (0, assistantRuntimeGuards_1.applyTemporalHintToExecutionPlan)(executionPlan, temporalGuard);
|
||||
executionPlan = (0, assistantRuntimeGuards_1.applyPolarityHintToExecutionPlan)(executionPlan, domainPolarityGuardInitial);
|
||||
const retrievalCalls = [];
|
||||
|
|
@ -1553,6 +1712,11 @@ class AssistantService {
|
|||
userMessage
|
||||
});
|
||||
retrievalResults = evidenceGateResult.retrievalResults;
|
||||
const rbpLiveRouteAudit = collectRbpLiveRouteAudit({
|
||||
claimType: claimAnchorAudit.claim_type,
|
||||
retrievalResults,
|
||||
planAudit: rbpRoutePlanEnforcement.audit
|
||||
});
|
||||
const coverageEvaluation = evaluateCoverage(requirementExtraction.requirements, retrievalResults);
|
||||
const groundingCheckBase = checkGrounding(userMessage, coverageEvaluation.requirements, coverageEvaluation.coverage, retrievalResults);
|
||||
const groundedAnswerEligibilityGuard = (0, assistantRuntimeGuards_1.evaluateGroundedAnswerEligibility)({
|
||||
|
|
@ -1665,6 +1829,7 @@ class AssistantService {
|
|||
claim_anchor_audit: claimAnchorAudit,
|
||||
targeted_evidence_acquisition: targetedEvidenceResult.audit,
|
||||
evidence_admissibility_gate: evidenceGateResult.audit,
|
||||
...(rbpLiveRouteAudit ? { rbp_live_route_audit: rbpLiveRouteAudit } : {}),
|
||||
eligibility_time_basis: groundedAnswerEligibilityGuard.eligibility_time_basis,
|
||||
grounded_answer_eligibility_guard: groundedAnswerEligibilityGuard,
|
||||
...(followupBinding.usage ? { followup_state_usage: followupBinding.usage } : {}),
|
||||
|
|
|
|||
|
|
@ -329,7 +329,15 @@ function requiredChecksByClaim(claimType: ClaimType): string[] {
|
|||
if (claimType === "prove_month_close_state") {
|
||||
return ["close_operation_found", "distribution_step_found", "residual_tail_found"];
|
||||
}
|
||||
return ["rbp_writeoff_lifecycle_confirmed", "residual_tail_found", "close_contradiction_or_normal_residual"];
|
||||
return [
|
||||
"rbp_writeoff_document_found",
|
||||
"rbp_object_identified",
|
||||
"rbp_movement_found",
|
||||
"rbp_period_end_residual_found",
|
||||
"rbp_writeoff_lifecycle_confirmed",
|
||||
"residual_tail_found",
|
||||
"close_contradiction_or_normal_residual"
|
||||
];
|
||||
}
|
||||
|
||||
function detectChecksForCorpus(corpus: string, claimType: ClaimType, anchors: Record<string, string[]>): string[] {
|
||||
|
|
@ -351,6 +359,10 @@ function detectChecksForCorpus(corpus: string, claimType: ClaimType, anchors: Re
|
|||
const hasRbp = /(?:\brbp\b|рбп|account\s*97|счет\s*97|deferred)/i.test(corpus);
|
||||
const hasResidual = /(?:tail|остат|незакры|overdue|period_boundary|terminal_state_gap)/i.test(corpus);
|
||||
const hasContradiction = /(?:contradiction|invalid_transition|normal residual|нормальн)/i.test(corpus);
|
||||
const hasRbpWriteoffDoc = /(?:списани[ея]\s+рбп|rbp_writeoff|deferred_expense_document|writeoff document)/i.test(corpus);
|
||||
const hasRbpObject = /(?:rbp[_\s-]?object|объект\s+рбп|analytics|subkonto|расходыбудущихпериодов)/i.test(corpus);
|
||||
const hasMovement = /(?:movement|движен|хозрасчетный|document_to_posting|posting|проводк)/i.test(corpus);
|
||||
const hasPeriodEndResidual = /(?:period_boundary|end_period|2020-07-31|остат)/i.test(corpus);
|
||||
|
||||
if (claimType === "prove_settlement_closure_state") {
|
||||
if (hasPayment) checks.add("payment_document_found");
|
||||
|
|
@ -377,6 +389,10 @@ function detectChecksForCorpus(corpus: string, claimType: ClaimType, anchors: Re
|
|||
if (hasDistribution) checks.add("distribution_step_found");
|
||||
if (hasResidual) checks.add("residual_tail_found");
|
||||
} else {
|
||||
if (hasRbpWriteoffDoc || (hasRbp && hasDistribution)) checks.add("rbp_writeoff_document_found");
|
||||
if (hasRbpObject || hasRbp) checks.add("rbp_object_identified");
|
||||
if (hasMovement) checks.add("rbp_movement_found");
|
||||
if (hasPeriodEndResidual || hasResidual) checks.add("rbp_period_end_residual_found");
|
||||
if (hasRbp && hasDistribution) checks.add("rbp_writeoff_lifecycle_confirmed");
|
||||
if (hasResidual) checks.add("residual_tail_found");
|
||||
if (hasContradiction || hasClose) checks.add("close_contradiction_or_normal_residual");
|
||||
|
|
|
|||
|
|
@ -65,6 +65,31 @@ interface LiveMcpOverlay {
|
|||
errors: string[];
|
||||
}
|
||||
|
||||
interface LiveMcpCallPlan {
|
||||
claim_type: string | null;
|
||||
query_subject: string;
|
||||
required_live_calls: string[];
|
||||
calls: Array<{
|
||||
call_id: string;
|
||||
purpose: string;
|
||||
query: string;
|
||||
required_for_claim: boolean;
|
||||
account_scope_override?: string[];
|
||||
}>;
|
||||
route_gap_reason: string | null;
|
||||
}
|
||||
|
||||
interface LiveMcpCallExecution {
|
||||
call_id: string;
|
||||
purpose: string;
|
||||
required_for_claim: boolean;
|
||||
status: "ok" | "empty" | "error";
|
||||
fetched_rows: number;
|
||||
matched_rows: number;
|
||||
returned_rows: number;
|
||||
error?: string | null;
|
||||
}
|
||||
|
||||
type BroadnessLevel = "low" | "medium" | "high";
|
||||
|
||||
interface BroadQueryAssessment {
|
||||
|
|
@ -150,6 +175,28 @@ const MCP_LIVE_MOVEMENTS_QUERY_TEMPLATE = `
|
|||
Движения.Период УБЫВ
|
||||
`;
|
||||
|
||||
const MCP_LIVE_MOVEMENTS_BY_PERIOD_QUERY_TEMPLATE = `
|
||||
ВЫБРАТЬ ПЕРВЫЕ __LIMIT__
|
||||
Движения.Период КАК Период,
|
||||
ПРЕДСТАВЛЕНИЕ(Движения.Регистратор) КАК Регистратор,
|
||||
ПРЕДСТАВЛЕНИЕ(Движения.СчетДт) КАК СчетДт,
|
||||
ПРЕДСТАВЛЕНИЕ(Движения.СчетКт) КАК СчетКт,
|
||||
Движения.Сумма КАК Сумма
|
||||
ИЗ
|
||||
РегистрБухгалтерии.Хозрасчетный КАК Движения
|
||||
ГДЕ
|
||||
Движения.Период МЕЖДУ __FROM_DATETIME__ И __TO_DATETIME__
|
||||
УПОРЯДОЧИТЬ ПО
|
||||
Движения.Период УБЫВ
|
||||
`;
|
||||
|
||||
const RBP_REQUIRED_LIVE_CALLS = [
|
||||
"find_rbp_writeoff_documents_in_period",
|
||||
"find_rbp_object_movements_account_97",
|
||||
"find_month_close_entries_linked_to_rbp",
|
||||
"compute_end_period_residual_by_rbp_object"
|
||||
];
|
||||
|
||||
function pushUniqueLine(target: string[], line: string): void {
|
||||
if (!target.includes(line)) {
|
||||
target.push(line);
|
||||
|
|
@ -181,6 +228,141 @@ function parseFiniteNumber(value: unknown): number | null {
|
|||
return null;
|
||||
}
|
||||
|
||||
function formatIsoDateUtc(date: Date): string {
|
||||
const year = date.getUTCFullYear();
|
||||
const month = String(date.getUTCMonth() + 1).padStart(2, "0");
|
||||
const day = String(date.getUTCDate()).padStart(2, "0");
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
|
||||
function monthEndFromIso(isoDate: string): string | null {
|
||||
const match = String(isoDate ?? "").match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
const year = Number(match[1]);
|
||||
const month = Number(match[2]);
|
||||
if (!Number.isFinite(year) || !Number.isFinite(month)) {
|
||||
return null;
|
||||
}
|
||||
const end = new Date(Date.UTC(year, month, 0));
|
||||
return formatIsoDateUtc(end);
|
||||
}
|
||||
|
||||
function shiftIsoDate(isoDate: string, deltaDays: number): string | null {
|
||||
const match = String(isoDate ?? "").match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
const date = new Date(Date.UTC(Number(match[1]), Number(match[2]) - 1, Number(match[3])));
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return null;
|
||||
}
|
||||
date.setUTCDate(date.getUTCDate() + deltaDays);
|
||||
return formatIsoDateUtc(date);
|
||||
}
|
||||
|
||||
function toDateTimeExpr(isoDate: string, endOfDay: boolean): string | null {
|
||||
const match = String(isoDate ?? "").match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
const year = Number(match[1]);
|
||||
const month = Number(match[2]);
|
||||
const day = Number(match[3]);
|
||||
if (!Number.isFinite(year) || !Number.isFinite(month) || !Number.isFinite(day)) {
|
||||
return null;
|
||||
}
|
||||
const hour = endOfDay ? 23 : 0;
|
||||
const minute = endOfDay ? 59 : 0;
|
||||
const second = endOfDay ? 59 : 0;
|
||||
return `ДАТАВРЕМЯ(${year}, ${month}, ${day}, ${hour}, ${minute}, ${second})`;
|
||||
}
|
||||
|
||||
function buildLiveRangeQuery(fromIso: string, toIso: string, limit: number): string {
|
||||
const fromExpr = toDateTimeExpr(fromIso, false);
|
||||
const toExpr = toDateTimeExpr(toIso, true);
|
||||
if (!fromExpr || !toExpr) {
|
||||
return MCP_LIVE_MOVEMENTS_QUERY_TEMPLATE.replace("__LIMIT__", String(limit));
|
||||
}
|
||||
return MCP_LIVE_MOVEMENTS_BY_PERIOD_QUERY_TEMPLATE.replace("__LIMIT__", String(limit))
|
||||
.replace("__FROM_DATETIME__", fromExpr)
|
||||
.replace("__TO_DATETIME__", toExpr);
|
||||
}
|
||||
|
||||
function hasRbpSignal(text: string): boolean {
|
||||
return /(?:\brbp\b|рбп|расходы\s+будущих\s+периодов|deferred|writeoff|списани[ея]\s+рбп|account\s*97|счет\s*97)/i.test(
|
||||
String(text ?? "").toLowerCase()
|
||||
);
|
||||
}
|
||||
|
||||
function buildLiveMcpCallPlan(route: string, fragmentText: string): LiveMcpCallPlan {
|
||||
const semanticProfile = buildSemanticRetrievalProfile(fragmentText);
|
||||
const rbpClaim =
|
||||
hasRbpSignal(fragmentText) ||
|
||||
semanticProfile.query_subject === "deferred_expense_lifecycle_anomaly" ||
|
||||
semanticProfile.domain_scope.includes("deferred_expense");
|
||||
if (!rbpClaim) {
|
||||
return {
|
||||
claim_type: null,
|
||||
query_subject: semanticProfile.query_subject,
|
||||
required_live_calls: [],
|
||||
calls: [
|
||||
{
|
||||
call_id: "generic_accounting_register_probe",
|
||||
purpose: "live_overlay_probe",
|
||||
query: MCP_LIVE_MOVEMENTS_QUERY_TEMPLATE.replace("__LIMIT__", String(ASSISTANT_MCP_LIVE_LIMIT)),
|
||||
required_for_claim: false
|
||||
}
|
||||
],
|
||||
route_gap_reason: null
|
||||
};
|
||||
}
|
||||
|
||||
const periodScope = inferPeriodScope(fragmentText);
|
||||
const primaryFrom = periodScope.from ?? "2020-07-01";
|
||||
const primaryTo = periodScope.to ?? monthEndFromIso(primaryFrom) ?? "2020-07-31";
|
||||
const carryFrom = shiftIsoDate(primaryFrom, -31) ?? primaryFrom;
|
||||
const carryTo = shiftIsoDate(primaryTo, 31) ?? primaryTo;
|
||||
|
||||
return {
|
||||
claim_type: "prove_rbp_tail_state",
|
||||
query_subject: "deferred_expense_lifecycle_anomaly",
|
||||
required_live_calls: [...RBP_REQUIRED_LIVE_CALLS],
|
||||
calls: [
|
||||
{
|
||||
call_id: "find_rbp_writeoff_documents_in_period",
|
||||
purpose: "seed_writeoff_documents",
|
||||
query: buildLiveRangeQuery(primaryFrom, primaryTo, ASSISTANT_MCP_LIVE_LIMIT),
|
||||
required_for_claim: true,
|
||||
account_scope_override: ["97", "20", "25", "26", "44"]
|
||||
},
|
||||
{
|
||||
call_id: "find_rbp_object_movements_account_97",
|
||||
purpose: "collect_rbp_object_movements",
|
||||
query: buildLiveRangeQuery(primaryFrom, primaryTo, ASSISTANT_MCP_LIVE_LIMIT),
|
||||
required_for_claim: true,
|
||||
account_scope_override: ["97"]
|
||||
},
|
||||
{
|
||||
call_id: "find_month_close_entries_linked_to_rbp",
|
||||
purpose: "link_month_close_to_rbp",
|
||||
query: buildLiveRangeQuery(primaryFrom, primaryTo, ASSISTANT_MCP_LIVE_LIMIT),
|
||||
required_for_claim: true,
|
||||
account_scope_override: ["97", "20", "25", "26", "44"]
|
||||
},
|
||||
{
|
||||
call_id: "compute_end_period_residual_by_rbp_object",
|
||||
purpose: "collect_residual_tail_signals",
|
||||
query: buildLiveRangeQuery(carryFrom, carryTo, ASSISTANT_MCP_LIVE_LIMIT),
|
||||
required_for_claim: true,
|
||||
account_scope_override: ["97", "20", "25", "26", "44"]
|
||||
}
|
||||
],
|
||||
route_gap_reason: null
|
||||
};
|
||||
}
|
||||
|
||||
function detectBroadQuery(fragmentText: string, route: string): BroadQueryAssessment {
|
||||
const text = String(fragmentText ?? "").trim();
|
||||
const lower = text.toLowerCase();
|
||||
|
|
@ -2587,79 +2769,170 @@ export class AssistantDataLayer {
|
|||
}
|
||||
|
||||
private async fetchLiveMcpOverlay(route: string, fragmentText: string): Promise<LiveMcpOverlay> {
|
||||
const accountScope = extractAccountScopeFromText(fragmentText);
|
||||
const endpoint = this.buildMcpUrl("/api/execute_query");
|
||||
const query = MCP_LIVE_MOVEMENTS_QUERY_TEMPLATE.replace("__LIMIT__", String(ASSISTANT_MCP_LIVE_LIMIT));
|
||||
const livePlan = buildLiveMcpCallPlan(route, fragmentText);
|
||||
const explicitAccountScope = extractAccountScopeFromText(fragmentText);
|
||||
const accountScope =
|
||||
explicitAccountScope.length > 0
|
||||
? explicitAccountScope
|
||||
: livePlan.claim_type === "prove_rbp_tail_state"
|
||||
? ["97", "20", "25", "26", "44"]
|
||||
: [];
|
||||
const callExecutions: LiveMcpCallExecution[] = [];
|
||||
const collectedRows: Array<Record<string, unknown>> = [];
|
||||
const errors: string[] = [];
|
||||
let fetchedRowsTotal = 0;
|
||||
let matchedRowsTotal = 0;
|
||||
|
||||
for (const call of livePlan.calls) {
|
||||
const callAccountScope =
|
||||
Array.isArray(call.account_scope_override) && call.account_scope_override.length > 0
|
||||
? call.account_scope_override
|
||||
: accountScope;
|
||||
try {
|
||||
const payload = await this.fetchJsonWithTimeout(endpoint, {
|
||||
query,
|
||||
query: call.query,
|
||||
limit: ASSISTANT_MCP_LIVE_LIMIT
|
||||
});
|
||||
|
||||
const parsed = this.parseExecuteQueryPayload(payload);
|
||||
if (parsed.error) {
|
||||
return {
|
||||
errors.push(parsed.error);
|
||||
callExecutions.push({
|
||||
call_id: call.call_id,
|
||||
purpose: call.purpose,
|
||||
required_for_claim: call.required_for_claim,
|
||||
status: "error",
|
||||
items: [],
|
||||
evidence: [],
|
||||
summary: {
|
||||
enabled: true,
|
||||
status: "error",
|
||||
route,
|
||||
channel: ASSISTANT_MCP_CHANNEL,
|
||||
proxy: ASSISTANT_MCP_PROXY_URL,
|
||||
account_scope: accountScope,
|
||||
fetched_rows: 0,
|
||||
matched_rows: 0,
|
||||
returned_rows: 0,
|
||||
error: parsed.error
|
||||
},
|
||||
selection_reason: ["Live MCP probe завершился ошибкой, использован snapshot fallback."],
|
||||
limitations: ["Live MCP недоступен или вернул ошибку; результат ограничен локальным snapshot."],
|
||||
errors: [parsed.error]
|
||||
};
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
const matchedRows = this.filterLiveRowsByAccountScope(parsed.rows, accountScope);
|
||||
const rowsForAnswer = matchedRows.length > 0 || accountScope.length === 0 ? matchedRows : parsed.rows;
|
||||
const items = this.toLiveOverlayItems(rowsForAnswer.slice(0, 12), route);
|
||||
const evidence = items.slice(0, 8).map((item) => ({
|
||||
const matchedRows = this.filterLiveRowsByAccountScope(parsed.rows, callAccountScope);
|
||||
const rowsForAnswer = callAccountScope.length > 0 ? matchedRows : parsed.rows;
|
||||
fetchedRowsTotal += parsed.rows.length;
|
||||
matchedRowsTotal += matchedRows.length;
|
||||
for (const row of rowsForAnswer) {
|
||||
collectedRows.push({
|
||||
...row,
|
||||
__live_call_id: call.call_id,
|
||||
__live_call_purpose: call.purpose,
|
||||
__claim_type: livePlan.claim_type,
|
||||
__query_subject: livePlan.query_subject,
|
||||
__account_scope_applied: callAccountScope
|
||||
});
|
||||
}
|
||||
callExecutions.push({
|
||||
call_id: call.call_id,
|
||||
purpose: call.purpose,
|
||||
required_for_claim: call.required_for_claim,
|
||||
status: rowsForAnswer.length > 0 ? "ok" : "empty",
|
||||
fetched_rows: parsed.rows.length,
|
||||
matched_rows: matchedRows.length,
|
||||
returned_rows: rowsForAnswer.length,
|
||||
error: null
|
||||
});
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
errors.push(errorMessage);
|
||||
callExecutions.push({
|
||||
call_id: call.call_id,
|
||||
purpose: call.purpose,
|
||||
required_for_claim: call.required_for_claim,
|
||||
status: "error",
|
||||
fetched_rows: 0,
|
||||
matched_rows: 0,
|
||||
returned_rows: 0,
|
||||
error: errorMessage
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const items = this.toLiveOverlayItems(collectedRows.slice(0, 16), route);
|
||||
const evidence = items.slice(0, 12).map((item) => ({
|
||||
source_entity: item.source_entity,
|
||||
source_id: item.source_id,
|
||||
source_namespace: "assistant_derived",
|
||||
period: item.period,
|
||||
account_debit: item.account_debit,
|
||||
account_credit: item.account_credit
|
||||
account_credit: item.account_credit,
|
||||
source_layer: item.source_layer,
|
||||
document_context: item.document_context,
|
||||
relation_pattern_hits: item.relation_pattern_hits,
|
||||
lifecycle_markers: item.lifecycle_markers,
|
||||
live_call_id: item.live_call_id,
|
||||
live_call_purpose: item.live_call_purpose,
|
||||
claim_type: item.claim_type
|
||||
}));
|
||||
|
||||
const executedRequiredCalls = callExecutions
|
||||
.filter((item) => item.required_for_claim && item.status !== "error")
|
||||
.map((item) => item.call_id);
|
||||
const missingLiveCalls = livePlan.required_live_calls.filter((callId) => !executedRequiredCalls.includes(callId));
|
||||
const liveRouteExecutionRate =
|
||||
livePlan.required_live_calls.length > 0
|
||||
? Number((executedRequiredCalls.length / livePlan.required_live_calls.length).toFixed(4))
|
||||
: 1;
|
||||
const routeGapReason =
|
||||
missingLiveCalls.length > 0
|
||||
? "required_live_calls_not_executed"
|
||||
: livePlan.claim_type && matchedRowsTotal <= 0
|
||||
? "claim_live_calls_executed_but_zero_matches"
|
||||
: livePlan.route_gap_reason;
|
||||
|
||||
const selectionReason = [
|
||||
`Live MCP probe: ${parsed.rows.length} rows fetched from 1C register.`,
|
||||
livePlan.claim_type
|
||||
? `Claim-bound live path selected for ${livePlan.claim_type}.`
|
||||
: `Live MCP probe: ${fetchedRowsTotal} rows fetched from 1C register.`,
|
||||
accountScope.length > 0
|
||||
? `Account scope filter (${accountScope.join(", ")}) matched ${matchedRows.length} rows.`
|
||||
? `Account scope filter (${accountScope.join(", ")}) matched ${matchedRowsTotal} rows.`
|
||||
: "Account scope filter was not applied."
|
||||
];
|
||||
|
||||
const limitations: string[] = [
|
||||
"Live probe использует ограниченный выборочный read-only запрос к 1С."
|
||||
];
|
||||
if (missingLiveCalls.length > 0) {
|
||||
limitations.push(`Required live calls were not executed: ${missingLiveCalls.join(", ")}.`);
|
||||
}
|
||||
if (items.length === 0) {
|
||||
limitations.push("Live probe не вернул строк, релевантных текущему запросу.");
|
||||
}
|
||||
if (errors.length > 0) {
|
||||
limitations.push("Часть live вызовов завершилась ошибкой; включен ограниченный fallback.");
|
||||
}
|
||||
|
||||
const status: LiveMcpOverlay["status"] =
|
||||
items.length > 0 ? "ok" : callExecutions.every((item) => item.status === "error") ? "error" : "empty";
|
||||
|
||||
return {
|
||||
status: items.length > 0 ? "ok" : "empty",
|
||||
status,
|
||||
items,
|
||||
evidence,
|
||||
summary: {
|
||||
enabled: true,
|
||||
status: items.length > 0 ? "ok" : "empty",
|
||||
status,
|
||||
route,
|
||||
channel: ASSISTANT_MCP_CHANNEL,
|
||||
proxy: ASSISTANT_MCP_PROXY_URL,
|
||||
source_profile: livePlan.claim_type ? "claim_bound_rbp_live_path" : "generic_live_probe",
|
||||
claim_type: livePlan.claim_type,
|
||||
query_subject: livePlan.query_subject,
|
||||
account_scope: accountScope,
|
||||
fetched_rows: parsed.rows.length,
|
||||
matched_rows: matchedRows.length,
|
||||
returned_rows: items.length
|
||||
fetched_rows: fetchedRowsTotal,
|
||||
matched_rows: matchedRowsTotal,
|
||||
returned_rows: items.length,
|
||||
required_live_calls: livePlan.required_live_calls,
|
||||
executed_live_calls: callExecutions,
|
||||
missing_live_calls: missingLiveCalls,
|
||||
live_route_execution_rate: liveRouteExecutionRate,
|
||||
route_gap_reason: routeGapReason
|
||||
},
|
||||
selection_reason: selectionReason,
|
||||
limitations,
|
||||
errors: []
|
||||
errors
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -2831,6 +3104,37 @@ export class AssistantDataLayer {
|
|||
const baseId = `${route}-mcp-${index + 1}`;
|
||||
const sourceId = periodRaw ? `${baseId}-${periodRaw}` : baseId;
|
||||
const displayName = registrator || `Live movement row #${index + 1}`;
|
||||
const accountContext = uniqueStrings([debit, credit].filter((item) => item.length > 0));
|
||||
const callId = valueAsString(row.__live_call_id ?? "").trim();
|
||||
const callPurpose = valueAsString(row.__live_call_purpose ?? "").trim();
|
||||
const claimType = valueAsString(row.__claim_type ?? "").trim() || null;
|
||||
const querySubject = valueAsString(row.__query_subject ?? "").trim() || null;
|
||||
const registratorLower = registrator.toLowerCase();
|
||||
const hasRbpByDocument = /(?:рбп|deferred|списани[ея]\s+рбп)/i.test(registratorLower);
|
||||
const hasAccount97 = accountContext.some((item) => /^97(?:\.|$)/.test(item));
|
||||
const hasCloseDoc =
|
||||
/(?:закрыти[ея]\s+месяц|period\s*close|month\s*close|close\s+operation)/i.test(registratorLower) ||
|
||||
callId.includes("month_close");
|
||||
const relationPatternHits = uniqueStrings([
|
||||
"document_to_posting",
|
||||
hasRbpByDocument || hasAccount97 ? "deferred_expense_to_writeoff" : "",
|
||||
hasCloseDoc ? "close_operation" : "",
|
||||
callId.includes("residual") ? "residuals_zero_or_explained" : ""
|
||||
]);
|
||||
const documentContext = uniqueStrings([
|
||||
hasRbpByDocument || hasAccount97 ? "deferred_expense_document" : "",
|
||||
hasCloseDoc ? "period_close_document" : "",
|
||||
"posting"
|
||||
]);
|
||||
const graphDomainScope = uniqueStrings([
|
||||
hasRbpByDocument || hasAccount97 ? "deferred_expense" : "",
|
||||
hasCloseDoc ? "period_close" : ""
|
||||
]);
|
||||
const lifecycleMarkers = uniqueStrings([
|
||||
callId.includes("residual") ? "period_boundary" : "",
|
||||
callId.includes("residual") ? "tail_state_observed" : "",
|
||||
hasCloseDoc ? "close_operation" : ""
|
||||
]);
|
||||
return {
|
||||
source_entity: "MCPLiveMovement",
|
||||
source_id: sourceId,
|
||||
|
|
@ -2838,6 +3142,16 @@ export class AssistantDataLayer {
|
|||
period: periodRaw || null,
|
||||
account_debit: debit || null,
|
||||
account_credit: credit || null,
|
||||
account_context: accountContext,
|
||||
document_context: documentContext,
|
||||
relation_pattern_hits: relationPatternHits,
|
||||
graph_domain_scope: graphDomainScope,
|
||||
lifecycle_markers: lifecycleMarkers,
|
||||
source_namespace: "assistant_derived",
|
||||
live_call_id: callId || null,
|
||||
live_call_purpose: callPurpose || null,
|
||||
claim_type: claimType,
|
||||
query_subject: querySubject,
|
||||
amount,
|
||||
source_layer: "mcp_live_probe",
|
||||
route
|
||||
|
|
|
|||
|
|
@ -582,6 +582,159 @@ function toExecutionPlan(routeSummary, normalized, userMessage, requirementByFra
|
|||
};
|
||||
});
|
||||
}
|
||||
function enrichRbpFragmentForLive(fragmentText, temporalGuard) {
|
||||
const base = compactWhitespace(String(fragmentText ?? ""));
|
||||
const hints = ["Списание РБП", "объект РБП", "остаток на конец периода", "счет 97"];
|
||||
const effective = temporalGuard && typeof temporalGuard === "object" ? temporalGuard.effective_primary_period : null;
|
||||
if (effective && effective.from && effective.to) {
|
||||
hints.push(`период ${effective.from}..${effective.to}`);
|
||||
}
|
||||
const hintText = hints.filter(Boolean).join(", ");
|
||||
if (!base) {
|
||||
return hintText;
|
||||
}
|
||||
if (/списани[ея]\s+рбп|счет\s*97|account\s*97|остат/i.test(base)) {
|
||||
return base;
|
||||
}
|
||||
return `${base}; ${hintText}`;
|
||||
}
|
||||
function enforceRbpLiveRoutePlan(input) {
|
||||
if (input.claimType !== "prove_rbp_tail_state") {
|
||||
return {
|
||||
executionPlan: input.executionPlan,
|
||||
audit: null
|
||||
};
|
||||
}
|
||||
const requiredLiveCalls = [
|
||||
"find_rbp_writeoff_documents_in_period",
|
||||
"find_rbp_object_movements_account_97",
|
||||
"find_month_close_entries_linked_to_rbp",
|
||||
"compute_end_period_residual_by_rbp_object"
|
||||
];
|
||||
let routeAdjusted = 0;
|
||||
let rescuedNoRoute = 0;
|
||||
const replacedRoutes = [];
|
||||
const adjustedPlan = input.executionPlan.map((item) => {
|
||||
if (!item || typeof item !== "object") {
|
||||
return item;
|
||||
}
|
||||
if (item.should_execute !== true && item.no_route_reason === "insufficient_specificity") {
|
||||
rescuedNoRoute += 1;
|
||||
routeAdjusted += 1;
|
||||
return {
|
||||
...item,
|
||||
route: "live_mcp_drilldown",
|
||||
should_execute: true,
|
||||
no_route_reason: null,
|
||||
clarification_reason: null,
|
||||
fragment_text: enrichRbpFragmentForLive(item.fragment_text, input.temporalGuard)
|
||||
};
|
||||
}
|
||||
if (item.should_execute === true && item.route !== "hybrid_store_plus_live" && item.route !== "live_mcp_drilldown") {
|
||||
routeAdjusted += 1;
|
||||
if (item.route && item.route !== "no_route") {
|
||||
replacedRoutes.push(String(item.route));
|
||||
}
|
||||
return {
|
||||
...item,
|
||||
route: "hybrid_store_plus_live",
|
||||
fragment_text: enrichRbpFragmentForLive(item.fragment_text, input.temporalGuard)
|
||||
};
|
||||
}
|
||||
if (item.should_execute === true) {
|
||||
return {
|
||||
...item,
|
||||
fragment_text: enrichRbpFragmentForLive(item.fragment_text, input.temporalGuard)
|
||||
};
|
||||
}
|
||||
return item;
|
||||
});
|
||||
return {
|
||||
executionPlan: adjustedPlan,
|
||||
audit: {
|
||||
claim_type: "prove_rbp_tail_state",
|
||||
required_live_calls: requiredLiveCalls,
|
||||
route_adjustments_applied: routeAdjusted,
|
||||
rescued_no_route_fragments: rescuedNoRoute,
|
||||
replaced_routes: Array.from(new Set(replacedRoutes)),
|
||||
route_gap_reason: routeAdjusted > 0 ? "rbp_claim_bound_live_route_override_applied" : null
|
||||
}
|
||||
};
|
||||
}
|
||||
function collectRbpLiveRouteAudit(input) {
|
||||
if (input.claimType !== "prove_rbp_tail_state") {
|
||||
return null;
|
||||
}
|
||||
const required = new Set(Array.isArray(input.planAudit?.required_live_calls) ? input.planAudit.required_live_calls : []);
|
||||
const executed = [];
|
||||
const missing = new Set();
|
||||
const routeGaps = [];
|
||||
let matchedRowsTotal = 0;
|
||||
let returnedRowsTotal = 0;
|
||||
let fetchedRowsTotal = 0;
|
||||
for (const result of input.retrievalResults) {
|
||||
if (!result || typeof result !== "object") {
|
||||
continue;
|
||||
}
|
||||
const summary = result.summary && typeof result.summary === "object" ? result.summary : null;
|
||||
const live = summary && typeof summary.live_mcp === "object" && summary.live_mcp ? summary.live_mcp : null;
|
||||
if (!live) {
|
||||
continue;
|
||||
}
|
||||
const requiredCalls = Array.isArray(live.required_live_calls) ? live.required_live_calls : [];
|
||||
for (const callId of requiredCalls) {
|
||||
required.add(String(callId ?? "").trim());
|
||||
}
|
||||
const executedCalls = Array.isArray(live.executed_live_calls) ? live.executed_live_calls : [];
|
||||
for (const call of executedCalls) {
|
||||
if (!call || typeof call !== "object") {
|
||||
continue;
|
||||
}
|
||||
executed.push(call);
|
||||
}
|
||||
const missingCalls = Array.isArray(live.missing_live_calls) ? live.missing_live_calls : [];
|
||||
for (const callId of missingCalls) {
|
||||
const token = String(callId ?? "").trim();
|
||||
if (token) {
|
||||
missing.add(token);
|
||||
}
|
||||
}
|
||||
const routeGapReason = String(live.route_gap_reason ?? "").trim();
|
||||
if (routeGapReason) {
|
||||
routeGaps.push(routeGapReason);
|
||||
}
|
||||
fetchedRowsTotal += Number(live.fetched_rows ?? 0) || 0;
|
||||
matchedRowsTotal += Number(live.matched_rows ?? 0) || 0;
|
||||
returnedRowsTotal += Number(live.returned_rows ?? 0) || 0;
|
||||
}
|
||||
const requiredList = Array.from(required).filter(Boolean);
|
||||
const executedList = executed;
|
||||
const missingFromExecuted = requiredList.filter((callId) => !executedList.some((item) => String(item.call_id ?? "") === callId));
|
||||
for (const callId of missingFromExecuted) {
|
||||
missing.add(callId);
|
||||
}
|
||||
const missingList = Array.from(missing);
|
||||
const routeGapReason = missingList.length > 0
|
||||
? "required_live_calls_not_executed"
|
||||
: matchedRowsTotal <= 0
|
||||
? "claim_live_calls_executed_but_zero_matches"
|
||||
: routeGaps[0] ?? null;
|
||||
const executionRate = requiredList.length > 0
|
||||
? Number(((requiredList.length - missingList.length) / requiredList.length).toFixed(4))
|
||||
: 1;
|
||||
return {
|
||||
claim_type: "prove_rbp_tail_state",
|
||||
required_live_calls: requiredList,
|
||||
executed_live_calls: executedList,
|
||||
missing_live_calls: missingList,
|
||||
route_gap_reason: routeGapReason,
|
||||
live_route_execution_rate: executionRate,
|
||||
fetched_rows_total: fetchedRowsTotal,
|
||||
matched_rows_total: matchedRowsTotal,
|
||||
returned_rows_total: returnedRowsTotal,
|
||||
plan_override: input.planAudit ?? null
|
||||
};
|
||||
}
|
||||
function toDebugRoutes(routeSummary) {
|
||||
if (!routeSummary) {
|
||||
return [];
|
||||
|
|
@ -1433,6 +1586,12 @@ export class AssistantService {
|
|||
const resolvedRouteSummary = businessScopeResolution.route_summary_resolved;
|
||||
const requirementExtraction = extractRequirements(resolvedRouteSummary, normalized.normalized, userMessage);
|
||||
let executionPlan = toExecutionPlan(resolvedRouteSummary, normalized.normalized, userMessage, requirementExtraction.byFragment);
|
||||
const rbpRoutePlanEnforcement = enforceRbpLiveRoutePlan({
|
||||
executionPlan,
|
||||
claimType: claimAnchorAudit.claim_type,
|
||||
temporalGuard
|
||||
});
|
||||
executionPlan = rbpRoutePlanEnforcement.executionPlan;
|
||||
executionPlan = (0, assistantRuntimeGuards_1.applyTemporalHintToExecutionPlan)(executionPlan, temporalGuard);
|
||||
executionPlan = (0, assistantRuntimeGuards_1.applyPolarityHintToExecutionPlan)(executionPlan, domainPolarityGuardInitial);
|
||||
const retrievalCalls = [];
|
||||
|
|
@ -1515,6 +1674,11 @@ export class AssistantService {
|
|||
userMessage
|
||||
});
|
||||
retrievalResults = evidenceGateResult.retrievalResults;
|
||||
const rbpLiveRouteAudit = collectRbpLiveRouteAudit({
|
||||
claimType: claimAnchorAudit.claim_type,
|
||||
retrievalResults,
|
||||
planAudit: rbpRoutePlanEnforcement.audit
|
||||
});
|
||||
const coverageEvaluation = evaluateCoverage(requirementExtraction.requirements, retrievalResults);
|
||||
const groundingCheckBase = checkGrounding(userMessage, coverageEvaluation.requirements, coverageEvaluation.coverage, retrievalResults);
|
||||
const groundedAnswerEligibilityGuard = (0, assistantRuntimeGuards_1.evaluateGroundedAnswerEligibility)({
|
||||
|
|
@ -1627,6 +1791,7 @@ export class AssistantService {
|
|||
claim_anchor_audit: claimAnchorAudit,
|
||||
targeted_evidence_acquisition: targetedEvidenceResult.audit,
|
||||
evidence_admissibility_gate: evidenceGateResult.audit,
|
||||
...(rbpLiveRouteAudit ? { rbp_live_route_audit: rbpLiveRouteAudit } : {}),
|
||||
eligibility_time_basis: groundedAnswerEligibilityGuard.eligibility_time_basis,
|
||||
grounded_answer_eligibility_guard: groundedAnswerEligibilityGuard,
|
||||
...(followupBinding.usage ? { followup_state_usage: followupBinding.usage } : {}),
|
||||
|
|
|
|||
|
|
@ -207,6 +207,19 @@ export interface GroundedAnswerEligibilityGuardDebug {
|
|||
reason_codes: string[];
|
||||
}
|
||||
|
||||
export interface RbpLiveRouteAuditDebug {
|
||||
claim_type: "prove_rbp_tail_state";
|
||||
required_live_calls: string[];
|
||||
executed_live_calls: Array<Record<string, unknown>>;
|
||||
missing_live_calls: string[];
|
||||
route_gap_reason: string | null;
|
||||
live_route_execution_rate: number;
|
||||
fetched_rows_total: number;
|
||||
matched_rows_total: number;
|
||||
returned_rows_total: number;
|
||||
plan_override: Record<string, unknown> | null;
|
||||
}
|
||||
|
||||
export interface AssistantMessageRequestPayload {
|
||||
session_id?: string;
|
||||
user_message?: string;
|
||||
|
|
@ -302,6 +315,7 @@ export interface AssistantDebugPayload {
|
|||
claim_anchor_audit?: ClaimBoundAnchorAuditDebug;
|
||||
targeted_evidence_acquisition?: TargetedEvidenceAcquisitionDebug;
|
||||
evidence_admissibility_gate?: EvidenceAdmissibilityGateDebug;
|
||||
rbp_live_route_audit?: RbpLiveRouteAuditDebug;
|
||||
eligibility_time_basis?: GroundedAnswerEligibilityGuardDebug["eligibility_time_basis"];
|
||||
grounded_answer_eligibility_guard?: GroundedAnswerEligibilityGuardDebug;
|
||||
followup_state_usage?: FollowupStateUsageDebug;
|
||||
|
|
|
|||
|
|
@ -122,6 +122,86 @@ describe.sequential("assistant MCP runtime bridge", () => {
|
|||
const summary = result.summary as Record<string, unknown>;
|
||||
const liveSummary = summary.live_mcp as Record<string, unknown>;
|
||||
expect(liveSummary.status).toBe("error");
|
||||
expect(result.limitations.some((item) => item.includes("Live MCP"))).toBe(true);
|
||||
expect(result.limitations.some((item) => /live/i.test(item))).toBe(true);
|
||||
});
|
||||
|
||||
it("does not inject out-of-scope rows when account filter matched zero", async () => {
|
||||
process.env[MCP_FLAG] = "1";
|
||||
process.env[MCP_PROXY] = "http://127.0.0.1:6003";
|
||||
process.env[MCP_CHANNEL] = "default";
|
||||
|
||||
const payload = JSON.stringify({
|
||||
success: true,
|
||||
data: [
|
||||
{
|
||||
Период: "2026-03-01T00:00:00",
|
||||
Регистратор: "Операция бухгалтерская 0002",
|
||||
СчетДт: "91.02",
|
||||
СчетКт: "51",
|
||||
Сумма: 900
|
||||
}
|
||||
]
|
||||
});
|
||||
const fetchMock = vi.fn(async () => new Response(payload, { status: 200 }));
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
|
||||
const { AssistantDataLayer } = await import("../src/services/assistantDataLayer");
|
||||
const dataLayer = new AssistantDataLayer(createSnapshotRoot());
|
||||
const result = await dataLayer.executeRouteRuntime("hybrid_store_plus_live", "Check account 60 only");
|
||||
|
||||
const summary = result.summary as Record<string, unknown>;
|
||||
const liveSummary = summary.live_mcp as Record<string, unknown>;
|
||||
expect(fetchMock).toHaveBeenCalledTimes(1);
|
||||
expect(Array.isArray(liveSummary.account_scope)).toBe(true);
|
||||
expect((liveSummary.account_scope as string[]).some((item) => String(item).includes("60"))).toBe(true);
|
||||
expect(liveSummary.matched_rows).toBe(0);
|
||||
expect(liveSummary.returned_rows).toBe(0);
|
||||
expect(result.items).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("uses claim-bound live call sequence for RBP lifecycle query", async () => {
|
||||
process.env[MCP_FLAG] = "1";
|
||||
process.env[MCP_PROXY] = "http://127.0.0.1:6003";
|
||||
process.env[MCP_CHANNEL] = "default";
|
||||
|
||||
const payload = JSON.stringify({
|
||||
success: true,
|
||||
data: [
|
||||
{
|
||||
Период: "2020-07-31T00:00:00",
|
||||
Регистратор: "Списание РБП за Июль 2020",
|
||||
СчетДт: "20.01",
|
||||
СчетКт: "97.01",
|
||||
Сумма: 5000
|
||||
},
|
||||
{
|
||||
Период: "2020-07-31T00:00:00",
|
||||
Регистратор: "Закрытие месяца Июль 2020",
|
||||
СчетДт: "97.01",
|
||||
СчетКт: "20.01",
|
||||
Сумма: 5000
|
||||
}
|
||||
]
|
||||
});
|
||||
const fetchMock = vi.fn(async () => new Response(payload, { status: 200 }));
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
|
||||
const { AssistantDataLayer } = await import("../src/services/assistantDataLayer");
|
||||
const dataLayer = new AssistantDataLayer(createSnapshotRoot());
|
||||
const result = await dataLayer.executeRouteRuntime(
|
||||
"hybrid_store_plus_live",
|
||||
"31 июля прошло Списание РБП за июль 2020 на 5000. Есть ли хвост РБП?"
|
||||
);
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledTimes(4);
|
||||
const summary = result.summary as Record<string, unknown>;
|
||||
const liveSummary = summary.live_mcp as Record<string, unknown>;
|
||||
expect(liveSummary.claim_type).toBe("prove_rbp_tail_state");
|
||||
expect(Array.isArray(liveSummary.required_live_calls)).toBe(true);
|
||||
expect((liveSummary.required_live_calls as unknown[]).length).toBe(4);
|
||||
expect(Array.isArray(liveSummary.executed_live_calls)).toBe(true);
|
||||
expect((liveSummary.executed_live_calls as unknown[]).length).toBe(4);
|
||||
expect(liveSummary.matched_rows).toBeGreaterThan(0);
|
||||
expect(result.items.some((item) => Array.isArray((item as Record<string, unknown>).relation_pattern_hits))).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue