NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-r.../README.md

26 KiB
Raw Blame History

Межпроектная маршрутизация задач

Цель

Добавить в NODE.DC TM отдельный сценарий межпроектной постановки задач между контурами без перепрошивки штатного Intake.

Базовая идея:

  • Рабочие элементы переименовываются в Внутренний контур
  • рядом появляется новый модуль Внешние контуры
  • пользователь из проекта-источника создает внешний запрос
  • запрос уходит в целевой проект
  • в целевом проекте он становится обычной задачей
  • в проекте-источнике сохраняется видимый объект маршрутизации со статусом, историей и материалами

Почему выбран именно этот путь

Не трогаем штатный Intake как пользовательский модуль.

Используем его только как внутренний backend-мост, потому что:

  • механизм уже умеет создавать bridge между Issue и IntakeIssue
  • уже есть переход из TRIAGE в default-state проекта
  • уже есть extra JSON для метаданных маршрутизации
  • это самый безопасный путь для форка и дальнейших обновлений

Термины

Внутренний контур

То, что сейчас в UI является обычными рабочими элементами проекта.

Внешние контуры

Новый отдельный модуль проекта, через который задача отправляется в другой проект внутри того же workspace.

Проект-источник

Проект, из которого инициируется запрос.

Целевой проект

Проект, в котором задача реально исполняется.

Исходная карточка внешнего контура

Карточка или запись в проекте-источнике, где инициатор видит:

  • текущий статус
  • целевой проект
  • назначенного исполнителя
  • историю обработки
  • файлы
  • уведомления о ходе работы

Целевая задача

Обычная задача в целевом проекте, которая попадает в обычный workflow этого проекта.

Ключевой продуктовый результат

Пользователь из Менеджеры должен иметь возможность:

  • открыть Внешние контуры
  • выбрать целевой проект, например Бухгалтерия
  • описать запрос
  • назначить исполнителя из Бухгалтерия
  • отправить запрос

После этого:

  • у Бухгалтерия появляется обычная задача в их проекте
  • у отправителя в Менеджеры появляется запись во Внешних контурах
  • у этой записи есть статусная пришлепка
  • при любом изменении статуса в целевом проекте статус в источнике обновляется
  • если в целевом проекте меняют описание, прикладывают файлы, комментируют или закрывают задачу, это отражается в источнике
  • инициатор получает уведомления о существенных изменениях

Текущий статус реализации

На текущем этапе уже реализовано:

  • отдельный модуль Внешние контуры
  • отдельный backend endpoint маршрутизации
  • создание target issue в целевом проекте через intake bridge
  • немедленный перевод target issue в обычный workflow целевого проекта
  • source-side список отправленных запросов
  • source-side детальный экран на базе shell Предложений
  • status pill по фактическому состоянию target issue
  • workspace-wide выбор целевого внешнего контура по policy:
    • тот же workspace
    • у целевого проекта включен модуль
    • прямой membership в target project не требуется
  • source-side карточка как основная точка работы отправителя, если у него нет доступа в целевой проект
  • source-side редактирование открытого запроса:
    • заголовок
    • описание
  • source-side действия:
    • Принять
    • Отклонить
    • Ответ во внешний контур
  • зеркалирование из целевой задачи в source-side карточку:
    • комментарии
    • вложения
    • activity
    • обновления статуса
  • proxy download для вложений без прямого membership в target project
  • unread-индикатор новых изменений по source-side карточке
  • блок Маршрутизация в фиксированном формате 3 x 3

Freeze point на 2026-04-19

Текущий этап временно заморожен.

Заморозка делается после достижения рабочего вертикального среза:

  • запрос можно отправить из проекта-источника в другой проект того же workspace
  • в целевом проекте создается обычная задача и сразу попадает в обычный workflow
  • отправитель видит свой source-side список и карточку без обязательного доступа в чужой проект
  • в source-side карточке видны статус, маршрут, назначенный, срок, комментарии, вложения и activity из целевого контура
  • отправитель может поправить ошибку в заголовке и описании, пока запрос открыт
  • отправитель может принять результат во внутренний контур или вернуть запрос обратно во внешний контур с комментарием причины

На этом месте разработка следующего шага останавливается до фиксации продуктовых решений.

