paste.txt

ChatGPT neutral 10 чанков ~14 мин чтения
PSSR MVP<br> <br> Итоговое описание и базовые ТЗ<br> <br> Часть 1. Архитектура, границы ответственности, репозитории<br> <br> 1. Назначение системы<br> <br> PSSR MVP это локальная прототипная система, которая принимает события из разнородных источников, детерминированно определяет режим и контур, применяет гейты L0 и L-Law как допуск, фиксирует аудитный след и возвращает результат в форме карточки решения. Система допускает использование ИИ в модулях, где это не критично для допуска, но ускоряет работу оператора, повышает качество разметки и помогает готовить тексты. На текущей фазе система работает на одном локальном компьютере, без требований к промышленной информационной безопасности и сертификации, но с сохранением архитектурной дисциплины, чтобы дальнейшее усиление безопасности не ломало модель.<br> <br> Ключевое требование MVP это воспроизводимость. При одинаковом входном событии и одинаковой версии реестра правил результат определения режима, гейтов и допустимых действий должен быть одинаковым. Это не означает “идеальную истинность”, но означает, что система не будет непредсказуемой.<br> <br> 2. Базовые принципы<br> <br> Принцип единственного исполнителя означает, что только Kernel формирует решения и допускает или блокирует дальнейшие действия. Ни UI, ни коннекторы, ни AI Assist не могут обходить Kernel и не могут производить “выходной текст” напрямую. Это защищает систему от деградации в “набор скриптов” и обеспечивает аудит.<br> <br> Принцип разделения данных означает, что сырьё и артефакты обработки не смешиваются. Сырьё это то, что пришло извне, с минимальными преобразованиями. Артефакты это то, что система вывела и зафиксировала как собственное действие, включая режим, контур, нарушения, протокол и черновики. Разделение нужно для дедупликации, расследований и доказуемости.<br> <br> Принцип “ИИ как ускоритель, не как допуск” означает, что ИИ может резюмировать, извлекать сущности, группировать события, переводить и готовить черновики. Но ИИ не имеет права определять режим, снимать ограничения L0 или L-Law и подтверждать факты как “verified” автоматически. Любой AI-draft, который потенциально может стать внешней формулировкой, обязан пройти повторную проверку через гейты Kernel.<br> <br> Принцип контрактов означает, что все компоненты системы общаются через зафиксированные схемы и OpenAPI, находящиеся в отдельном репозитории contracts. Контракты являются источником истины, а не “договорённостью на словах”.<br> <br> 3. Компонентная архитектура<br> <br> Система состоит из пяти независимых компонент.<br> <br> Kernel. Единственный исполнитель решения. Принимает события, записывает сырьё, связывает события, определяет режим и контур по реестру, применяет гейты, формирует решение, пишет журнал, отдаёт карточку решения и агрегаты для UI.<br> <br> AI Assist. Отдельный сервис помощника. Выполняет суммаризацию, извлечение сущностей, перевод, кластеризацию и генерацию черновиков. Работает только как advisory. Результаты сохраняются в Kernel через специальный API, чтобы у системы было одно хранилище истины.<br> <br> Ingest. Набор коннекторов источников. Каждый коннектор преобразует данные конкретного источника к единой Event Schema и отправляет в Kernel. Ingest хранит только checkpoint и технические состояния, но не хранит решения.<br> <br> UI. Отдельный фронтенд. Реализует три представления: Mobile Console, Desktop Operator, Sitcenter Wall. Работает только через Kernel API. Не содержит логики допуска.<br> <br> Stack Orchestrator. Отдельный репозиторий для сборки локального запуска, docker-compose, конфигурации окружения и тестовых сценариев.<br> <br> 4. Организация репозиториев и выпусков<br> <br> Мы фиксируем multi-repo как базовую организацию.<br> <br> Репозиторий pssr-contracts. Здесь лежат JSON Schema объектов и OpenAPI спецификация Kernel. Здесь же определены enum режимов, контуров, статусов и типы событий. В репозитории есть фиксированные примеры событий и решений для тестов, и генерация артефактов для Python и Node. Контракты имеют версионирование. Любое изменение контрактов идёт через повышение версии и проверку совместимости.<br> <br> Репозиторий pssr-kernel. Здесь только Kernel, его доменная логика, миграции SQLite, тесты воспроизводимости, и реализация OpenAPI. Kernel не содержит ни UI, ни конкретных парсеров YouScan, ни “бизнес-логики источников”. Kernel имеет один файловый каталог артефактов и одну БД. Это специально, чтобы не появилось “двух правд”.<br> <br> Репозиторий pssr-assist. Здесь AI Assist как отдельный HTTP сервис. Он читает данные через Kernel API, генерирует артефакты и возвращает их в Kernel через API сохранения. Assist может использовать Ollama локально. Он не имеет прямого доступа к БД Kernel.<br> <br> Репозитории pssr-ingest-youscan, pssr-ingest-rss, pssr-ingest-import. Каждый коннектор отдельно, чтобы не связывать циклы релизов. Все коннекторы используют общий Python пакет из contracts и отправляют события только в Kernel. В каждом коннекторе есть строгая логика checkpoint: checkpoint обновляется только при успешной обработке событий Kernel.<br> <br> Репозиторий pssr-ui. Отдельный фронтенд на стандартном стеке и Bootstrap 5. Фронт получает типы из contracts. Реализует три view-режима как отдельные маршруты и отдельные layout’ы. Обновление очереди и ситцентра делается через SSE или polling fallback.<br> <br> Репозиторий pssr-stack. В этом репозитории нет доменной логики. Здесь docker-compose, переменные окружения, локальные volume, и документация “как поднять всё локально”. Здесь же могут лежать таблицы тестовых сценариев tabletop, чтобы прогонять ядро на входных наборах.<br> <br> 5. Принципиальные границы ответственности между компонентами<br> <br> Kernel обязан обеспечить, чтобы любое решение существовало только как запись в его журнале. Если запись не сделана, решение не возвращается. Это фундаментальная гарантия. Kernel обязан фиксировать версию реестра в каждом решении.<br> <br> UI обязан отображать режим и контур как доминирующий сигнал, а hard_stop как явное ограничение. UI не может “скрывать” блокировки и не может предлагать действия, которых Kernel не разрешил через next_actions.<br> <br> Ingest обязан быть идемпотентным на уровне источника. Повторный запуск коннектора не должен создавать дублей. Для этого коннектор хранит checkpoint, а Kernel хранит fingerprint и индексы.<br> <br> AI Assist обязан маркировать все результаты как advisory и не должен производить “готовый текст” без повторного gate-check. Любой draft должен быть возвращён в Kernel и проверен, прежде чем UI получит его как “approved draft”.<br> <br> Contracts обязаны оставаться назад-совместимыми как минимум в пределах minor версии. Kernel обязан оставаться назад-совместимым по API хотя бы на период активной разработки MVP, иначе вы будете постоянно чинить UI и ingest вместо развития логики.<br> <br> 6. Выбор UI стека и роль Bootstrap<br> <br> Вы просили заранее заложить стандартные и обкатанные решения. В этой архитектуре Bootstrap 5 фиксируется как базовая дизайн-система. Это означает, что UI проектируется вокруг стандартных компонентов Bootstrap, а кастомные элементы допускаются только в части визуальной индикации режима и hard_stop. Это дисциплинирует интерфейс, ускоряет разработку и снижает риск “UI ради UI”.<br> <br> Так как UI отдельный, опыт показывает, что в дальнейшем sitcenter-экран почти всегда начинает жить по своим законам. Поэтому Sitcenter Wall фиксируется как отдельный маршрут и отдельный layout, а не как “responsive-верстка на тех же компонентах”. Адаптивность используется как техническая мера, но логика отображения различается.<br> <br> 7. Сводка ключевых требований MVP на уровне архитектуры<br> <br> Система должна работать локально, но уже в “правильной” компонентной архитектуре. Kernel должен быть единственным исполнителем решений, а гейты должны быть обязательными. Сырьё и решения разделены. Контракты вынесены отдельно. UI поддерживает телефон, desktop и ситцентр не через попытку “одним экраном”, а через три режима отображения. ИИ ускоряет работу, но не принимает решений и не снимает ограничения.<br> <br> Часть 2. Контракты, API, данные, Router/Gates, next_actions<br> <br> 8. Контракты и версии<br> <br> Репозиторий pssr-contracts является источником истины для объектов и интерфейсов. В MVP контракты включают как минимум:<br> <br> JSON Schema: Event, Decision, AIArtifact, RegistryRule, RegistryTrigger, RegistryProtocol<br> <br> OpenAPI: Kernel API и Assist API<br> <br> Enum: source_type, mode_code, contour_code, severity, decision_status, artifact_type<br> <br> Набор фикстур: примеры входных событий и ожидаемых решений для тестов<br> <br> Версионирование контрактов. Вводится semver. Изменения, которые ломают обратную совместимость, идут только через major. Kernel и UI обязаны проверять совместимость на CI: если контракт обновился, сборка должна упасть, если сервис не соответствует схеме.<br> <br> 9. Канонические перечисления<br> <br> 9.1. SourceType<br> <br> social_listening<br> <br> news<br> <br> internal<br> <br> manual<br> <br> 9.2. ModeCode<br> <br> N0<br> <br> N1<br> <br> N2<br> <br> N3<br> <br> N4<br> <br> 9.3. ContourCode<br> <br> A<br> <br> S<br> <br> C<br> <br> D<br> <br> 9.4. Severity<br> <br> CRITICAL<br> <br> HIGH<br> <br> MEDIUM<br> <br> LOW<br> <br> 9.5. DecisionStatus<br> <br> APPROVED<br> <br> BLOCKED<br> <br> 9.6. ArtifactType<br> <br> summary<br> <br> entities<br> <br> translation<br> <br> cluster<br> <br> draft<br> <br> sitcenter_brief<br> <br> test_case<br> <br> 10. Контракт Event<br> <br> Event является входным объектом для Kernel. Минимальный объект, который обязан быть принят системой, это source_type, source_name, text. Остальные поля либо заполняются ingest-коннектором, либо проставляются Kernel.<br> <br> Схема Event фиксируется так, чтобы она была стабильной для всех источников.<br> <br> {<br> <br> "type": "object",<br> <br> "required": ["source_type", "source_name", "text"],<br> <br> "properties": {<br> <br> "event_id": { "type": ["string", "null"] },<br> <br> "source_type": { "type": "string", "enum": ["social_listening","news","internal","manual"] },<br> <br> "source_name": { "type": "string" },<br> <br> "source_item_id": { "type": ["string","null"] },<br> <br> "observed_at": { "type": ["string","null"] },<br> <br> "received_at": { "type": ["string","null"] },<br> <br> "url": { "type": ["string","null"] },<br> <br> "language": { "type": "string", "enum": ["ru","kk","en","unknown"], "default": "unknown" },<br> <br> "title": { "type": ["string","null"] },<br> <br> "text": { "type": "string", "minLength": 1 },<br> <br> "author": { "type": ["string","null"] },<br> <br> "reach_proxy": { "type": ["number","null"] },<br> <br> "sentiment_proxy": { "type": ["number","null"] },<br> <br> "tags": { "type": "array", "items": { "type": "string" } },<br> <br> "raw_ref": { "type": ["string","null"] },<br> <br> "meta": { "type": "object", "additionalProperties": true }<br> <br> },<br> <br> "additionalProperties": false<br> <br> }<br> <br> Требование. Kernel обязан проставлять received_at. Если observed_at отсутствует, Kernel проставляет observed_at равным received_at и добавляет метку в meta.<br> <br> 11. Контракт Decision<br> <br> Decision является выходным объектом Kernel для любого обработанного Event. Decision обязателен даже если событие заблокировано. Decision является “атомом” обсуждения, аудита и привязки UI.<br> <br> {<br> <br> "type": "object",<br> <br> "required": ["decision_id","created_at","registry_version","mode_code","contour_code","hard_stop","status","violations","reasons","next_actions","links"],<br> <br> "properties": {<br> <br> "decision_id": { "type": "string" },<br> <br> "created_at": { "type": "string" },<br> <br> "registry_version": { "type": "integer" },<br> <br> "mode_code": { "type": "string", "enum": ["N0","N1","N2","N3","N4"] },<br> <br> "contour_code": { "type": "string", "enum": ["A","S","C","D"] },<br> <br> "hard_stop": { "type": "boolean" },<br> <br> "status": { "type": "string", "enum": ["APPROVED","BLOCKED"] },<br> <br> "violations": {<br> <br> "type": "array",<br> <br> "items": {<br> <br> "type": "object",<br> <br> "required": ["rule_code","rule_type","severity","description"],<br> <br> "properties": {<br> <br> "rule_code": { "type": "string" },<br> <br> "rule_type": { "type": "string", "enum": ["L0","LLAW"] },<br> <br> "severity": { "type": "string", "enum": ["CRITICAL","HIGH","MEDIUM","LOW"] },<br> <br> "description": { "type": "string" }<br> <br> }<br> <br> }<br> <br> },<br> <br> "reasons": { "type": "array", "items": { "type": "string" } },<br> <br> "next_actions": { "type": "array", "items": { "type": "string" } },<br> <br> "links": {<br> <br> "type": "object",<br> <br> "required": ["raw_item_id","canonical_event_id"],<br> <br> "properties": {<br> <br> "raw_item_id": { "type": "integer" },<br> <br> "canonical_event_id": { "type": "integer" }<br> <br> }<br> <br> },<br> <br> "debug": { "type": ["object","null"], "additionalProperties": true }<br> <br> },<br> <br> "additionalProperties": false<br> <br> }<br> <br> Требование. decision_id возвращается только если запись решения успешно сохранена в БД. Если запись не сохранена, Kernel отвечает ошибкой.<br> <br> 12. Контракты Registry объектов<br> <br> Правила и триггеры должны быть внешними по отношению к коду, то есть храниться в реестре и версионироваться.<br> <br> RegistryRule:<br> <br> rule_code<br> <br> rule_type (L0 или LLAW)<br> <br> severity<br> <br> description<br> <br> patterns<br> <br> is_active<br> <br> RegistryTrigger:<br> <br> mode_code<br> <br> contour_code (опционально)<br> <br> priority<br> <br> patterns<br> <br> is_active<br> <br> RegistryProtocol:<br> <br> protocol_code<br> <br> name<br> <br> allowed_modes<br> <br> constraints (включая стиль и запреты)<br> <br> is_active<br> <br> В MVP допускается, что RegistryProtocol в начале будет содержать только next_actions по режимам и минимальные текстовые ограничения, а позже будет расширяться.<br> <br> 13. Kernel API (OpenAPI смысловые эндпойнты)<br> <br> 13.1. Обработка события<br> <br> POST /event<br> <br> Вход: Event<br> <br> Выход: Decision<br> <br> Гарантии:<br> <br> записывается raw_item<br> <br> создаётся или выбирается canonical_event<br> <br> вычисляется режим и контур<br> <br> применяются гейты<br> <br> записывается decision<br> <br> возвращается Decision<br> <br> 13.2. Получение решения<br> <br> GET /decision/{decision_id}<br> <br> Выход: Decision + расширенная карточка для UI, включая нормализацию и ссылки на связанные raw_items, если запрошено параметрами.<br> <br> Для MVP можно сделать два режима:<br> <br> краткий (по умолчанию)<br> <br> полный (include=details)<br> <br> 13.3. Очередь<br> <br> GET /queue?limit=50&mode=N2&status=BLOCKED<br> <br> Выход: массив элементов очереди. Каждый элемент содержит минимум:<br> <br> decision_id<br> <br> created_at<br> <br> mode_code<br> <br> contour_code<br> <br> status<br> <br> source_name<br> <br> короткий preview текста (первые N символов)<br> <br> hard_stop<br> <br> 13.4. Sitcenter агрегаты<br> <br> GET /sitcenter/summary<br> <br> Выход:<br> <br> текущий режим системы (как агрегат по последним решениям или как “последнее состояние”)<br> <br> количество событий по режимам за период<br> <br> количество blocked за период<br> <br> топ причин блокировок<br> <br> последние решения N3/N2<br> <br> 13.5. Sitcenter поток<br> <br> GET /sitcenter/stream (SSE)<br> <br> Выход: события обновления очереди и агрегатов, чтобы большой экран обновлялся без перезагрузки.<br> <br> 13.6. Реестр<br> <br> GET /registry/rules<br> <br> POST /registry/rules<br> <br> GET /registry/triggers<br> <br> POST /registry/triggers<br> <br> GET /registry/protocols<br> <br> POST /registry/protocols<br> <br> Требование. Любое изменение реестра увеличивает registry_version и фиксируется в журнале реестра (в MVP можно журналировать изменения как отдельную таблицу или через системные decisions типа “REGISTRY_UPDATE”).<br> <br> 14. Kernel: хранение и транзакционность<br> <br> Kernel использует SQLite и файловое хранилище артефактов.<br> <br> Требование. Обработка /event обязана быть транзакционной минимум на уровне: raw_item + canonical_event link + decision. Если что-либо не записалось, decision не возвращается.<br> <br> 15. Формальная спецификация нормализации и fingerprint<br> <br> Нормализация для fingerprint должна быть:<br> <br> воспроизводимой<br> <br> консервативной<br> <br> не зависящей от внешних библиотек, которые могут менять поведение между версиями без явного контроля<br> <br> MVP нормализация:<br> <br> lowercasing<br> <br> удаление двойных пробелов<br> <br> замена табов на пробелы<br> <br> удаление невидимых символов<br> <br> обрезка до разумного лимита (например 20 000 символов) с фиксацией в meta, если было обрезание<br> <br> Fingerprint:<br> <br> hash(normalized_text + “|” + source_name + “|” + (source_item_id or “-”) + “|” + (url or “-”))<br> <br> Важное уточнение. fingerprint не является “истиной” дедупликации, это практическая эвристика. Поэтому система хранит и fingerprint, и source_item_id, и url. Это позволяет позже улучшать дедуп без потери данных.<br> <br> 16. Router: формальная спецификация<br> <br> Router использует registry_triggers. Алгоритм Router в MVP детерминированный и основан на pattern matching.<br> <br> Псевдокод:<br> <br> candidates = []<br> <br> for t in active registry_triggers:<br> <br> if matches_any(t.patterns, normalized_text):<br> <br> candidates.append(t)<br> <br> if empty:<br> <br> mode = "N0"<br> <br> contour = default_contour("N0")<br> <br> else:<br> <br> max_pr = max(c.priority for c in candidates)<br> <br> top = [c for c in candidates if c.priority == max_pr]<br> <br> if len(top) == 1:<br> <br> chosen = top[0]<br> <br> else:<br> <br> chosen = tie_break(top)<br> <br> mode = chosen.mode_code<br> <br> contour = chosen.contour_code or default_contour(mode)<br> <br> Tie-break фиксируется в коде и тестируется. Tie-break правило: выбирается более жёсткий режим по порядку N4 > N3 > N2 > N1 > N0. Если режим одинаковый, выбирается тот, где contour указан явно. Если и это одинаково, выбирается первый по стабильной сортировке (например по id триггера).<br> <br> Default contour фиксируется в реестре или в коде, но должен быть единственным источником истины. Для MVP допустимо зафиксировать в коде. Позже лучше вынести в registry_protocols.<br> <br> 17. Gates: формальная спецификация<br> <br> Гейт L-Law имеет приоритет. Если срабатывает LLAW правило, то hard_stop устанавливается в true и статус решения становится BLOCKED независимо от L0.<br> <br> Псевдокод:<br> <br> violations = []<br> <br> if matches_any(LLAW.patterns):<br> <br> violations += LLAW violations<br> <br> hard_stop = true<br> <br> status = BLOCKED<br> <br> next_actions = next_actions_for_hard_stop(mode)<br> <br> return<br> <br> if matches_any(L0.patterns):<br> <br> violations += L0 violations<br> <br> hard_stop = false<br> <br> status = BLOCKED<br> <br> next_actions = next_actions_for_l0_block(mode)<br> <br> return<br> <br> hard_stop = false<br> <br> status = APPROVED<br> <br> next_actions = next_actions_for_mode(mode)<br> <br> Важное уточнение. Даже при APPROVED next_actions ограничивают то, что UI имеет право предложить оператору. APPROVED не означает “публикация разрешена”, это означает “событие допускается к дальнейшим разрешённым операциям”.<br> <br> 18. Next_actions: спецификация<br> <br> Next_actions являются ключевым мостом между логикой Kernel и UX. Они должны быть достаточно грубыми, чтобы не зависеть от конкретного UI, но достаточно конкретными, чтобы UI мог ограничить сценарии.<br> <br> В MVP фиксируем минимальный набор действий как строковые коды.<br> <br> Базовые действия:<br> <br> ACTION_LOG_ONLY (зафиксировать и оставить в мониторинге)<br> <br> ACTION_REQUEST_VERIFICATION (пометить UNVERIFIED и запросить подтверждение)<br> <br> ACTION_ESCALATE (эскалация оператору/руководителю)<br> <br> ACTION_PREPARE_BRIEF (подготовить краткую сводку)<br> <br> ACTION_PREPARE_DRAFT (подготовить черновик формулировки)<br> <br> ACTION_USE_TEMPLATE (использовать шаблон, без свободного текста)<br> <br> ACTION_FREEZE_OUTPUT (запрет на любые внешние тексты)<br> <br> Правило по режимам в MVP:<br> <br> В N0 обычно доступны LOG_ONLY, REQUEST_VERIFICATION, PREPARE_DRAFT, PREPARE_BRIEF.<br> <br> В N2 обычно доступны REQUEST_VERIFICATION, ESCALATE, PREPARE_BRIEF, PREPARE_DRAFT с ограничениями.<br> <br> В N3 доступны ESCALATE, PREPARE_BRIEF, USE_TEMPLATE, FREEZE_OUTPUT.<br> <br> При hard_stop всегда доступен FREEZE_OUTPUT, и недоступен PREPARE_DRAFT.<br> <br> Детальные правила и связка с протоколами должны быть в registry_protocols. В MVP можно захардкодить матрицу next_actions в Kernel и позже вынести в реестр, но при этом необходимо зафиксировать её как часть версии Kernel и покрыть тестами.<br> <br> Часть 3. AI Assist, коннекторы, UI, CI/CD, критерии приёмки<br> <br> 19. AI Assist: архитектура и API<br> <br> AI Assist реализуется как отдельный сервис pssr-assist. Его назначение — ускорять и улучшать качество работы оператора без вмешательства в логику допуска.<br> <br> Assist не имеет прямого доступа к БД Kernel. Все операции сохранения происходят через API Kernel.<br> <br> 19.1. Поток взаимодействия<br> <br> Сценарий “AI summary”:<br> <br> UI запрашивает у Assist summary по canonical_event_id.<br> <br> Assist запрашивает через Kernel API все raw_items данного canonical_event.<br> <br> Assist генерирует summary.<br> <br> Assist отправляет в Kernel POST /ai/artifact.<br> <br> Kernel сохраняет ai_artifact.<br> <br> UI получает результат через Kernel.<br> <br> Сценарий “AI draft”:<br> <br> UI запрашивает draft по decision_id и protocol_code.<br> <br> Assist запрашивает через Kernel API:<br> <br> decision<br> <br> режим<br> <br> протокол<br> <br> Assist генерирует draft.<br> <br> Assist отправляет draft в Kernel POST /ai/draft-check.<br> <br> Kernel выполняет повторный gate-check.<br> <br> Kernel сохраняет draft как ai_artifact с gate_result.<br> <br> Kernel возвращает статус draft: APPROVED или BLOCKED.<br> <br> UI отображает draft только с указанием результата проверки.<br> <br> Assist не имеет права напрямую возвращать draft в UI без прохождения через Kernel.<br> <br> 19.2. Assist API (минимальный)<br> <br> POST /assist/summary<br> <br> Вход:<br> <br> canonical_event_id<br> <br> POST /assist/entities<br> <br> Вход:<br> <br> raw_item_id<br> <br> POST /assist/draft<br> <br> Вход:<br> <br> decision_id<br> <br> protocol_code<br> <br> Assist API является внутренним. В продакшене его может вызывать только UI или оркестратор.<br> <br> 19.3. Ограничения AI Assist<br> <br> Не может менять режим.<br> <br> Не может менять hard_stop.<br> <br> Не может менять registry_version.<br> <br> Не может напрямую писать в БД Kernel.<br> <br> Все результаты помечаются как advisory.<br> <br> 20. Коннекторы: формализация<br> <br> Коннектор — отдельный сервис, который:<br> <br> получает данные из источника,<br> <br> приводит к Event Schema,<br> <br> отправляет в Kernel.<br> <br> Коннектор обязан быть идемпотентным.<br> <br> 20.1. Общие требования к коннекторам<br> <br> Наличие checkpoint (last_processed_id или timestamp).<br> <br> Checkpoint обновляется только после успешного ответа Kernel.<br> <br> Повторный запуск не создаёт дублей.<br> <br> При ошибке Kernel коннектор логирует и повторяет попытку.<br> <br> Коннектор не хранит решений.<br> <br> 20.2. YouScan Connector<br> <br> Функция:<br> <br> получать mentions через API<br> <br> маппить в Event Schema<br> <br> отправлять в Kernel<br> <br> Дополнительные поля:<br> <br> reach_proxy<br> <br> sentiment_proxy<br> <br> platform<br> <br> engagement<br> <br> Checkpoint:<br> <br> хранится локально (файл или SQLite)<br> <br> обновляется после успешной обработки партии<br> <br> 20.3. RSS Connector<br> <br> Функция:<br> <br> регулярный polling RSS<br> <br> hash URL+title<br> <br> отправка в Kernel<br> <br> Дедупликация:<br> <br> если URL уже обработан, событие не отправляется повторно<br> <br> 20.4. Manual Import Connector<br> <br> Функция:<br> <br> загрузка файла (CSV/JSON)<br> <br> преобразование строк в Event<br> <br> отправка в Kernel<br> <br> Используется для tabletop-тестов.<br> <br> 21. UI: детальная спецификация<br> <br> UI реализуется как отдельное SPA или веб-приложение с Bootstrap 5.<br> <br> 21.1. Mobile Console<br> <br> Экран:<br> <br> список последних решений<br> <br> карточка выбранного события<br> <br> режим (крупно)<br> <br> статус (APPROVED/BLOCKED)<br> <br> кнопки next_actions<br> <br> Особенности:<br> <br> минимальное количество текста<br> <br> collapsible детали<br> <br> крупная индикация hard_stop<br> <br> 21.2. Desktop Operator<br> <br> Экран:<br> <br> очередь<br> <br> карточка решения<br> <br> блок violations<br> <br> блок next_actions<br> <br> блок AI artifacts<br> <br> ссылка на Decision Viewer<br> <br> 21.3. Sitcenter Wall<br> <br> Экран:<br> <br> текущий режим (очень крупно)<br> <br> индикатор hard_stop<br> <br> количество событий по режимам<br> <br> последние решения N2/N3<br> <br> топ нарушений<br> <br> Особенности:<br> <br> read-only<br> <br> обновление через SSE<br> <br> минимальное взаимодействие<br> <br> 22. CI/CD и контроль качества<br> <br> Каждый репозиторий имеет свой CI:<br> <br> contracts: проверка схем<br> <br> kernel: unit-тесты Router и Gates<br> <br> assist: тест генерации и возврата draft<br> <br> ingest: тест идемпотентности<br> <br> ui: типизация и проверка контрактов<br> <br> Интеграционные тесты:<br> <br> запуск всего стека через docker-compose<br> <br> отправка тестовых событий<br> <br> проверка, что режимы совпадают с ожиданиями<br> <br> проверка, что blocked события не дают draft<br> <br> 23. Критерии приёмки MVP<br> <br> Kernel:<br> <br> Детерминированный режим.<br> <br> L-Law блокирует корректно.<br> <br> registry_version фиксируется.<br> <br> Нет решения без decision_id.<br> <br> Assist:<br> <br> Генерирует summary.<br> <br> Draft проходит повторную проверку.<br> <br> Заблокированный draft отображается как BLOCKED.<br> <br> Ingest:<br> <br> Нет дублей при повторном запуске.<br> <br> Checkpoint работает.<br> <br> UI:<br> <br> Отображает режим.<br> <br> Отображает hard_stop.<br> <br> Не предлагает запрещённых действий.<br> <br> Sitcenter:<br> <br> Обновляется автоматически.<br> <br> Показывает агрегаты корректно.<br> <br> 24. Итоговое состояние MVP<br> <br> В результате вы получаете:<br> <br> раздельные сервисы,<br> <br> воспроизводимое ядро,<br> <br> масштабируемую архитектуру,<br> <br> возможность расширять источники,<br> <br> возможность усиливать безопасность позже,<br> <br> возможность заменить фронтенд без переписывания Kernel.