Newer
Older
gnexus-tasks / docs / TZ.md

Техническое задание: gntodo

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

Версия ТЗ 0.30
Дата 2026-09-21
Статус На обсуждении

1. Общие сведения

1.1. Назначение

Продвинутый личный таск-менеджер. Ключевая идея — минимальный трением ввод: задача закидывается в систему в одну строку, без выбора проекта, тегов и приоритета. Система сама делает предварительную детализацию, а пользователь позже утверждает или правит её при разборе.

1.2. Пользователи

  • Один пользователь (владелец).
  • Авторизация — через централизованный SSO-сервер auth.gnexus.space с клиентской библиотекой gnexus-gauth (см. 6.4).
  • Косвенные «пользователи» — ИИ-агенты, действующие от имени владельца через MCP.

1.3. Развёртывание

  • Собственный сервер (VPS), доступ из интернета.
  • HTTPS, реальный домен.
  • Данные хранятся только на своём сервере.

2. Сценарии использования

Сценарий А — веб-интерфейс (основной). Разбор стека входящих, детализация и утверждение задач, работа с проектами, планирование, просмотр дерева задач.

Сценарий Б — ИИ-агент через MCP. Агент от имени пользователя добавляет задачи (например, из переписки или диалога с LLM). Большинство AI-задач выполняется на стороне агента; сервер предоставляет MCP-интерфейс к данным.

3. Функциональные требования

3.1. Быстрый захват задач (стек входящих)

  • Задача создаётся одним текстом (заголовок). Выбор проекта, тегов, приоритета — не обязателен и не предлагается принудительно при вводе.
  • Такие «сырые» задачи попадают в стек входящих (raw) и ожидают детализации.
  • Стек — отдельное представление с количеством входящих, видимое с главного экрана.

3.2. Автоматическая предварительная детализация

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

  • теги — максимум 3, выбираются из существующего справочника; если подходящих нет, LLM может предложить 1–2 новых (создаются при утверждении);
  • проект — выбирается из открытых проектов с их описаниями (LLM видит заметку каждого проекта, чтобы соотнести задачу по смыслу); если ни один не подходит — краткое название нового проекта;
  • короткий заголовок — если исходный перегружен деталями, суть переносится в описание;
  • описание с нумерованными шагами — если шаги выполнения очевидны;
  • возможно, приоритет и оценка длительности.

Требования:

  • Это не окончательная детализация — промахи ожидаемы и нормальны.
  • При разборе задачи в стеке доступны варианты:
    1. «Да, всё верно» — принять предложенные метаданные одним действием;
    2. отредактировать — изменить предложенное вручную, затем утвердить.
  • Задача считается утверждённой (approved) только после явного действия пользователя.
  • Ответ LLM валидируется: строки-заглушки («NULL», пустые/пробельные, «n/a») отбрасываются, длина ограничивается, дубли тегов схлопываются; вне шкалы приоритет и длительность обнуляются.
  • Механизм предсказания — см. 3.11 и раздел открытых вопросов.

3.3. Содержание и редактирование задачи

  • Описание задачи — Markdown (редактирование с форматированием).
  • Вложения — изображения, в том числе вставка из буфера обмена (Ctrl+V прямо в редактор).
  • Отображение Markdown в описании (просмотр и редактирование).
  • Чекбоксы списков задач (- [ ] / - [x]) в отображаемом описании кликабельны: клик переключает пункт и сохраняет статус в markdown описания.
  • Инлайн-редактирование на странице задачи: каждое редактируемое поле правится прямо на месте (клик по значению → редактор на его месте, ✓/✗ или Esc); пустые поля тоже показываются («— не указано») и редактируются кликом. То же — на странице проекта (название, заметка, актуальность, приоритет). Полный режим правки (вся форма целиком) сохраняется наряду с инлайном.

3.4. Статусы, дедлайны, прогнозы, бюджет

Тип задачи: каждая задача имеет тип — разовая или регулярная (повторяющаяся; см. 3.5).

Статусы выполнения:

