diff --git a/backend/app/api/tasks.py b/backend/app/api/tasks.py index b69d385..c8e77f6 100644 --- a/backend/app/api/tasks.py +++ b/backend/app/api/tasks.py @@ -117,10 +117,12 @@ background: BackgroundTasks, response: Response, ) -> dict[str, int]: - """Быстрый захват: достаточно title — задача попадает в стек (raw, to_do). + """Быстрый захват: достаточно title — задача создаётся сырой (raw, to_do). С parent_task_id — создание подзадачи (M3). Сразу в фоне запускается - автодетализация (LLM-предложение метаданных). + автодетализация (LLM-предложение метаданных) — она идёт для любой сырой + задачи; в стек входящих (3.1) попадают только задачи без проекта, но + детализация от этого не зависит. """ _validate_parent(db, None, schema.parent_task_id, user_id) task = Task( diff --git a/backend/app/services/detailing.py b/backend/app/services/detailing.py index 8ecd678..50dc5fc 100644 --- a/backend/app/services/detailing.py +++ b/backend/app/services/detailing.py @@ -439,7 +439,7 @@ def detail_task(task_id: int) -> None: - """Фоновая работа: сгенерировать и сохранить предложение для задачи в стеке. + """Фоновая работа: сгенерировать и сохранить предложение для сырой задачи. Теги предлагаются всегда — они ДОПОЛНЯЮТ назначенные, поэтому существующие теги задачи уходят в промпт контекстом. Приоритет и оценка — только если поля diff --git a/docs/TZ.md b/docs/TZ.md index 31064b4..a1b325b 100644 --- a/docs/TZ.md +++ b/docs/TZ.md @@ -4,7 +4,7 @@ | | | |---|---| -| Версия ТЗ | 0.94 | +| Версия ТЗ | 0.95 | | Дата | 2026-10-10 | | Статус | На обсуждении | @@ -47,12 +47,20 @@ - Задача создаётся одним текстом (заголовок). Выбор проекта, тегов, приоритета — **не обязателен** и не предлагается принудительно при вводе. - **Массовое добавление (0.39)**: после сохранения полной формы создания она не закрывается, а очищается (выбранный проект сохраняется, фокус в заголовок) — можно вводить следующую задачу. Страница за формой обновляется (глобальный «+» с любой страницы, кроме страницы задачи, переводит её к созданной задаче). - **Проект из контекста**: на странице проекта новая задача по умолчанию относится к нему; на странице задачи — к её проекту (подзадачи наследуют проект родителя). -- Такие «сырые» задачи попадают в стек входящих (`raw`) и ожидают детализации. +- Такие задачи создаются «сырыми» (`raw`) и ожидают детализации. +- **В стек попадают только задачи без проекта** (0.95): задача, созданная сразу в + проекте (страница проекта, подзадача, агент через MCP), уже получила контекст от + владельца — она не «входящая». Стек — стопка разбора для того, что захвачено + на бегу и ещё ни к чему не отнесено. Такие задачи никуда не пропадают: они видны + на странице своего проекта, автодетализация для них идёт как обычно, а предложение + ИИ ждёт на странице самой задачи. - Стек — отдельное представление с количеством входящих, видимое с главного экрана. ### 3.2. Автоматическая предварительная детализация -При попадании задачи в стек система самостоятельно предлагает черновые метаданные. +При создании задачи система самостоятельно предлагает черновые метаданные — независимо +от того, попадёт ли задача в стек: задача, созданная сразу в проекте, детализируется так +же, просто ждёт разбора не в стопке входящих, а на своей странице. Состав предложения (решение 2026-10-10, 0.93): - **теги** — максимум 3: подходящие из существующего справочника или новые; @@ -80,7 +88,7 @@ приоритет и оценка запрашиваются только у пустых полей; теги — всегда. «Переспросить ИИ» (redetail) сбрасывает текущее предложение и спрашивает заново по **текущему** тексту задачи — то же правило пустых полей действует и там. -- При разборе задачи в стеке доступны варианты: +- При разборе задачи в стеке (карточка стека — 3.7) доступны варианты: 1. **«Да, всё верно»** — принять предложенные метаданные одним действием (теги **добавляются** к назначенным, пользовательские не снимаются, заполненные приоритет и оценка остаются как есть); @@ -302,13 +310,24 @@ ### 3.7. Главная страница (дашборд + стек) - Главная совмещает два блока: **дашборд активного** сверху и **стек входящих** снизу. +- В стеке — только задачи без проекта (правило 0.95, см. 3.1). - Дашборд: «В работе», «Просрочено», дедлайны на неделю, «Следующие» (to_do по приоритету, топ-5); сайдбар — сводка по статусам и активные проекты с прогрессом. - Пустые секции дашборда не показываются; при отсутствии и активных, и проектов — нейтральное пустое состояние. - Карточки стека раскладываются **сеткой по три в ряд** (0.59): на узких экранах — - две и одна (ломающиеся точки 1080 и 720px), карточки разной высоты выравниваются - по верху, а не растягиваются в ряду; скелетон загрузки повторяет ту же сетку. + две и одна (ломающиеся точки 1080 и 720px); скелетон загрузки повторяет ту же + сетку. Карточки ряда — **одной высоты** (0.95; в 0.59 они выравнивались по верху, + и кнопки утверждения плясали между соседями): карточка тянется по высоте ряда, + а блок предложения ИИ с кнопками прижат к низу — бейджей у задач разное число, + без этого кнопки встают на разной высоте. +- **Карточка стека — обычная карточка задачи** (0.95): тот же компонент `TaskCard`, + что в списке задач и в выдаче, — заголовок-ссылка на задачу (без принудительного + аперкейса), сниппет описания, бейджи задачи, подвал «свежесть» и «⋯»-меню. Своё у + стека одно: предложение автодетализации бейджами и кнопки **«Да, всё верно»** и + **«Детализировать»**, а в «⋯» добавляется **«Переспросить ИИ»** (её место — там, + где живут остальные действия задачи). Бейдж «в стеке» и абсолютная дата создания + из карточки ушли: и то и другое дублировало место карточки и её подвал. ### 3.8. Проекты @@ -542,6 +561,10 @@ - Выбор кандидатов учитывает: прогнозируемую длительность ≤ доступного времени, приоритеты, статус актуальности проектов. - Варианты должны быть осмысленно разными (не дубликаты). +- Карточек в выдаче не больше трёх, и раскладываются они **в ряд по три** (0.95; + просили «давай 3 в ряд»): сетка та же, что у стека входящих (3.7), — весь ответ + ложится одной строкой, а на узких экранах сжимается до двух и одной (те же + ломающиеся точки 1080 и 720px). - Отдельной кнопки выбора/выполнения на странице выдачи нет: пользователь открывает карточку задачи (переход несёт `?via=options`) и берёт её в работу на странице задачи; закрытие задачи, открытой из выдачи, помечается «выбрал и сделал». ### 3.10. MCP-интерфейс @@ -1219,7 +1242,8 @@ - **Заголовок-ссылка в карточке — не классом `card-title`** (0.59): `card-title` — имя шапки карточки в ките (`header.card-title`, у него `padding: 15px 15px 0`); тот же класс на вложенной ссылке давал вторые 15px, и текст заголовка уезжал - вправо от остального содержимого. Ссылка стека носит собственный `card-link`. + вправо от остального содержимого. Карточка задачи (`TaskCard` — список, выдача и + стек с 0.95) носит ссылку классом `.title`, карточка проекта в архиве — `card-link`. - **Селектор цвета проекта — сырой блок в стиле кита** (0.63): в ките компонента выбора цвета нет (проверено: `GnChip`/`GnChipGroup`/`GnPopover`/`GnDropdown`/ `GnRadioGroup`/`GnRange` цвета не принимают), а `GnPopover` оборачивает @@ -1748,7 +1772,7 @@ | M5 — MCP | MCP-сервер, инструменты для агентов | | M5+ — мандат агента | Доступность задачи для ИИ-агента, взятие в работу (аренда), приёмка работы, журнал `task_events` (0.85, 3.20) | | M6 — мобильность | PWA (Android-приложение — позже, вне стартового скоупа) | -| M6+ — уведомления | Системные уведомления (Web Push): подписки устройств, ключи VAPID, блок настроек, работа агента в закрытом приложении (0.88, 3.21). Напоминания: дедлайны, ритм регулярных задач, утренняя сводка, тихие часы (0.89, 3.21). Регулярные задачи: дата следующего экземпляра у клона, метка в карточке, фильтр «Регулярные» (0.91, 3.5). Импорт задачи из ссылки на багрепорт BugTrail — в форме задачи и в попапе расширения (0.92, 3.22). Автодетализация переведена на теги, приоритет и оценку времени — заголовок и описание ИИ не предлагает (0.93, 3.2). Журнал и шапка списка приспособлены к телефону, «Кто создал» стал переключателем (0.94, 3.20, 3.6) | +| M6+ — уведомления | Системные уведомления (Web Push): подписки устройств, ключи VAPID, блок настроек, работа агента в закрытом приложении (0.88, 3.21). Напоминания: дедлайны, ритм регулярных задач, утренняя сводка, тихие часы (0.89, 3.21). Регулярные задачи: дата следующего экземпляра у клона, метка в карточке, фильтр «Регулярные» (0.91, 3.5). Импорт задачи из ссылки на багрепорт BugTrail — в форме задачи и в попапе расширения (0.92, 3.22). Автодетализация переведена на теги, приоритет и оценку времени — заголовок и описание ИИ не предлагает (0.93, 3.2). Журнал и шапка списка приспособлены к телефону, «Кто создал» стал переключателем (0.94, 3.20, 3.6). В стек идут только задачи без проекта, карточка стека собрана из обычной карточки задачи (карточки ряда одной высоты), выдача раскладывается тремя карточками в ряд (0.95, 3.1, 3.7, 3.9) | | M7 — упаковка | Docker (docker-compose: API, PostgreSQL, фронт, Ollama + модель) | Порядок M4/M5 может меняться — MCP можно поднять раньше ради ИИ-сценария. diff --git a/frontend/src/components/TaskCard.vue b/frontend/src/components/TaskCard.vue index 7f4591b..b74b2cc 100644 --- a/frontend/src/components/TaskCard.vue +++ b/frontend/src/components/TaskCard.vue @@ -21,6 +21,8 @@ showProject?: boolean /** Параметры запроса у ссылок на задачу (например { via: 'options' }) */ linkQuery?: Record + /** Свои пункты меню «⋯» — перед «Открыть» (стек добавляет «Переспросить ИИ», 0.95) */ + menuExtra?: { label: string; icon?: string; danger?: boolean; onSelect: () => void }[] }>() const emit = defineEmits<{ @@ -88,6 +90,7 @@ }, }, { label: t('common.open'), icon: 'ph-arrow-square-out', onSelect: () => open(task.id) }, + ...(props.menuExtra ?? []), { label: t('common.delete'), icon: 'ph-trash', danger: true, onSelect: () => emit('delete', task) }, ] } @@ -166,6 +169,10 @@
+ +