Add docs for cross-project task routing

This commit is contained in:
DCCONSTRUCTIONS 2026-04-18 19:48:02 +03:00
parent 39d9d9cd7a
commit 75ba36a318
2 changed files with 560 additions and 0 deletions

View File

@ -0,0 +1,357 @@
# Межпроектная маршрутизация задач
## Цель
Добавить в `NODE.DC TM` отдельный сценарий межпроектной постановки задач между контурами без перепрошивки штатного `Intake`.
Базовая идея:
- `Рабочие элементы` переименовываются в `Внутренние контуры`
- рядом появляется новый модуль `Внешние контуры`
- пользователь из проекта-источника создает внешний запрос
- запрос уходит в целевой проект
- в целевом проекте он становится обычной задачей
- в проекте-источнике сохраняется видимый объект маршрутизации со статусом, историей и материалами
## Почему выбран именно этот путь
Не трогаем штатный `Intake` как пользовательский модуль.
Используем его только как внутренний backend-мост, потому что:
- механизм уже умеет создавать bridge между `Issue` и `IntakeIssue`
- уже есть переход из `TRIAGE` в default-state проекта
- уже есть `extra JSON` для метаданных маршрутизации
- это самый безопасный путь для форка и дальнейших обновлений
## Термины
### Внутренние контуры
То, что сейчас в UI является обычными рабочими элементами проекта.
### Внешние контуры
Новый отдельный модуль проекта, через который задача отправляется в другой проект внутри того же workspace.
### Проект-источник
Проект, из которого инициируется запрос.
### Целевой проект
Проект, в котором задача реально исполняется.
### Исходная карточка внешнего контура
Карточка или запись в проекте-источнике, где инициатор видит:
- текущий статус
- целевой проект
- назначенного исполнителя
- историю обработки
- файлы
- уведомления о ходе работы
### Целевая задача
Обычная задача в целевом проекте, которая попадает в обычный workflow этого проекта.
## Ключевой продуктовый результат
Пользователь из `Менеджеры` должен иметь возможность:
- открыть `Внешние контуры`
- выбрать целевой проект, например `Бухгалтерия`
- описать запрос
- назначить исполнителя из `Бухгалтерия`
- отправить запрос
После этого:
- у `Бухгалтерия` появляется обычная задача в их проекте
- у отправителя в `Менеджеры` появляется запись во `Внешних контурах`
- у этой записи есть статусная пришлепка
- при любом изменении статуса в целевом проекте статус в источнике обновляется
- если в целевом проекте меняют описание, прикладывают файлы, комментируют или закрывают задачу, это отражается в источнике
- инициатор получает уведомления о существенных изменениях
## Обязательные требования
### 1. Отдельный модуль
`Внешние контуры` не должны быть переименованным `Intake`.
Это отдельная новая вкладка проекта.
### 2. Обычная задача в целевом проекте
Задача не должна висеть в ручном triage.
После отправки она должна сразу попадать в обычный workflow целевого проекта, в его default-state.
### 3. Статусная пришлепка в источнике
У каждой записи во `Внешних контурах` в списке должен быть видимый статус.
Для первой версии правильнее показывать фактическое имя текущего статуса целевой задачи:
- `В плане`
- `К выполнению`
- `В работе`
- `Готово`
- `Отменено`
- либо любой другой кастомный статус целевого проекта
То есть источник видит не абстрактное `accepted`, а реальный текущий статус исполнения.
### 4. Зеркалирование изменений из целевого проекта в источник
Изменения в целевой задаче должны отражаться в исходной карточке внешнего контура.
Минимальный обязательный набор:
- изменение статуса
- изменение названия
- изменение описания
- добавление/удаление файлов
- комментарии и служебные заметки по задаче
- закрытие/отмена задачи
### 5. Уведомления инициатору
Инициатор должен получать уведомления, когда:
- задача принята в работу
- задача переведена в другой статус
- добавлен файл
- добавлен комментарий
- задача завершена
- задача отменена
### 6. Трассировка между источником и целью
Связь между источником и целевой задачей должна быть явной и восстановимой.
Нельзя делать фичу как “создали задачу и забыли”.
## Архитектурный подход
## Общая схема
Используем существующий intake bridge как транспортный слой:
- создаем `Issue` в целевом проекте
- создаем `IntakeIssue`
- сразу переводим bridge в `ACCEPTED`
- целевая задача попадает в default-state проекта
Но только этого уже недостаточно.
Из-за требований на статусную пришлепку, зеркалирование файлов и уведомления нужен еще source-side слой отображения.
## Что остается от текущей идеи варианта 2
Сохраняем:
- reuse intake backend-механики
- отдельный orchestration endpoint
- отдельный фронтовый модуль `Внешние контуры`
Расширяем:
- добавляем источник правды для source-side карточки
- добавляем синхронизацию изменений из target issue в source representation
- добавляем уведомления
## Рекомендуемая модель данных для первой итерации
### Обязательная связь
Нужна явная пара:
- `source_project_id`
- `source_request_id`
- `target_project_id`
- `target_issue_id`
### Метаданные bridge
В `IntakeIssue.extra` храним:
- тип моста: `external-contours`
- источник
- цель
- автора
- временные метки
Пример:
```json
{
"bridge": "external-contours",
"source_project_id": "uuid",
"source_project_name": "Менеджеры",
"target_project_id": "uuid",
"target_project_name": "Бухгалтерия",
"requested_by_id": "uuid",
"requested_by_name": "Иван Петров",
"requested_at": "2026-04-18T19:00:00Z"
}
```
### Source-side представление
Для source-side части есть два пути:
1. Легкая проекция без отдельной таблицы
- список `Отправленные` собирается по `IntakeIssue.extra`
- детали берутся из целевой задачи
2. Отдельная source-side сущность или shadow-record
- отдельная запись для внешнего контура в проекте-источнике
- в ней хранится mirrored state
Для требований текущего этапа безопаснее считать, что source-side проекция понадобится.
Причина:
- нужен список со статусом
- нужны файлы в источнике
- нужна история изменений
- нужны уведомления
Простого “читать target issue на лету” для этого, скорее всего, будет мало.
## UX первой рабочей вертикали
## Модуль `Внешние контуры`
В проекте появляется новая вкладка:
- `Внешние контуры`
Внутри:
- кнопка `Новый внешний запрос`
- список `Открытые`
- список `Завершенные`
## Форма создания
Поля:
- целевой проект
- название
- описание
- исполнитель из целевого проекта
- приоритет
- срок
- метки
Вложения можно заложить сразу в спецификацию, но в первую техническую поставку лучше включать аккуратно.
## Карточка в списке
В строке списка должны быть:
- название
- целевой проект
- исполнитель
- дата создания
- статусная пришлепка
- индикатор новых изменений
## Детальный экран внешнего контура
Детальный экран источника не должен быть просто копией target issue.
Правильнее собрать его из блоков:
- исходный запрос
- текущий статус
- целевой проект и исполнитель
- история изменений
- синхронизированные файлы
- комментарии/обновления
Это безопаснее, чем пытаться перетирать исходное описание данными целевого проекта.
## Правила синхронизации
## Направления
### Источник -> цель
На этапе создания отправляем:
- название
- описание
- исполнителя
- приоритет
- срок
- метки
### Цель -> источник
После создания отражаем обратно:
- текущий статус
- изменения описания
- комментарии
- файлы
- итоговый результат
## Что должно быть синхронизировано в обязательном порядке
- `target issue state.name`
- `target issue updated_at`
- файлы target issue
- пользовательские комментарии
- итоговый resolution state
## Что пока не нужно считать обязательным
- полная двусторонняя редакция из источника после отправки
- редактирование чужих project labels через источник
- полный realtime-collab режим
## Уведомления
Минимальный набор событий:
- запрос создан
- задача принята
- статус изменен
- добавлен файл
- добавлен комментарий
- задача завершена
- задача отменена
Каналы первой версии:
- in-app notifications
Каналы последующих итераций:
- email
- внешние integrations
## Ограничения текущего этапа
### 1. Вложения сейчас хрупкие
Текущий runtime уже показывал хрупкость attachment flow.
Поэтому вложения нужно учитывать в дизайне, но внедрять аккуратно и тестировать отдельно.
### 2. Права сложнее, чем кажется
Отправитель должен иметь право отправлять запрос из source project, но не обязан быть участником target project.
При этом:
- target assignee должен быть участником target project
- target issue создается в target project
- источник должен иметь возможность видеть результат обработки без полного membership в target project
### 3. Простая “копия intake” уже недостаточна
Как только добавляются:
- статусная пришлепка
- файлы
- история
- уведомления
фича перестает быть просто формой создания.
Нужен отдельный источник правды для source-side представления.
## Что считаем текущим этапом
Текущий этап — это не финальная реализация, а проектирование и запуск вертикального среза.
В этот этап входят:
- фиксация терминологии
- фиксация архитектурного подхода
- разбиение на поставки
- определение обязательных требований для первой версии
- определение границ MVP
Подробная поэтапная разработка описана в:
- [phase-roadmap.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/cross-project-task-routing/phase-roadmap.md)