Статус Смысл
to_do — К выполнению Принята в работу, ожидает выполнения
in_progress — В работе Выполняется сейчас
done — Завершено (закрыто) Выполнена
cancelled — Отменено Была актуальной, затем перестала быть актуальной. Не равно удалению — задача сохраняется, т.к. может снова стать актуальной
deferred — Отложено На текущий момент не нужна или не в приоритете; возможно, позже это изменится
  • Статус cancelled и deferred — обратимы: задача может быть возвращена в to_do.
  • Удаление — отдельное явное действие, не статус.
  • Детализационный жизненный цикл (rawapproved) — отдельная плоскость, не статус выполнения: «сырая» задача из стека получает статус только после утверждения.

Дедлайны — двух видов:

  • строгий: «сделать до конкретной даты»;
  • нестрогий: «сделать в течение недели / месяца / года» — не привязан к конкретному дню, задаётся периодом.

Прогнозирование времени выполнения — система оценивает длительность задачи (на основе истории завершённых задач; алгоритм уточняется).

Бюджет — опциональный, на задачу; есть не у каждой задачи:

  • задаётся пользователем вручную (деньги и/или время);
  • рядом с бюджетом отображается оценка затрат по задаче, чтобы сразу видеть: задачу можно взять в работу или на неё не хватает денег.

3.5. Регулярные задачи

  • Отдельный тип задачи — регулярная (повторяющаяся) в противовес разовой.
  • Повторение создаёт новую задачу по правилу после выполнения/истечения предыдущей.
  • Точный набор правил повторения (ежедневно/еженедельно/интервалы) — уточняется.

3.6. Представления задач

  • Классический вид: список с фильтрами (проект, тег, статус, приоритет). Фильтр приоритета — по градациям шкалы 0-10 (очень низкий…срочный); задача без приоритета попадает в «очень низкий».
  • Пагинация: длинные списки (список задач, стек на главной, задачи проекта, проекты, архив) разбиваются на страницы по 30 элементов; навигация кнопками (‹ номера ›, с усечением «…» и подписью «Страница N из M»). Смена фильтров возвращает на первую страницу; при одной странице контрол не показывается.
  • Подзадачи показываются карточками внутри задачи и в списке; представление «дерево» убрано (проба 0.5 показала, что оно мешает — возможен возврат позже). Связь подзадачи с родителем (parent_task_id) в модели данных сохраняется.

3.7. Главная страница (дашборд + стек)

  • Главная совмещает два блока: дашборд активного сверху и стек входящих снизу.
  • Дашборд: «В работе», «Просрочено», дедлайны на неделю, «Следующие» (to_do по приоритету, топ-5); сайдбар — сводка по статусам и активные проекты с прогрессом.
  • Пустые секции дашборда не показываются; при отсутствии и активных, и проектов — нейтральное пустое состояние.

3.8. Проекты

  • Статус актуальности проекта (активен / приостановлен; «закрыт» выражается архивом, см. 3.8.1).
  • Приоритет проекта.
  • Заметка к проекту: Markdown-поле для ссылок на ресурсы проекта и прочего контекста; заметка — тот же «документ», что и описание задачи: в неё можно вставлять изображения из буфера (Ctrl+V).

3.8.1. Архив

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

  • Архивация — с подтверждением («Отправить проект и его N задач в архив?»).
  • Архивный проект пропадает из рабочих видов: списка проектов, фильтров, выдачи задачи (3.9); его задачи не видны в активных списках задач. Задачи живут и уезжают в архив только вместе с проектом: отдельной архивации/удаления для задач внутри проекта нет (удаление отдельной задачи остаётся — гигиена).
  • Статистика и XP не пересчитываются: закрытия в архивных проектах остаются в истории.
  • Страница «Архив» (отдельный раздел меню): история архивных проектов — открытие проекта, все задачи, заметка. Восстановление возвращает проект со всеми задачами и статусами как были. Доступно и «удалить навсегда».
  • У архивного проекта страница доступна на чтение (с плашкой «в архиве»); создание задач и правки спрятаны.

3.9. Выдача задачи (бывший режим «3 вариантов»)

