# Этапы разработки ## Общий принцип Не делаем сразу тяжелую доменную платформу. Идем вертикальными поставками: 1. сначала транспорт и создание задачи 2. потом source-side представление 3. потом синхронизация 4. потом уведомления и полировка ## Freeze point на 2026-04-19 Текущий вертикальный срез временно заморожен. На момент freeze point уже есть: - отправка запроса из source project в target project того же `workspace` - отсутствие требования прямого membership в target project для отправки - source-side список `Открытые / Завершенные` - source-side карточка на shell `Предложений` - source-side редактирование открытого запроса по `заголовку` и `описанию` - зеркалирование статуса, комментариев, вложений и activity из целевого контура - source-side действия `Принять`, `Отклонить`, `Ответ во внешний контур` - индикатор непрочитанных изменений - карточка `Маршрутизация` в целевом формате `3 x 3` Дальше по roadmap пока не идем, пока не приняты продуктовые решения по внутреннему жизненному циклу принятого запроса. ## Новая рамка после freeze point на 2026-04-20 После дополнительной продуктовой фиксации следующий цикл делится на три слоя: 1. единый shell карточки внешнего контура 2. двусторонняя доска `Исходящие / Входящие` 3. пользовательские представления поверх той же доски При этом обязательное архитектурное ограничение фиксируется заранее: - во `Внешних контурах` нет drag-and-drop между блоками - блоки здесь означают представления, а не стадии workflow Подробные архитектурные шаги вынесены в: - [11_STEP_external-contours-detail-shell.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-routing/11_STEP_external-contours-detail-shell.md) - [12_STEP_external-contours-bidirectional-board.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-routing/12_STEP_external-contours-bidirectional-board.md) - [13_STEP_external-contours-board-data-contract.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-routing/13_STEP_external-contours-board-data-contract.md) ## Этап 0. Термины и навигация ### Цель Подготовить интерфейс и словарь сущностей без ломки backend-логики. ### Что входит - `Рабочие элементы` -> `Внутренний контур` - новая вкладка `Внешние контуры` - подготовка i18n-ключей и текстов - фиксация терминов в продуктовой документации ### Результат В проекте уже есть новая структура навигации, но бизнес-логика еще не внедрена. ## Этап 1. Маршрутизация запроса в целевой проект ### Цель Сделать рабочий сценарий отправки задачи из source project в target project. ### Что входит - новая create-form во `Внешних контурах` - выбор целевого проекта - выбор исполнителя из целевого проекта - orchestration endpoint - использование intake bridge как backend-моста - немедленный перевод в default-state целевого проекта - создание target issue - запись source/target metadata ### Что не входит - полноценная синхронизация файлов - полноценная зеркальная история - сложные уведомления ### Критерий приемки - пользователь отправляет внешний запрос - в целевом проекте появляется обычная задача - задача не зависает в triage - source-side список уже видит факт отправки ### Статус Реализовано. Что работает фактически: - `POST /external-contours/` создает target issue в целевом проекте - target issue сразу попадает в обычный workflow целевого проекта - source-side `GET /external-contours/` возвращает отправленные запросы с metadata источника и цели - target contour теперь выбирается по policy `same workspace + intake enabled`, а не только из joined projects - прямое membership в target project для отправки не требуется ## Этап 2. Source-side список и статусная пришлепка ### Цель Дать инициатору читаемый контроль за отправленными запросами. ### Что входит - список `Открытые` - список `Завершенные` - текущий статус задачи как пришлепка - отображение целевого проекта - отображение исполнителя - отображение даты обновления - индикатор новых изменений ### Критерий приемки - в проекте-источнике виден список отправленных запросов - у каждой записи отображается актуальный статус целевой задачи ### Статус Реализовано частично в рамках текущего вертикального среза. Что уже работает: - source-side список `Открытые / Завершенные` - status pill по фактическому state целевой задачи - отображение целевого проекта - отображение исполнителей целевого контура - отображение фактической даты последнего изменения - индикатор новых изменений в source-side списке на базе unread уведомлений - открытие source-side detail экрана Что еще остается на следующие этапы: - полноценная зеркальная activity/history - уведомления Дополнительно реализовано: - source-side detail показывает блок маршрутизации - в карточке видны источник, цель, отправитель, дата отправки и связанная целевая задача ## Этап 3. Source-side детальный экран и зеркалирование изменений ### Цель Сделать так, чтобы отправитель видел ход исполнения не только по одной плашке статуса. ### Что входит - детальный экран внешнего контура - блок `Исходный запрос` - блок `Текущий статус` - mirrored activity stream - mirrored comments - mirrored files - mirrored description updates ### Важное правило Исходный запрос не должен теряться. Поэтому target-изменения лучше показывать отдельным блоком истории, а не просто затирать исходное описание. ### Критерий приемки - если в target issue добавили файл, инициатор видит его в source-side карточке - если в target issue поменяли статус, это видно в source-side карточке - если в target issue написали комментарий, это видно в source-side карточке ### Статус Реализовано частично. Что уже работает: - source-side detail использует отдельный экран `Внешних контуров` - в карточке отображается блок маршрутизации с ключевой source-target связью - у отправителя открытый внешний запрос редактируется прямо из source-side карточки по полям `заголовок` и `описание`, даже без membership в target project - текущий статус берется из фактического state целевой задачи - если у инициатора нет membership в target project, карточка переключается в source-side readonly режим без прямого открытия чужого проекта - блок `Маршрутизация` перестроен в фиксированный формат `3 x 3` - в `Маршрутизацию` перенесены `Назначенный` и `Срок выполнения` - в блоке `Свойства` убраны дубли `Внешний контур`, `Назначенный` и `Срок выполнения` - название исходного внутреннего контура в карточке маршрутизации берется из живого проекта, а не из застывшего metadata snapshot - для закрытого внешнего запроса доступны source-side действия `Принять` и `Отклонить` - `Принять` фиксирует решение источника в bridge metadata и помечает запрос как принятый во внутренний контур - `Отклонить` требует комментарий причины, возвращает target issue в default-state целевого проекта и переносит source-side карточку обратно в список `Открытые` - source-side readonly карточка зеркалит актуальные комментарии, вложения и activity целевой задачи - вложения доступны через proxy download endpoint без прямого membership в target project - detail карточка source-only пользователя обновляется polling-ом и подтягивает новые комментарии без ручной перезагрузки - инициатор может отправить комментарий обратно во внешний контур прямо из source-side карточки Что остается: - зеркалирование inline-файлов из комментариев и описания, а не только issue attachments - realtime вместо polling - отдельная сущность или шаг для переноса принятого результата во `Внутренний контур` ## Этап 4. Уведомления ### Цель Не заставлять инициатора вручную проверять изменения. ### Что входит - in-app notification на: - принятие - перевод статуса - добавление файла - новый комментарий - завершение - отмену ### Критерий приемки - инициатор получает уведомления по ключевым событиям жизненного цикла внешнего запроса ### Статус Реализовано частично. Что уже работает: - создаются in-app уведомления по изменениям целевой задачи внешнего контура - покрыты события: - смена статуса - новый комментарий - изменение описания - новое вложение - уведомление привязано к source project, а не требует membership в target project - notification payload несет `external contour request id` и `target issue id` - список уведомлений помечает такие записи как `is_external_contour = true` - notification preview может открыть source-side карточку внешнего контура, а не обычный issue preview - открытие source-side карточки помечает связанные unread уведомления как прочитанные и снимает индикатор новых изменений в списке Что остается: - in-app уведомления на явные source-side решения `Принять / Отклонить` - отдельный индикатор новых изменений в списке `Открытые / Завершенные` - push/realtime канал вместо обычного цикла обновления UI ## Этап 5. Полировка и правила эксплуатации ### Что входит - edge cases - повторная отправка - отмена - защита от удаления target issue - аудит прав - тест-кейсы - регламент эксплуатации ## Этап 6. Единый shell карточки внешнего контура ### Цель Привести карточку деталей `Внешних контуров` к тому же UX-паттерну, что и во `Внутреннем контуре`, не ломая при этом внешний data-flow. ### Что входит - общий shell открытия карточки - тот же класс верхнего action-bar: - закрытие просмотра - полноэкранный режим - переключение макета - подписка или отписка - копирование ссылки - меню дополнительных действий - переиспользование общего представления shell без подмены доменной модели внешнего контура - сохранение внешнеконтурного body: - `Маршрутизация` - зеркальные комментарии - зеркальные вложения - external lifecycle ### Что не входит - две системные зоны `Исходящие / Входящие` - пользовательские колонки - drag-and-drop - насильственный перевод внешнего запроса в обычный issue detail ### Критерий приемки - карточка `Внешних контуров` открывается по тому же UX-паттерну, что и внутренний peek - source-only сценарий не ломается - body карточки остается внешнеконтурным ### Статус Запланировано. Подробно описано в: - [11_STEP_external-contours-detail-shell.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-routing/11_STEP_external-contours-detail-shell.md) ## Этап 7. Двусторонняя доска `Исходящие / Входящие` ### Цель Дать проекту единый рабочий экран межконтурной работы, где видны и отправленные, и полученные запросы. ### Что входит - две фиксированные системные зоны: - `Исходящие` - `Входящие` - единый board-level data contract - фильтрация обеих зон по аналогии с `Внутренним контуром` - счетчики - открытие карточки в shell этапа 6 ### Важное правило Это не kanban статусов. Во `Внешних контурах`: - нет drag-and-drop между блоками - блоки означают представления по направлению и фильтрам - смена состояния не должна кодироваться визуальным переносом карточки ### Что не входит - пользовательские кастомные зоны - свободный конструктор колонок - превращение доски во второй workflow движок ### Критерий приемки - пользователь видит и `Исходящие`, и `Входящие` - отправленные запросы не теряются после отправки - обе системные зоны фильтруются через единый механизм - карточка из любой зоны открывается единообразно ### Статус Запланировано. Подробно описано в: - [12_STEP_external-contours-bidirectional-board.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-routing/12_STEP_external-contours-bidirectional-board.md) - [13_STEP_external-contours-board-data-contract.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-routing/13_STEP_external-contours-board-data-contract.md) ## Этап 8. Пользовательские представления поверх двусторонней доски ### Цель Разрешить пользователю собирать собственные рабочие выборки поверх уже стабилизированной двусторонней доски. ### Что входит - пользовательские блоки или представления - пользовательское имя блока - сохранение набора фильтров - персональные рабочие выборки по контурам, статусам, пользователям и другим признакам ### Важное правило Пользовательские блоки не меняют базовый принцип: - это не стадии workflow - это не drag-and-drop - это не замена `Внутреннего контура` ### Зависимость Этап начинается только после стабилизации этапов 6 и 7. ### Статус Запланировано как следующий слой развития, но не входит в ближайший обязательный срез. ## Технические решения, которые желательно держать с самого начала ### 1. Не ломать штатный intake Он остается отдельным продуктовым модулем. ### 2. Явно хранить source/target связь Даже если первая версия идет через `IntakeIssue.extra`, связь не должна быть неявной. ### 3. Использовать фактический статус target issue В source-side плашке лучше показывать не abstract intake status, а реальный текущий статус исполнения. ### 4. Не пытаться делать полную двустороннюю редакцию сразу На старте безопаснее сделать: - создание из источника - исполнение в цели - синхронизацию результата обратно в источник ## Открытые вопросы ### 1. Что именно делает `Принять` Нужно зафиксировать конечную бизнес-логику: - `Принять` только ставит source-side решение `accepted` - `Принять` создает отдельную сущность во `Внутреннем контуре` - `Принять` переводит карточку в отдельный внутренний статус без создания дубликата Это главный блокирующий вопрос перед следующим этапом. ### 2. Где дальше живет принятый запрос Нужно решить: - карточка остается во `Внешних контурах` как историческая запись - карточка уходит во `Внутренний контур` - карточка одновременно видна в обоих местах, но с разной ролью ### 3. Нужна ли отдельная сущность source-side Нужно принять решение: - достаточно ли текущей source-side проекции поверх bridge metadata - или уже пора вводить отдельную таблицу/модель для внешних контуров ### 4. Файлы Нужно решить: - достаточно ли proxy-доступа к файлам целевой задачи - или файлы надо физически копировать в source-side representation - нужно ли зеркалировать inline-файлы из описания и комментариев ### 5. Комментарии Нужно решить: - source-side reply остается облегченной обратной связью - или нужен полноценный двусторонний поток комментариев как единый discussion-thread ### 6. Уровень realtime Нужно решить: - хватает ли polling для PoC - или следующий этап уже должен включать push/realtime события ### 7. Счетчики и вкладки Нужно решить: - нужен ли отдельный unread-counter по вкладкам `Открытые / Завершенные` - нужен ли отдельный сегмент для запросов, принятых во `Внутренний контур` ### 8. Право редактирования после отправки Нужно решить: - отправитель редактирует только `заголовок` и `описание` - или после отправки он может менять еще `срок`, `назначенного`, `приоритет`, `метки` ### 9. Доступ к target issue Нужно решить: - должен ли инициатор иметь прямую ссылку на target issue - или source-side карточка должна оставаться единственной точкой просмотра для пользователей без membership Текущее решение: - при отсутствии membership в target project прямой переход в target issue скрывается - карточка остается доступной из source project ## Рекомендуемый порядок фактической разработки 1. Этап 0 2. Этап 1 3. Этап 2 4. Этап 3 5. Этап 4 6. Этап 5 Это даст быстрый полезный результат и не загонит проект в ранний тяжелый refactor.