Зафиксированные продуктовые решения на 2026-04-20

После freeze point приняты дополнительные продуктовые решения по следующему циклу развития Внешних контуров.

1. Нужны две обязательные системные зоны

Во Внешних контурах должны появиться:

  • Исходящие
  • Входящие

Исходящие обязательны, потому что пользователь должен видеть запросы, которые он сам отправил в другие контуры, до и после обработки.

Входящие обязательны, потому что проект должен видеть запросы, пришедшие к нему из других контуров, в отдельном специализированном режиме работы, а не только как обычные задачи Внутреннего контура.

2. Обе зоны должны фильтроваться так же гибко, как во Внутреннем контуре

Минимальный целевой принцип:

  • фильтрация по пользователям
  • фильтрация по статусам
  • фильтрация по назначенным
  • фильтрация по автору
  • фильтрация по контурам и связанным проектам

То есть Внешние контуры должны получить не просто статичный список, а управляемое рабочее представление.

3. Карточка деталей внешнего контура должна перейти на тот же UX-паттерн, что и во Внутреннем контуре

При клике по карточке должна открываться панель того же класса:

  • закрыть просмотр
  • открыть на весь экран
  • переключить макет
  • подписка или отписка
  • копирование ссылки
  • меню дополнительных действий

При этом:

  • действие удаления в этом shell не является обязательным
  • тело карточки остается внешнеконтурным, а не превращается в обычную карточку внутренней задачи

4. Внешний контур — это не workflow-kanban

Важно зафиксировать заранее:

  • пользователь не должен перетаскивать задачи между блоками
  • блоки во Внешних контурах — это представления и выборки, а не стадии исполнения
  • нельзя переносить сюда механику drag-and-drop из Внутреннего контура

5. Пользовательские колонки нужны, но не входят в ближайший обязательный срез

Собственные пользовательские блоки и сортировки нужны как следующий этап развития, но не должны размыть ближайшие обязательные поставки:

  1. единый shell карточки внешнего контура
  2. двусторонняя доска Исходящие / Входящие

6. Архитектура должна остаться расширяемой

Следующий слой развития не ограничивается только внешними контурами.

Дальше в проекте могут появиться:

  • новые типы досок
  • агентные доски
  • специализированные мониторинговые представления
  • пользовательские рабочие поверхности под разные роли

Поэтому нельзя решать следующий этап только переобертками и точечными хаками.

Но и полный демонтаж текущего проекта ради абстрактной платформы тоже недопустим.

Рабочий принцип:

  • не ломать текущий runtime
  • не дублировать уже существующие механики без причины
  • выносить только те контракты, которые реально переиспользуются дальше

Что нужно решить перед продолжением

  • Что именно делает действие Принять:
    • только фиксирует решение источника
    • создает отдельную сущность во Внутреннем контуре
    • или переводит внешний запрос в отдельный внутренний режим без дублирования сущностей
  • Должен ли принятый запрос оставаться во Внешних контурах как историческая карточка, или он должен исчезать из рабочего списка и жить только во Внутреннем контуре
  • Нужен ли отдельный статус или отдельная вкладка для запросов, которые уже приняты во Внутренний контур
  • Должна ли коммуникация по комментариям быть полностью двусторонней, или source-side ответов достаточно только для возврата и уточнений
  • Нужно ли физически копировать файлы в source-side представление, или для PoC достаточно proxy-доступа к файлам целевой задачи
  • Нужно ли переводить обновление карточки с polling на realtime/push уже в следующем этапе, или polling пока приемлем
  • Нужны ли отдельные счетчики непрочитанных изменений по вкладкам Открытые и Завершенные
  • Должен ли отправитель после создания запроса иметь право менять только заголовок и описание, или еще и назначенного, срок, приоритет, метки
  • Нужно ли сохранять запрет на прямой переход в целевую задачу для пользователей без membership в target project как постоянное правило
  • Какой финальный lifecycle должен быть у запроса после возврата, принятия, завершения и отмены, чтобы source-side карточка не стала второй несогласованной системой учета

Обязательные требования

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
  • источник
  • цель
  • автора
  • временные метки

Пример:

{
  "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
  • детали берутся из целевой задачи
  1. Отдельная 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

Подробная поэтапная разработка описана в: