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

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

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

---

## 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. Автоматическая предварительная детализация

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

- теги — выбираются из существующего справочника тегов;
- проект или категорию;
- возможно, приоритет.

Требования:

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

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

- Описание задачи — **Markdown** (редактирование с форматированием).
- Вложения — изображения, в том числе **вставка из буфера обмена** (Ctrl+V прямо в редактор).
- Отображение Markdown в описании (просмотр и редактирование).

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

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

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

| Статус | Смысл |
|---|---|
| `to_do` — К выполнению | Принята в работу, ожидает выполнения |
| `in_progress` — В работе | Выполняется сейчас |
| `done` — Завершено (закрыто) | Выполнена |
| `cancelled` — Отменено | Была актуальной, затем перестала быть актуальной. **Не равно удалению** — задача сохраняется, т.к. может снова стать актуальной |
| `deferred` — Отложено | На текущий момент не нужна или не в приоритете; возможно, позже это изменится |

- Статус `cancelled` и `deferred` — обратимы: задача может быть возвращена в `to_do`.
- Удаление — отдельное явное действие, не статус.
- Детализационный жизненный цикл (`raw` → `approved`) — **отдельная плоскость**, не статус выполнения: «сырая» задача из стека получает статус только после утверждения.

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

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

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

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

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

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

- **Классический вид**: список с фильтрами (проект, тег, статус, приоритет).
- Подзадачи показываются карточками внутри задачи и в списке; представление
  «дерево» убрано (проба 0.5 показала, что оно мешает — возможен возврат позже).
  Связь подзадачи с родителем (`parent_task_id`) в модели данных сохраняется.

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

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

### 3.8. Проекты

- Статус **актуальности** проекта (активен / приостановлен / закрыт).
- **Приоритет** проекта.
- **Заметка к проекту**: Markdown-поле для ссылок на ресурсы проекта и прочего контекста.

### 3.9. Режим выбора («3 варианта»)

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

- Выбор кандидатов учитывает: прогнозируемую длительность ≤ доступного времени, приоритеты, статус актуальности проектов.
- Варианты должны быть осмысленно разными (не три дубликата).
- После выбора — прямой переход к выполнению задачи (отметка начала, быстрый доступ к описанию).

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

- Собственный **MCP-сервер** как часть backend.
- Инструменты (первичный набор, расширяется):
  - `create_task` — добавить задачу (достаточно текста; метаданные опциональны);
  - `update_task`, `complete_task`;
  - `list_tasks` / `search_tasks` — фильтры по проекту, тегу, статусу;
  - `get_task` — полное описание с вложениями.
- Аутентификация агентов — через SSO-механизм (токен, выданный централизованной системой; детали после предоставления данных SSO).
- Агент действует от имени пользователя; отдельной мультитенантности нет.

### 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`.
- **Уровень**: растёт из суммарного XP (уровень не падает); прогресс до следующего
  уровня и **название звания** показываются в «Саду». Звания ботанические
  (Росток, Сеянцев, Садовник, … Легенда сада — 10 званий).
- **Момент награды**: при закрытии задачи — короткая конфетти-анимация и тост
  «+N XP» с похвалой. Особые закрытия (редкое растение, крупная задача) —
  усиленное «золотое» конфетти.
- **Сад** (отдельная страница): каждая закрытая задача — растение на грядке;
  сад только растёт. Рядом — уровень, **«последний росток»** (что и когда
  закрыто последним), **история по месяцам** (12 месяцев, столбики) и ачивки.
- **Редкие растения**: редкость решается в момент закрытия по весу задачи —
  чем больше XP, тем выше шанс редкого; эпик-растения — только у крупных
  закрытий. Редкость хранится в `xp_events`, визуально — золото + бейдж.
- **Ачивки с тирами**: у каждой ачивки ступени I/II/III (например, 10/50/100
  задач), прогресс к следующей ступени виден всегда. Набор: вехи закрытий,
  уровни, макс. задач за день, разные проекты, суммарные часы, строгие
  дедлайны, закрытия через режим «3 вариантов» (см. 3.9), регулярная, проект.
- **Связка с «3 вариантами»** (3.9): закрытие задачи из режима помечается
  (`earned_via`) и празднуется меткой «выбрал и сделал» + счётчик-ачивкой;
  XP при этом не меняется.

## 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-вызовы — на собственном сервере |

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

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

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

```
Task
  id, title, description (markdown)
  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 | archived   — статус актуальности
  priority
  note              markdown — ссылки на ресурсы, контекст

Tag           — справочник тегов
Attachment    — файлы задач (изображения), task_id, mime
```

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

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

```
┌─────────────┐     ┌────────────────────── VPS (docker-compose) ─────────────┐
│  Web SPA    │────▶│  API (FastAPI) ──▶ PostgreSQL                           │
│  Vue 3 +    │     │       │                                                 │
│  gnexus-    │     │       ├──▶ Сервис автодетализации ──▶ Ollama (модель    │
│  ui-kit     │     │       │      — LLM, модель из конфига)                  │
└─────────────┘     │       ├──▶ Хранилище вложений (файлы)                   │
                    │       └──▶ MCP-сервер (для ИИ-агентов)                  │
                    └─────────────────────────────────────────────────────────┘
                                     ▲ SSO auth.gnexus.space (клиент gnexus-gauth)
```

- API и MCP-сервер — одно Python-приложение (общая бизнес-логика).
- Вложения — файлы на диске VPS + метаданные в БД.

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

| Этап | Содержание |
|---|---|
| M0 — каркас | Репозиторий, скелет backend + frontend, SSO-интеграция (gnexus-gauth), деплой на VPS |
| M1 — MVP задач | CRUD задач, быстрый ввод, стек входящих, теги, проекты (базово), ручная детализация |
| M2 — детализация | Интеграция Ollama + модель из конфига, автопредзаполнение метаданных, подтверждение/редактирование, Markdown-редактор, вложения из буфера |
| M3 — структура | Подзадачи (parent_task_id), классический список с фильтрами, заметки проектов |
| M4 — умность | Прогнозирование времени, бюджет, режим «3 варианта» |
| 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), но поведение в интерфейсе почти одинаковое — скрыть из активных списков и оставить доступным для возврата. Уточнить при проектировании представлений, нужны ли оба статуса или их поведение сольётся.