View File

@ -0,0 +1,203 @@
# Этапы разработки
## Общий принцип
Не делаем сразу тяжелую доменную платформу.
Идем вертикальными поставками:
1. сначала транспорт и создание задачи
2. потом source-side представление
3. потом синхронизация
4. потом уведомления и полировка
## Этап 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 список уже видит факт отправки
## Этап 2. Source-side список и статусная пришлепка
### Цель
Дать инициатору читаемый контроль за отправленными запросами.
### Что входит
- список `Открытые`
- список `Завершенные`
- текущий статус задачи как пришлепка
- отображение целевого проекта
- отображение исполнителя
- отображение даты обновления
- индикатор новых изменений
### Критерий приемки
- в проекте-источнике виден список отправленных запросов
- у каждой записи отображается актуальный статус целевой задачи
## Этап 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 карточке
## Этап 4. Уведомления
### Цель
Не заставлять инициатора вручную проверять изменения.
### Что входит
- in-app notification на:
- принятие
- перевод статуса
- добавление файла
- новый комментарий
- завершение
- отмену
### Критерий приемки
- инициатор получает уведомления по ключевым событиям жизненного цикла внешнего запроса
## Этап 5. Полировка и правила эксплуатации
### Что входит
- edge cases
- повторная отправка
- отмена
- защита от удаления target issue
- аудит прав
- тест-кейсы
- регламент эксплуатации
## Технические решения, которые желательно держать с самого начала
### 1. Не ломать штатный intake
Он остается отдельным продуктовым модулем.
### 2. Явно хранить source/target связь
Даже если первая версия идет через `IntakeIssue.extra`, связь не должна быть неявной.
### 3. Использовать фактический статус target issue
В source-side плашке лучше показывать не abstract intake status, а реальный текущий статус исполнения.
### 4. Не пытаться делать полную двустороннюю редакцию сразу
На старте безопаснее сделать:
- создание из источника
- исполнение в цели
- синхронизацию результата обратно в источник
## Открытые вопросы
### 1. Source-side сущность
Нужно принять решение:
- достаточно ли source-side проекции
- или нужна отдельная таблица/модель для внешних контуров
### 2. Файлы
Нужно решить:
- показываем ли мы source-side ссылку на target asset
- или физически копируем файл в source representation
### 3. Комментарии
Нужно решить:
- комментарии зеркалируются односторонне из цели в источник
- или источник тоже может отвечать прямо из source-side карточки
### 4. Уровень realtime
Нужно решить:
- хватит ли near-realtime через polling и existing refresh
- или сразу нужен realtime через live-события
### 5. Доступ к target issue
Нужно решить:
- должен ли инициатор иметь прямую ссылку на target issue
- или доступ к target issue должен быть скрыт, а source-side карточка должна быть единственной точкой просмотра
## Рекомендуемый порядок фактической разработки
1. Этап 0
2. Этап 1
3. Этап 2
4. Этап 3
5. Этап 4
6. Этап 5
Это даст быстрый полезный результат и не загонит проект в ранний тяжелый refactor.