Анти-прокрастинационный режим: пользователь указывает доступное время в часах (например, «3», можно 0.5), система предлагает подходящие задачи; предложение — те же карточки, что в списке задач.

  • Выбор кандидатов учитывает: прогнозируемую длительность ≤ доступного времени, приоритеты, статус актуальности проектов.
  • Варианты должны быть осмысленно разными (не дубликаты).
  • Отдельной кнопки выбора/выполнения на странице выдачи нет: пользователь открывает карточку задачи (переход несёт ?via=options) и берёт её в работу на странице задачи; закрытие задачи, открытой из выдачи, помечается «выбрал и сделал».

3.10. MCP-интерфейс

  • Собственный MCP-сервер как часть backend.
  • Инструменты (первичный набор, расширяется):
    • create_task — добавить задачу (достаточно текста; метаданные опциональны);
    • update_task, complete_task;
    • list_tasks — фильтры по проекту (id или имени), тегу, статусу, подстроке;
    • get_task — полное описание с вложениями;
    • list_projects / get_project — обнаружение проектов и восстановление контекста проекта (заметка проекта + его открытые задачи);
    • list_tags — справочник тегов (id для параметра tag_ids).
  • Эргономика для агентов (в т.ч. небольших моделей):
    • серверные instructions: порядок работы, правило привязки задач к проекту, восстановление контекста через get_project после перерыва, запрет придумывать id, автоматика наград/спавна при закрытии;
    • адресация проекта по имени: параметры project_name (регистронезависимо) в create_task/update_task/list_tasks наряду с project_id;
    • описания параметров в схеме каждого инструмента (enum значений, форматы дат, диапазоны приоритета);
    • ошибки подсказывают следующий шаг («call list_projects()», «найдите id через list_tasks(query=...)»); ответ create_task без проекта содержит подсказку.
  • Аутентификация агентов — через SSO-механизм (токен, выданный централизованной системой; детали после предоставления данных SSO).
  • Агент действует от имени пользователя; отдельной мультитенантности нет.
  • Закрытие задачи агентом (update_task/complete_task) идёт по тому же общему пути, что и в UI: спавн регулярной, XP, монеты, растение (3.5, 3.13); в открытых вкладках — скромный тост о награде (3.14).

3.11. Локальные AI-функции

  • Автодетализация (3.2) выполняется маленькой LLM, запущенной локально через Ollama:
    • модель и параметры — конфигурацией приложения, без зашивки в код;
    • LLM классифицирует текст задачи: предлагает теги (из справочника или новые), проект по описаниям открытых проектов, короткий заголовок, описание с шагами, приоритет;
    • результат — черновые метаданные для утверждения (3.2), не окончательное решение.
  • Все вызовы LLM — на собственном сервере, данные не покидают VPS.
  • Спекулярные LLM-сценарии вне метаданных — не в скоупе: большинство ИИ-задач выполняют внешние агенты через MCP (3.10).

3.12. Мультиязычность

  • UI поддерживает три языка: ru (базовый/fallback), en, uk.
  • Язык по умолчанию берётся из gnexus auth (profile.locale из SSO-профиля, scope profile).
  • В «Настройках» возможно ручное переопределение языка; значение хранится в глобальных настройках приложения (app_settings, ключ language), пустое значение = следовать SSO.
  • Даты, суммы и названия дней недели форматируются через Intl по активной локали.
  • Переводится только собственный UI: gnexus-ui-kit текстов не содержит (тексты через props).

3.13. Геймификация

