Добавить сухой прогон текста по конвейеру
POST /api/admin/check-message прогоняет текст через стоп-правила, глобальные исключения, ML и ИИ без создания карточки (PipelineWorkerService.DryRunAsync), отдаёт этапы, разбор и целевой контейнер. UI тестера в настройках переведён на новый контракт. Зафиксированы решения по вложениям (медиа-посты пропускаем).
This commit is contained in:
+6
-3
@@ -23,7 +23,7 @@
|
||||
| Статические сегменты против `{id}` | Литералы объявляются до `{id}`: `/cards/counts`, `/cards/clear-col`, `/cards/clear-rejected`, `/cards/reclassify`, `/cards/mark-all-seen`, `/cards/mark-col-seen`, `/cards/take` — до `/cards/{cardId}`; `/containers/state`, `/containers/reorder` — до `/containers/{containerId}`; `/rejected/clear` — до `/rejected/{rejId}`. ASP.NET Core отдаёт приоритет литералам, порядок сохранён для читаемости |
|
||||
| Prefix'ы id | `c_` — карточка (единый для всех дашбордов), `b_` — контейнер-колонка, `p_` — строка очереди, `r_` — запись отсева, `cm_` — комментарий, `h_` — запись истории, `pf_` — файл, `pl_*` — ссылка, `dt_` — discovery-задача, `dl_` — запись лога, `m_<dialog>_<msg>` — сообщение. Контейнеры-стадии/служебные зоны — без префикса (`planned`…`rejected`, `inbox`/`archive`/`trash`) |
|
||||
| Служебные админ | `admin/tick`, `admin/fts/rebuild`, `admin/check-message` — служебные, фронтом не вызываются |
|
||||
| Проверка фильтра/тестера | `POST /api/admin/check-message` — имитация этапов пайплайна |
|
||||
| Проверка фильтра/тестера | `POST /api/admin/check-message` — сухой прогон текста по всему конвейеру (стоп-правила → ML → ИИ) без создания карточки |
|
||||
| Фоновые циклы (не API) | storage-тик (30 с): автоархив/очистка + напоминания; pipeline-воркер (2 с); discovery-воркер (5 с); ML outbox (10 с); suggest (180 с); tg sweep (30 с); rates (30 мин) |
|
||||
|
||||
---
|
||||
@@ -103,7 +103,7 @@
|
||||
|---|---|---|
|
||||
| `POST /admin/tick` | Ручной тик: хранение+напоминания+разбор очереди (фронт зовёт раз в 60 с) | `{storage: {archived, purgedArchive, purgedTrash, purgedRejected}, reminders: [{id, title, containerId}] (уже «выстрелившие», после SSE), pipeline: <dict pump_once>, queue: int}` |
|
||||
| `POST /admin/fts/rebuild` | Пересобрать FTS-индекс | `{ok: bool, ready: bool}` |
|
||||
| `POST /admin/check-message` | Тестер фильтра (этап 1 + этап 2) | см. §4.10 |
|
||||
| `POST /admin/check-message` | Сухой прогон текста по конвейеру (стоп-правила → ML → ИИ) | см. §4.10 |
|
||||
| `POST /admin/wipe` | Полный сброс (карточки+ML+счётчики) | `{ok, cardsRemoved, ml: {ok}}` *(прототип)* |
|
||||
| `POST /admin/clear-cards` | Очистить карточки/очереди без сброса ML | `{ok, cardsRemoved}` *(прототип)* |
|
||||
| `POST /admin/pump-gate` | Шлагбаум воркера `{limit?}` | `{ok, limit, done}` *(прототип)* |
|
||||
@@ -375,7 +375,10 @@ links/files/history/tzText/reminder` — модули; `isNew/prevCol/isVacancy/
|
||||
### 4.10 Прочее
|
||||
|
||||
- **`GET /api/ml/status`**: `{enabled: bool, service: {ready, classes: {label: n}, learned: int, eval: {count, correct, accuracy}}, reachable: bool, stats: {ml, ai, learning, ready, classes, learned, reachable, outbox}}`. Фронт читает: `reachable`, `service.ready/classes/learned/eval.{count,correct,accuracy}`, `stats.outbox`.
|
||||
- **`POST /api/admin/check-message`**: `{stage1: {pass: bool, reason: string|null}, stage2: {pass: bool, reason: string|null, skipped: bool}, passed: bool}` — при ошибке ИИ `stage2={pass:true,reason:null,skipped:true}`.
|
||||
- **`POST /api/admin/check-message`** (сухой прогон конвейера): `{text}` →
|
||||
`{passed, wouldCreateCard, targetContainer, matchHits, parsed, stages:[{stage, pass, skipped, reason, kw, label}]}`.
|
||||
Коды `stage`: `length|stop|resume|type|exclude|ml|ai|spam_ai|budget`; `skipped=true` — этап выключен
|
||||
настройкой. `parsed` — разбор текста (поля карточки) либо null. Запись в систему не производится.
|
||||
- **`POST /api/ai/check`**: `{ok: bool, message: string, local?, keySet?}`.
|
||||
- Комментарии карточки: `{id, by: string, text, time: string}` — `by` всегда «Вы», `time` «только что».
|
||||
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
> больше не знают о Telegram; Telegram-специфика — только в тонком адаптере приёма. Tenant-миграции
|
||||
> пересозданы с нуля (init). Добавлены extension-point `ISourceContentProvider`/`SourceContentResolver` и
|
||||
> `GET /api/cards/{id}/source`. Входящий поток источников — generic (`sources.proto`/`PushSource`,
|
||||
> `SourceIngressGrpcService`), `PushMessage` из telegram.proto удалён. Ядро: build 5 sln 0/0,
|
||||
> `Deal.Tests.Unit` **1289/1289 PASS**, telegram **125/125**, фронт `build` + `lint:i18n` зелёные.
|
||||
> `SourceIngressGrpcService`), `PushMessage` из telegram.proto удалён. Сухой прогон текста по конвейеру
|
||||
> (стоп-правила → ML → ИИ) без записи: `POST /api/admin/check-message` + UI настроек. Ядро: build 5 sln 0/0,
|
||||
> `Deal.Tests.Unit` **1298/1298 PASS**, telegram **125/125**, фронт `build` + `lint:i18n` зелёные.
|
||||
> Детали — `docs/superpowers/specs/2026-09-11-source-contract-design.md`.
|
||||
> Осталось (в backlog): `GET /api/cards/{id}/source` + `ISourceContentProvider`, выгрузка вложений
|
||||
> telegram-адаптером в Storage, `TelegramSourceContentProvider`, перенос оставшейся Telegram-специфики
|
||||
|
||||
@@ -1,6 +1,29 @@
|
||||
# Открытые вопросы: вложения источников (media → Storage) и просмотр исходника
|
||||
|
||||
Дата: 2026-09-11. Статус: часть требует живого внешнего контура (Telegram API) для проверки.
|
||||
Дата: 2026-09-11. Статус: решения владельца получены (см. §0).
|
||||
|
||||
## 0. Решения владельца (2026-09-11)
|
||||
|
||||
- **А) Медиа-посты пропускаем.** Сообщения без текста (только медиа/вложение) в систему не попадают.
|
||||
Извлечение вложений Telegram и выгрузка их в Storage не делаются. Generic-контракт по-прежнему умеет
|
||||
нести `DataRef` — этим смогут пользоваться другие источники (файл/диск/таблица) и ручные вложения карточки.
|
||||
- **Б) Проверка без живого Telegram** — реализуем с юнит-тестами на фейковой сессии/фейковом Storage,
|
||||
без реального API.
|
||||
- **В)** Объяснение термина — в §1.5.
|
||||
|
||||
## 1.5. Что такое «remote-просмотр исходника»
|
||||
|
||||
Карточка хранит **ссылку на источник** (`SourceRef`) и **содержимое** (`SourceContent`). Содержимое попадает
|
||||
в карточку в момент приёма. «Просмотр исходника» — это возможность по кнопке догрузить/показать **оригинальное
|
||||
сообщение у источника** (то, что было в канале/письме/строке), если контент в карточке устарел или урезан.
|
||||
|
||||
Сейчас содержимое уже отдаётся в `CardDto.content` и через `GET /api/cards/{id}/source`. Для локальных
|
||||
источников этого достаточно. Для **внешних** источников (например Telegram) данные лежат не в ядре, а в
|
||||
сервисе-владельце; чтобы их догрузить, ядру нужен провайдер `ISourceContentProvider` для `kind`, который
|
||||
ходит по gRPC к сервису-владельцу (условный RPC `ReadSource(dialogId, msgId)`) и возвращает исходный текст/медиа.
|
||||
|
||||
Это и есть «remote-просмотр» — расширение extension-point, которое не требуется до появления реальной
|
||||
необходимости (напр. если карточки хранят урезанный текст или нужно открыть живой первоисточник).
|
||||
|
||||
## 1. Что уже готово (не требует решений)
|
||||
|
||||
|
||||
@@ -756,6 +756,11 @@ health — `GET /api/health` → `{"ok":true,"service":"deal"}`.
|
||||
reason, skipped}, passed}`; этап-1 правила из настроек (длина/стоп-фразы/резюме/тип); ИИ-фильтр
|
||||
тестера на этапе 2 всегда `skipped:true`.
|
||||
|
||||
> **Актуально с 2026-09-11:** тестер стал сухим прогоном по всему конвейеру
|
||||
> (`PipelineWorkerService.DryRunAsync`): `{passed, wouldCreateCard, targetContainer, matchHits, parsed,
|
||||
> stages[]}` — стоп-правила → глобальные исключения → ML (спам/тип) → ИИ-фильтр/классификация → «без
|
||||
> суммы»; без записи в систему. UI — вкладка настроек «Стоп-слова».
|
||||
|
||||
### 4c. Эндпоинты этапа 3 (канбан/дашборд; сессия `deal_session` обязательна, иначе 401)
|
||||
|
||||
> На этапе 4 `POST /api/admin/tick` стал реальным (pipeline/pump/purge-отсева) и
|
||||
|
||||
Reference in New Issue
Block a user