diff --git a/docs_prod/cross-project-task-routing/README.md b/docs_prod/cross-project-task-routing/README.md new file mode 100644 index 0000000..92eba27 --- /dev/null +++ b/docs_prod/cross-project-task-routing/README.md @@ -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) diff --git a/docs_prod/cross-project-task-routing/phase-roadmap.md b/docs_prod/cross-project-task-routing/phase-roadmap.md new file mode 100644 index 0000000..8768762 --- /dev/null +++ b/docs_prod/cross-project-task-routing/phase-roadmap.md @@ -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.