| 2026-10-10 |
Интерфейс мандата: бейджи, приёмка, журнал, тосты (0.85)
root
committed
13 hours ago
|
Приёмка агентской работы: ждёт приёмки, принять, вернуть (0.85)
root
committed
13 hours ago
|
Аренда задачи агентом: взятие, heartbeat, возврат (0.85)
root
committed
13 hours ago
|

Мандат агента: флаг доступности и гейт (0.85)
...
- services/claims.py: рамка мандата (ТЗ 3.20) — агент меняет только задачи с флагом
ai_eligible, а сам флаг ставит только владелец: иначе «пометил и закрыл» обходило
бы правило. Ошибка — доменным исключением MandateError: REST отдаёт по нему 403,
MCP — текст с подсказкой следующего шага (стиль 3.10), а правило одно на оба пути.
- REST: PATCH проверяет рамку до правок; create принимает флаг (своя задача — можно),
пишет created_by_kind/created_by_name. Список задач фильтруется по ai_eligible,
created_by_kind и accept_state — признаки лежат в самой задаче, а не в join'е.
- MCP: update_task принимает ai_eligible (только владелец) и отказывает агенту на
задаче без флага с подсказкой «попросите владельца пометить или действуйте с
is_user=true»; create_task принимает флаг; list_tasks фильтруется теми же полями;
_compact отдаёт агенту ai_eligible, created_by_kind/name, accept_state, claimed_by.
- tests/test_agent_mandate.py: 12 тестов — дефолт «нет», гейт REST и MCP, отказ агенту
в выдаче флага себе, Bearer-токен на REST как агент по умолчанию и владелец под
заголовком X-Actor, фильтры списка, поля мандата в ответах тулов.
ТЗ 0.85.
root
committed
13 hours ago
|

Журнал действий по задачам и API журнала (0.85)
...
- services/tasklog.py — единственная точка записи в task_events, общая для REST и
MCP: иначе «кто закрыл задачу» отвечалось бы по-разному в двух путях. Заголовок
хранится снапшотом, запись об удалении ссылку не оставляет вовсе (FK с ON DELETE
SET NULL обнулил бы её сам, но в SQLite тестов внешние ключи не проверяются, и
журнал ссылался бы на несуществующую задачу). status_transition() пишет переход
кодами («to_do→in_progress») — журнал не хранит переводов, подписи даёт интерфейс.
- api/task_events.py: GET /api/task-events — первый пагинированный список API,
конверт {items, total, page, per_page}, потолок per_page 100, фильтры по типу
события, актору, каналу, проекту и задаче; порядок — свежие первыми, id вторым
ключом (у записей одной секунды иначе нет устойчивого порядка).
- Запись событий из HTTP: создание, закрытие (с комментарием), смена статуса, выдача
и снятие доступности агенту, удаление. Пишутся только настоящие перемены: PATCH,
ничего не изменивший, журнал не засоряет.
- Запись событий из MCP: те же события в тех же местах; у update_task и complete_task
появился параметр comment — что сделано (у агента он станет обязательным вместе с
приёмкой).
- main.py: роутер журнала подключён; conftest: стаб mcp_ctx принимает актора, а
agent_ctx() даёт контекст агента (по умолчанию актора нет — действие владельца,
так вызывают тулы тесты, написанные до мандата).
- tests/test_task_events.py: 9 тестов — события из UI и MCP, фильтры, конверт
пагинации и потолок per_page, изоляция журнала по пользователю, снапшот заголовка
после удаления.
ТЗ 0.85.
root
committed
13 hours ago
|
| 2026-10-09 |

