NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-r.../phase-roadmap.md

468 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Этапы разработки
## Общий принцип
Не делаем сразу тяжелую доменную платформу.
Идем вертикальными поставками:
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.