Маленькая дополнительная награда за выполнение задач — мотивация без негативных последствий. Принцип только позитив: XP только начисляется, ничего не сгорает и не отнимается; стрики/серии (которые «ломаются» при пропуске) не используются.

  • XP за закрытие задачи: база 10 + бонус за приоритет (0–15) + бонус за объём по оценке времени (0–15). Начисление — один раз на задачу (идемпотентно); удаление задачи не отнимает заработанное. Хранение — таблица xp_events (поле kind разделяет события: task — закрытие, create_task / create_project — создание).
  • Микронаграды за создание (без конфетти — скромный тост «+N XP • +M монет»): создание задачи — +2 XP и +1 монета, создание проекта — +5 XP и +2 монеты. В суммарный опыт (уровень) входят, растений в саду не рождают, счётчик закрытых задач не увеличивают; хранятся с task_id = NULL — удаление задачи или проекта награду не отнимает.
  • Ежедневная награда за визит: при открытии приложения фронт запрашивает POST /api/xp/daily — раз в сутки (граница дня UTC) начисляется 50 монет (только монеты, XP нет), повторные визиты в те же сутки молча пропускаются. Тост «+50 монет» только в день первого визита.
  • Уровень: растёт из суммарного XP (уровень не падает); прогресс до следующего уровня и название звания показываются в «Саду». Звания ботанические (Росток, Сеянцев, Садовник, … Легенда сада — 13 званий; порог уровня L = 100·L·(L−1)/2 XP). Дерево уровней — модалка со списком всех уровней: звание, порог XP, что открывается (виды растений с ценой семени и premium-пометкой, расширения карты); пройденные отмечены, текущий подсвечен.
  • Момент награды: при закрытии задачи — короткая конфетти-анимация и тост «+N XP» с похвалой. Особые закрытия (редкое растение, крупная задача) — усиленное «золотое» конфетти.
  • Сад (отдельная страница): живая сцена — графическое представление сада с домиком в центре; вокруг сад на мелкой сетке (ячейка ~20px, привязка при перемещении, наложения разрешены). Каждая закрытая задача — растение в саду; сад только растёт, продавать и удалять растения нельзя. Растения и декорации можно перетаскивать (drag&drop). Рядом — уровень, кошелёк (баланс монет), «последний росток» (что и когда закрыто последним), история по месяцам (12 месяцев, столбики) и ачивки.
    • Отрисовка сцены — пиксель-арт на PixiJS 8 (WebGL): nearest масштабирование без сглаживания, целочисленный «нативный пиксель» (матрицы 16px × 2 = 32px на клетку). Все спрайты (тайлы травы/дикой земли, изгородь, домик, 13 видов растений × 3 стадии, декорации, кольца редкости, блёстки) генерируются из пиксель-матриц прямо в коде — внешних файлов-ассетов нет. Рендерер (src/game/GardenRenderer.ts) — обычный класс, не оборачивается во Vue-reactive (deep-прокси ломает внутренние identity-проверки Pixi); Pixi загружается динамическим импортом (отдельный чанк). Инвентарь, поповер и drag-ghost — DOM поверх канваса.
  • Две награды: опыт и монеты. Опыт — «ранг садовника»: только растёт, ничего не открывает в магазине напрямую. Монеты — «валюта сада»: тратятся. Общий принцип: контент открывается за опыт, покупается за монеты — опыт (уровень) открывает виды растений и землю, монеты покупают рост растений, декорации и расширения карты.
  • Монеты: начисляются при закрытии задачи — floor(xp / 2) (заголовок X-Earned-Coins рядом с XP в тосте), и бонусом 25 × L при достижении уровня L. Хранение — таблица coin_events (журнал заработка и трат; баланс = сумма amount). Траты — отрицательные события (source = shop); продажи нет («только позитив»).
  • Редкие растения: редкость решается в момент закрытия по весу задачи — чем больше XP, тем выше шанс редкого; эпик-растения — только у крупных закрытий. Редкость хранится в xp_events, визуально — золото + бейдж.
  • Растения и виды: растение рождается только от закрытой задачи (отпечаток работы), вид выбирается детерминированно из пула видов, открытых уровнем на момент рождения (premium-виды — только для rare/epic закрытий), и фиксируется за растением (garden_items.item_key) — открытые позже виды не перерисовывают старые растения. Растение привязано к событию XP (переживает удаление задачи).
  • Семена растений (покупка видов за монеты): в маркете блок «Семена растений» — открытые уровнем виды продаются семенами (цены 30–1200 по «дороговизне» вида; 13 видов, открытие растянуто по уровням 1–13 — прогрессия рассчитана примерно на 300 закрытых задач при среднем ~26 XP за закрытие). Покупка кладёт растение-росток в инвентарь (как декорации); перетаскивание из инвентаря на свободную клетку сажает его. Размещённое семя обратно в инвентарь вернуть нельзя (сад только растёт); редкость — common, задача-родитель отсутствует. Доступность семени — по уровню вида (🔒 «откроется на уровне N»), независимо от premium-флага вида (вопрос о premium-видах в семенах — открыт, см. раздел 8).
  • Рост растений за монеты: растение растёт стадиями росток → куст → цветение, каждая стадия покупается монетами (цена по редкости: common 20/50, rare 40/100, epic 80/200). Автороста по времени нет.
  • Маркет сада: в модалке — расширения карты (первым блоком), декорации, семена растений и каталог видов (справка о редкости). У каждой покупки три состояния: 🔒 «откроется на уровне N» (если уровень не открывает), цена золотом (кнопка активна), цена серым + «не хватает N монет».
    • Декорации — чисто косметика: фонарь, лавочка, поилка, пруд, беседка, флюгер, скворечник, садовый самоцвет, теплица (уникальные), изгородь, клумба и куст (повторяемые). Двигаются как растения. Изгородь — самосоединяющиеся секции: текстура выбирается по маске соседей (N/E/S/W), секция соединяется только с соседними секциями изгороди. Постройки в изометрии (домик, теплица, беседка) — крупная изометрия 2:1 (домик с двором, теплица со стеклянными стенами и каркасом, беседка с площадкой у входа). Дорожки убраны (не прижились — сложность рендера и соединений).
    • Подпись выбранного объекта: клик по любому объекту сада (растение или декорация) показывает у клетки чип с иконкой и названием («Скворечник», «Куст», «Подсолнух»); у растений одновременно открывается поповер роста. Повторный клик по объекту или клик по пустому месту снимает выбор.
    • Инвентарь декораций: покупка кладёт декорацию в инвентарь под картой (garden_items.x/y = NULL) — место покупки всегда видно пользователю. Из инвентаря декорация перетаскивается на карту; перетаскивание размещённой декорации обратно на полосу инвентаря убирает её с карты (растения в инвентарь вернуть нельзя — сад только растёт).
    • Расширения карты: стартовая сетка 32×20 ячеек; каждое расширение (+8 клеток периметра) открывается уровнем (I — ур. 3, II — ур. 5, III — ур. 8, IV — ур. 9, V — ур. 11) и покупается монетами (100/250/500/750/1000). Финал ~72×60.
  • Ачивки с тирами: у каждой ачивки ступени I/II/III (например, 10/50/100 задач), прогресс к следующей ступени виден всегда. Набор: вехи закрытий, уровни, макс. задач за день, разные проекты, суммарные часы, строгие дедлайны, закрытия через выдачу задачи (см. 3.9), регулярная, проект.
  • Связка с выдачей задачи (3.9): закрытие задачи, открытой из выдачи, помечается (earned_via) и празднуется меткой «выбрал и сделал» + счётчик-ачивкой; XP при этом не меняется.
  • Страница «Статистика»: закрываемость за выбранный день / неделю / месяц (период листается стрелками назад/вперёд). Метрики — закрытые задачи, XP, созданные задачи, часы работы, «дни с результатом» — каждая со сравнением с предыдущим аналогичным периодом (дельта и проценты). Анимированный сравнительный график закрытых задач по бакетам периода (часы / дни недели / дни месяца): текущий и предыдущий период — пары столбиков. Сетка активности «как в гитхабе» за полгода или год (переключатель диапазона; цвет по закрытым задачам или XP, переключается). Данные считаются из xp_events и дат задач, без новых эндпоинтов.
  • Метка «ментально сложная»: у незакрытой задачи есть кнопка-переключатель «Не хочется делать» (warning-стиль) — она ставит метку «ментально сложная»: трудность не по объёму, а из-за требуемых волевых усилий. Метку можно снять до закрытия, после закрытия она не меняется. Закрытие такой задачи даёт +10 XP (сила воли) и всегда празднуется золотым конфетти; ачивка «Преодоление» (5/25/50 закрытых «ментально сложных») — в саду.
  • Справка «О саде»: кнопка на странице сада открывает модалку с объяснением механик (XP, уровни, растения и редкости, ачивки, принцип «только позитив»).

3.14. Реактивность: серверные события (SSE)

Данные меняются не только из UI: MCP-агенты (3.10) и фоновая автодетализация (3.2) пишут в БД вне HTTP-запроса. Все виды обновляются событиями от сервера — без обновления страницы и переходов между страницами.

  • Эндпоинт: GET /api/events (авторизация штатная, 401 — на вход). Транспорт — SSE (text/event-stream), по одному соединению на вкладку (EventSource, авто-reconnect браузером). Keep-alive: при тишине дольше 20 с сервер шлёт кадр ping, чтобы прокси (Vite dev, nginx) не рвал поток.
  • Модель — грубозернистые события: событие это kind + опциональные данные; фронт реагирует refetch'ем (перечитывает данные целиком), а не патчами. Трейлинг-debounce 300 мс коалесцирует бёрсты (закрытие задачи = 2–3 события). Виды подписываются на свои kind'ы: стек/список — task.changed, task.deleted, detail.changed, project.changed, project.deleted; статистика — xp.changed, task.changed; сад — garden.changed, xp.changed, task.changed (рефetch подавляется на время drag по сцене); страница задачи — перечитывается при task.changed/detail.changed своего id.
  • Точки публикации (строго после коммита транзакции): HTTP-хендлеры задач, проектов, сада, XP-дейли и настроек; MCP-инструменты и фоновая детализация — broadcast (всем вкладкам). Список kind'ов: task.changed {id}, task.deleted {id}, detail.changed {id}, project.changed {id}, project.deleted {id}, garden.changed {reason}, xp.changed {amount?, celebrate}, settings.changed, ready (первый кадр), ping. Упрощение: закрытие задачи через MCP не шлёт garden.changed — растение создаётся лениво, refetch по task.changed покрывает.
  • Дедуп XP-тостов: действие своей вкладки празднуется по заголовкам ответа (X-Earned-XP, ТЗ 3.13); SSE-эхо и эхо соседней вкладки молчат — окно активности 3 с (localStorage). Соседние вкладки показывают скромный тост «+N XP» без конфетти.
  • Reconnect: при обрыве — backoff 1→2→5→15 с; 401 при проверке сессии — редирект на вход; после переподключения — форс-рефреш всех открытых видов (данные за время разрыва могли измениться).

3.15. PWA

Приложение устанавливается на устройство как приложение (Chrome/Android; вопрос оффлайн-режима данных — открытый вопрос 8.4, пока приложение всегда онлайн).

  • Манифест: standalone, тёмная палитра кита (#16161e — фон и theme-color, чтобы не мигало белым при запуске и не зеленела шапка окна), иконки 192/512 + maskable-512, id/start_url = /, язык ru.
  • Service Worker (vite-plugin-pwa, autoUpdate): precache оболочки — собранные ассеты, шрифты/иконки кита (~6 МБ лимит), /api/*, /auth/*, /mcp/* никогда не кэшируются и не получают fallback на index.html.
  • Оффлайн-оболочка: при отсутствии сети SW отдаёт оболочку приложения (SPA-fallback) — интерфейс открывается, данные при этом недоступны (запросы к API не кэшируются). Вложения и статические ассеты — CacheFirst.
  • Обновление: новая версия подхватывается автоматически при следующем визите (autoUpdate); SSE-соединение при обновлении рвётся — reconnect покрывает (3.14).
  • Установка с телефона: требует secure context — при доступе по LAN по HTTP (не localhost) браузер SW не зарегистрирует; нужен HTTPS (M7 Docker/nginx).
  • Dev-режим: SW не включён (devOptions выключен) — PWA проверяется на прод-сборке (dist), не на dev-сервере.

4. Нефункциональные требования

Требование Значение
Архитектура Клиент-серверное; SPA + REST API + MCP
Фронтенд SPA на Vue 3 с gnexus-ui-kit (npm: gnexus-ui-kit@^0.4.0, peer: Vue ^3.4)
Бэкенд Python (FastAPI — предположительно), клиент SSO — gnexus-gauth
СУБД PostgreSQL (рекомендация для VPS)
Авторизация SSO через auth.gnexus.space, библиотека gnexus-gauth (https://git.gnexus.space/git/root/gnexus-auth-client-py.git)
Хостинг VPS, HTTPS
AI Ollama на сервере; модель задана конфигом
Упаковка В итоге всё пакуется в Docker (docker-compose: API, PostgreSQL, фронт, Ollama + модель)
Мобильность На старте — только PWA; Android-приложение — вне скоупа стартовой версии (вернуться к нему позже)
Приватность Все данные и LLM-вызовы — на собственном сервере
Реактивность SSE (/api/events): грубозернистые события + refetch, см. 3.14
PWA манифест + SW (precache оболочки, autoUpdate), оффлайн-оболочка без кэша API, см. 3.15

Внешние зависимости проекта (не форкать, обновлять через пакетный менеджер):

  • gnexus-ui-kit — часто обновляется, использовать только публичный API кита;
  • gnexus-gauth — клиентская библиотека SSO.

5. Модель данных (черновик)

Task
  id, title
  description      markdown — живёт в Document (owner_type = task)
  task_type         one_time | recurring          — тип задачи: разовая / регулярная
  status            to_do | in_progress | done | cancelled | deferred
  detail_state      raw | approved                — плоскость детализации (стека)
  parent_task_id    nullable  — дерево подзадач
  project_id        nullable
  tag_ids           []
  priority          nullable  (заполняется автодетализацией / вручную)
  deadline          nullable  — дедлайн:
                        strict  { date }                  — «до конкретной даты»
                        soft    { period: week|month|year } — «в течение периода»
  recurrence        nullable  — правило повторения (для task_type = recurring)
  time_estimate     nullable  — прогноз времени (система)
  budget            nullable  — ручной бюджет (деньги и/или время), опционален
  estimated_cost    nullable  — оценка затрат по задаче (сравнивается с бюджетом)
  actual_time       nullable  — фактические затраты (для обучения прогноза)
  created_at, approved_at, done_at

Project
  id, name
  relevance_status  active | paused               — статус актуальности
  is_archived       bool — архив (3.8.1): проект и его задачи скрыты
                    из рабочих видов, восстановимы из «Архива»
  priority
  note              markdown — живёт в Document (owner_type = project):
                    ссылки, контекст, картинки

Tag           — справочник тегов
Document      — markdown-текст с полиморфной привязкой к владельцу:
                owner_type (task | project), owner_id, body (у задачи —
                описание, у проекта — заметка); document всегда один на владельца
Attachment    — файлы документов (изображения), document_id, mime.
                URL скачивания файла неизменен: /api/attachments/{id}/file —
                он зашит в сохранённый markdown-текст

XpEvent       — начисление XP за закрытую задачу (идемпотентно по task_id):
                amount, rarity (common | rare | epic), via_options

CoinEvent     — журнал монет сада (заработок и траты; баланс = Σ amount):
                task_id (nullable), level (nullable — бонус уровня),
                source (task | level | shop), amount (+/−), item_key (ключ
                покупки для трат), created_at

GardenItem    — элемент сцены сада: kind (plant | decoration),
                ref_id (→ xp_events для растений; уникально в паре с kind),
                item_key (вид растения / ключ декорации), x, y (ячейки сетки),
                stage (0 росток, 1 куст, 2 цветение)

История завершённых задач (фактическое время) — источник для прогнозирования длительности.

6. Архитектура (черновик)

┌─────────────┐     ┌────────────────────── VPS (docker-compose) ─────────────┐
│  Web SPA    │────▶│  API (FastAPI) ──▶ PostgreSQL                           │
│  Vue 3 +    │     │   ▲    │                                                │
│  gnexus-    │     │   │    ├──▶ Сервис автодетализации ──▶ Ollama (модель    │
│  ui-kit     │     │   │    │      — LLM, модель из конфига)                  │
└─────────────┘     │   │    ├──▶ Хранилище вложений (файлы)                   │
      ▲             │   │    └──▶ MCP-сервер (для ИИ-агентов)                  │
      └─ SSE ───────┤ шина событий (realtime)                                  │
                    └─────────────────────────────────────────────────────────┘
                                     ▲ SSO auth.gnexus.space (клиент gnexus-gauth)
  • API и MCP-сервер — одно Python-приложение (общая бизнес-логика).
  • Вложения — файлы на диске VPS + метаданные в БД.
  • Изменения данных публикуются в шину событий и уходят в SPA по SSE (3.14).

7. Этапы разработки (предложение)

Этап Содержание
M0 — каркас Репозиторий, скелет backend + frontend, SSO-интеграция (gnexus-gauth), деплой на VPS
M1 — MVP задач CRUD задач, быстрый ввод, стек входящих, теги, проекты (базово), ручная детализация
M2 — детализация Интеграция Ollama + модель из конфига, автопредзаполнение метаданных, подтверждение/редактирование, Markdown-редактор, вложения из буфера
M3 — структура Подзадачи (parent_task_id), классический список с фильтрами, заметки проектов
M4 — умность Прогнозирование времени, бюджет, выдача задачи
M5 — MCP MCP-сервер, инструменты для агентов
M6 — мобильность PWA (Android-приложение — позже, вне стартового скоупа)
M7 — упаковка Docker (docker-compose: API, PostgreSQL, фронт, Ollama + модель)

Порядок M4/M5 может меняться — MCP можно поднять раньше ради ИИ-сценария.

8. Открытые вопросы

  1. Правила повторениярешено 2026-09-19: три правила — интервал N дней, дни недели (ISO), день месяца (без дня — последний); якорь — фиксированный календарь от даты выполнения; новый экземпляр рождается при завершении предыдущего.
  2. Прогнозирование временирешено 2026-09-19: оценка длительности приходит из LLM-детализации (или задаётся вручную); точность не требуется — оценка нужна, чтобы отсекать заведомо большие задачи при малом доступном времени.
  3. Оценка затрат к бюджетурешено 2026-09-19: оба поля (бюджет и оценка затрат) — ручные; валюта — глобальная настройка, выбирается один раз и применяется всюду (UAH, USD, EUR, GBP, PLN).
  4. Оффлайн-режим в PWA: нужен ли, или всегда онлайн?
  5. Модель для Ollama: какая конкретно модель и параметры (в конфиг, но нужно выбрать для проверки M2).
  6. Практическое различие cancelled / deferred: определения зафиксированы (3.4), но поведение в интерфейсе почти одинаковое — скрыть из активных списков и оставить доступным для возврата. Уточнить при проектировании представлений, нужны ли оба статуса или их поведение сольётся.
  7. Анти-дюп награды за статусрешено 2026-09-21: закрытие (HTTP и MCP) идёт через общий путь; XP — один раз на задачу (grant_task_xp), спавн регулярной — один раз на цепочку (метка spawned_at), выход из done сбрасывает done_at. Повторные закрытия и обновления закрытой не дублируют награды и экземпляры — покрыто тестами.
  8. Пиксель-арт сцена садарешено 2026-09-20: сцена переведена на пиксель-арт (PixiJS 8, WebGL); спрайты генерируются из пиксель-матриц в коде (без внешних ассетов и лицензий), см. 3.13.
  9. Premium-виды в семенах: premium-виды (сейчас кактус) рождаются только из rare/epic закрытий — «отпечаток крупной работы». Семена же продаются за монеты и дают common-растение; сейчас семя premium-вида купить можно. Оставить ли покупку семян premium-видов (простой доступ к виду) или запретить (эксклюзив rare/epic сохраняется) — решить.
  10. Самосоединяющийся забор: секции изгороди автоматически соединяются с соседними секциями (маска соседей N/E/S/W → текстура); ручного поворота нет. Соединяются только соседние секции забора — диагонали не считаются. Подтвердить, что поведение устраивает.