Проекты: цвет, сайт, фавикон, закрепление, README из репозитория (0.63–0.67)
...
- Цвет-метка проекта (0.63): у проекта может быть цвет-кружок. Селектор
цвета — сырым блоком в стиле кита (в ките компонента нет); кружок рисует
общий компонент ProjectColorDot.
- Сайт проекта (0.63): отдельное поле site_url. Иконку сайта тянет
бэкенд-прокси с кэшем (GET /api/projects/{id}/favicon, том favicons) —
сторонние favicon-сервисы не используются, данные не покидают VPS. В 0.65
иконка встала в метку проекта (кружок + фавикон), а ссылка на сайт —
чипом в шапке страницы проекта.
- Карточка списка кликабельна целиком (0.63; кнопка «Открыть» дублировала
ссылку), тайтл крупнее (0.65), клетки прогресса — поверх полосы кита
(0.64): сегментированной полосы в ките нет.
- Закрепление проектов (0.66): поле pinned, закреплённые — секцией сверху,
сортировка списка по свежести активности, подвал карточки — отсчёт до
ближайшего дедлайна.
- Место булавки переставлено (0.67): на карточке — правый верхний угол
рядом с бейджем актуальности и видна всегда (была приглушена в подвале),
на странице проекта — кнопка-булавка рядом с именем (искали строкой
«Закреплён» в параметрах).
- Репозиторий проекта (0.67): ссылка на git-репозиторий — отдельное поле
repository_url, отдельно от заметки и сайта. README из репозитория
показывается вторым описанием — карточкой «README из репозитория» под
заметкой, со ссылкой на репозиторий и сворачиванием длинного текста;
тянет такой же бэкенд-прокси с кэшем (GET /api/projects/{id}/readme),
не нашли — «README не найден». Распознавание ссылки на репозиторий в
заметке проекта снято (у задачи README-вместо-описания остаётся),
данные в БД не мигрировались.
- Фантомный отступ перед именем у проекта без цвета и фавикона (0.67):
ProjectMark рисовал пустой спан в ряду с gap.
- ТЗ 0.63–0.67; MCP зеркалит поля проекта (color, site_url,
repository_url, pinned). Тесты: 207.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
1 day ago
|
| 2026-09-22 |
MCP: управление проектами — создание, обновление, архив/восстановление
...
Тулы create_project (микронаграда + фоновая суммаризация заметки),
update_project (имя/заметка/relevance_status/приоритет) и
archive_project/restore_project — архив вместо безвозвратного удаления:
задачи и история переживают архив, вызовы идемпотентны, delete-тула
в MCP нет намеренно. ТЗ 0.45 (§3.10).
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
18 days ago
|
| 2026-09-21 |

Мультиюзерность: изоляция данных, per-user MCP-токены, claim при первом логине (ТЗ 0.34, бэкенд)
...
- Модели: User (профиль из SSO), McpToken (только sha256-хэш),
user_id на tasks/projects/tags/documents/xp_events/coin_events/garden_items;
уникальности имени проекта/тега — составные (per-user); app_settings →
per-user (PK user_id+key), старая таблица → app_settings_global (источник claim)
- Миграция f9a0b1c2d3e4 (Postgres): новые таблицы, user_id на 7 таблиц,
составные уникальности, частичные индексы дейли/уровня per-user
- Claim-on-first-login (ТЗ 1.2): первый вошедший забирает строки с user_id NULL
и копирует глобальные настройки; upsert профиля в callback
- Scoping всех API и сервисов: tasks/projects/tags/attachments/settings/xp/
garden + xp/garden/closing/options/recurrence/detailing; чужое — 404
- MCP (ТЗ 3.10): per-user bearer-токены вместо env MCP_TOKEN (middleware →
sha256 → request.state.gntodo_user_id), 8 тулов с Context; SSE publish(uid)
- API /api/mcp-tokens: список/генерация (plaintext один раз)/отзыв
- Тесты: test_multiuser (изоляция двух пользователей, claim, per-user дейли/
настройки), test_mcp_tokens; 135 passed, ruff, mypy strict
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
19 days ago
|

Docker-деплой готов к проде (ТЗ 0.33, M7)
...
- nginx: client_max_body_size 20m (вложения до 10 МБ падали бы с 413),
HTTP/1.1-апстрим с keepalive и без буферизации для /api/ и /mcp/ (SSE),
кэш хэшированной статики на год, gzip
- compose: убраны контейнеры ollama/ollama-init (Ollama — внешний сервер,
OLLAMA_BASE_URL из .env); restart для db; healthcheck api через
/api/health (start_period 30s на миграции); модель по умолчанию
согласована с конфигом (qwen3.5:2b-q4_K_M, открытый вопрос ТЗ 8.5 закрыт)
- mcp_server: FastMCP пропускал только Host localhost — в проде за nginx
/mcp отвечал 421; разрешённый Host берётся из GAUTH_REDIRECT_URI
(dev-поведение не изменилось, защита от DNS-rebinding сохранена)
- README: раздел «Деплой» — шаги, внешний TLS-прокси, лимит тела,
буферизация SSE, почему 1 воркер uvicorn
- ТЗ 0.33: TLS — внешний reverse-proxy; Ollama — внешний сервер
Проверено локально полным стеком (db+api+web на :8135): сборка образов,
SPA/health/SSO-редирект/413/gzip/MCP-флоу (initialize → tools/call),
MCP с чужим Host — 421. 117 backend-тестов, mypy, ruff — чисто.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
19 days ago
|
MCP-эргономика для небольших моделей и проектный контекст (ТЗ 0.30)
...
- Серверные instructions FastMCP: порядок работы, привязка задач к проекту,
восстановление контекста через get_project, запрет придумывать id.
- Новые тулы: list_projects (заметка + открытые задачи), get_project (по id
или имени, полная заметка + открытые задачи), list_tags.
- Адресация проекта по имени: project_name (регистронезависимо) в
create_task/update_task/list_tasks; сравнение в Python — lower() в SQLite
не понимает кириллицу.
- Ошибки с подсказкой следующего шага; create_task без проекта отдаёт hint.
- Описания всех параметров через Annotated/Field (enum, форматы, диапазоны).
- _compact отдаёт project_id; обновлённые докстринги тулов.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
19 days ago
|
Пачка 4 ревью: расхождения с ТЗ
...
- Фильтр по приоритету в списке задач (ТЗ 3.6): параметр priority в
GET /api/tasks — градации шкалы 0-10, без приоритета = very_low;
селект в ListView, ключи i18n в ru/en/uk, тест.
- Статистика (ТЗ 3.13): метрики «закрыто», XP, график и теплокарта считают
только закрытия (kind='task') — микронаграды за создание больше не
попадают в «закрыто».
- apply_proposal привязывает задачу только к неархивному проекту; каталог
проектов для LLM-детализации тоже без архивных (ТЗ 3.8.1).
- i18n: «ч» часов в достижениях сада — через словарь (taskui.time.h).
- Докстринги: актуальные номера разделов ТЗ (MCP 3.10, архив 3.8.1).
ТЗ 0.29 (семантика фильтра приоритета в 3.6).
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
19 days ago
|

Пачка 3 ревью: гонки наград и остатки фронтенда
...
- Гонка дейли: уникальный частичный индекс (source, day) + колонка
coin_events.day; параллельные POST /api/xp/daily отдают granted=False
вместо 500 (IntegrityError ловится молча).
- Гонка ensure_garden (параллельные GET /api/garden): работа в savepoint,
при нарушении уникальности (uq_coin_level, kind+ref_id) — откат и выход;
дубли бонусов уровня и растений исключены.
- Параллельное закрытие: PATCH и MCP update_task берут задачу с FOR UPDATE
OF tasks (Postgres; SQLite игнорирует) — двойных наград/спавнов нет.
- redetail утверждённой задачи — no-op: ai_proposal больше не стирается,
фоновая LLM не будится (worker и так работает только с raw).
- Фронт: ProjectView подписан на SSE (task/project changed/deleted);
SSE-refetch на странице задачи не затирает начатый ввод тега;
просрочка дедлайна считается по локальной дате, а не UTC; бросок
предмета мимо сада игнорируется (не прилипает к краю); пауза refetch'а
сада держится до конца своего move-запроса, а не фиксированные 300 мс.
- Тест: redetail no-op для approved. 110 passed.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
19 days ago
|
Пачка 2 ревью: общий путь закрытия — MCP-награды и анти-дюп спавна
...
- Новый services/closing.py: handle_task_closed — спавн регулярной + XP +
монеты + бонус уровня; используют и HTTP-API, и MCP-инструменты. Закрытие
агентом теперь даёт те же награды, что и UI (ТЗ 3.5, 3.13, 3.10).
- Задача.spawned_at (+миграция): спавн — один раз на цепочку; раньше MCP
спавнил следующий экземпляр при каждом обновлении закрытой задачи.
- Выход из done сбрасывает done_at (HTTP и MCP): повторное закрытие снова
проходит через ветку закрытия без дублей наград (открытый вопрос ТЗ 7).
- MCP create_task: микронаграда за создание, как в HTTP-API; broadcast
xp.changed (celebrate:true при закрытии, false при создании).
- Тесты: MCP-награды при закрытии и создании, спавн ровно один раз,
un-done/повторное закрытие без дублей (HTTP и MCP). 109 passed.
ТЗ 0.28.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
19 days ago
|
Пачка UI + Ollama + SSE-реактивность (ТЗ 3.14)
...
- Бейдж приоритета с иконкой (PriorityBadge) во всех видах
- Фильтры страницы проекта запоминаются в localStorage (глубокий watch)
- DurationInput (ч/мин, шаг 5), ConfirmDialog, пагинация, иконки удаления
- Диалоги: «В архив» warning, кнопки поменяны местами
- Автодетализация на Ollama 192.168.1.130 (qwen3.5:2b, think:false)
- SSE /api/events: шина realtime, публикации после коммита, coarse-события + refetch
- Фронт: realtime.ts, удаление поллинга StackView, refetch по видам,
подавление во время drag сада, дедуп XP-тостов
- Тесты 93 passed, e2e двух вкладок; ТЗ 0.24
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
19 days ago
|
| 2026-09-20 |
Сущность «документ»: описания и заметки — единый текст с вложениями
...
- Новая таблица documents (owner_type task|project, owner_id, body) —
описания задач и заметки проектов теперь одна сущность; на моделях
полиморфная relationship + свойства description/note (API не меняется).
- Вложения привязаны к документу: attachments.document_id; эндпоинты
/api/documents/{id}/attachments; URL файла /api/attachments/{id}/file
не тронут (зашит в сохранённый markdown и PWA-кэш).
- Миграция d9e8f7c6b5a4: перенос текстов в документы (документ заводится
каждому владельцу), бэкфилл вложений, дроп старых колонок.
- Картинки в заметке проекта: Ctrl+V в инлайн-редакторе, drawer на
странице проекта и в списке проектов.
- MCP: поиск по описанию через join по документу; вложения в _full.
- ТЗ 0.13: модель данных обновлена.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
20 days ago
|
| 2026-09-19 |
Дедлайны и регулярные задачи (ТЗ 3.4, 3.5)
...
- дедлайны двух видов: строгий (deadline_date) и нестрогий
(deadline_period: день/неделя/месяц/год); бейджи в дереве и списке,
просроченные — красным
- регулярные задачи: три правила (интервал N дней, дни недели, день месяца),
якорь — фиксированный календарь от даты выполнения; при завершении
автоматически рождается следующий экземпляр (API и MCP)
- «3 варианта»: срочность дедлайнов влияет на отбор (просроченные и близкие
строгие — первыми, затем нестрогие периоды)
- ТЗ 0.4: вопросы 8.1–8.3 помечены решёнными (правила повторения, прогноз,
валюта)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
21 days ago
|
M5: MCP-сервер для ИИ-агентов (ТЗ 3.9)
...
- FastMCP (streamable HTTP), монтируется на /mcp основного приложения
- инструменты: create_task / update_task / complete_task / list_tasks / get_task
- авторизация: bearer-токен MCP_TOKEN (пусто — /mcp закрыт); SSO-токены — после
предоставления данных (открытый вопрос ТЗ)
- автодетализация созданных агентом задач — в фоновом потоке
- lifespan: запуск session manager для mounted ASGI-приложения
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
21 days ago
|