| 2026-09-22 |
MdEditor: textarea на всю ширину контейнера
...
GnTextarea без ширины сжимался до ~20 символов, а .form-group кита
упёрт в max-width: 600px — перебито внутри компонента.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
13 hours ago
|
Сад: компактный старт 24×12, два расширения (ТЗ 0.37)
...
- старт 24×12 (было 32×20): дворик заполняется быстро, расширение
ощущается событием
- расширение I (ур. 3, 100) возвращает прежний старт 32×20; II (ур. 12,
250) — до 40×28; расширения III–V убраны
- предметы существующих садов, оказавшиеся за новой границей,
переставляются по спирали к дому при первом заходе (идемпотентно)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
14 hours ago
|
Тосты: непрозрачный фон вместо rgba-тинки кита
...
Вариантные тосты кита красятся rgba(...,.18) — сквозь них просвечивает
страница. Перебито китовым базовым #1f2335 (селектор 0,2,0), цвет варианта
остаётся в рамке и иконке.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
14 hours ago
|
| 2026-09-21 |
Имя и аватар из SSO: users.name, синк по webhook и при логине (ТЗ 0.36)
...
- users.name (display_name из SSO), миграция f1a2b3c4d5e6
- webhook user.profile_updated: name ← profile.display_name (ключа нет —
не трогаем), avatar_url, locale; username_changed имя не меняет
- /auth/callback: name в сессию и БД (display_name, fallback username)
- /auth/me: профиль из БД, не из cookie-сессии — изменения от webhook
видны сразу, без повторного логина
- фронт: имя в сайдбаре (identity-title), email в meta
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
1 day ago
|
Подготовка к деплою: GAUTH_WEBHOOK_SECRET в compose, чистка MCP_TOKEN
...
- docker-compose: проброс GAUTH_WEBHOOK_SECRET в api (без него webhook
молча 503 на проде); удалён устаревший MCP_TOKEN (ТЗ 0.34)
- .env.example/README: комментарий про per-user токены вместо env
- тест webhook_disabled: секрет пуст явно — Settings теперь читает
backend/.env с реальным секретом
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
1 day ago
|
Фильтры проекта на моб — ширина 10rem (просьба пользователя)
...
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
1 day ago
|
«Новая задача» на моб — GnIconButton кита вместо ручного квадрата
...
Штатный компонент кита (.btn-icon 38×38, иконка 22px) вместо самодельного
сжатия .btn с перебивкой border-left; переключение display по брейкпоинту.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
1 day ago
|
Мобильные UI-фиксы: переполнения дашборда/проекта, кнопки-иконки (360px)
...
- Dashboard/ProjectView: grid-треки minmax(0,1fr) вместо 1fr — min-content
nowrap-текста растягивал колонку и ломал страницу на телефоне
- Dashboard: заголовки задач на моб переносятся вместо ellipsis
- «Новая задача» в топбаре и шапке проекта — квадратная кнопка 42×42 на моб;
перебито правило кита .btn.btn-small.with-icon (border-left 32px)
- SettingsView: .token-create — кнопка «Сгенерировать» не уплывает за экран,
на моб поля в столбик
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
1 day ago
|
Вебхуки от gnexus-auth: профиль, статус, отзыв MCP-токенов (ТЗ 0.35, 3.16)
...
- POST /auth/webhook: HMAC-SHA256 через gnexus_gauth (verify_and_parse_webhook),
секрет GAUTH_WEBHOOK_SECRET; не задан — 503 (приём выключен)
- user.email_changed / user.profile_updated — синхронизация User (email,
locale, avatar_url) без повторного логина
- user.blocked / user.archived / user.deleted — отзыв всех MCP-токенов
пользователя (агент теряет доступ вместе с аккаунтом); cookie-сессии
stateless — закрываются на стороне SSO (документировано)
- незнакомые типы (включая webhook.test) — 200 без действий, против retry-шторма
- тесты: подпись, 503 без секрета, битый payload, отзыв токенов, sync профиля
(9 новых; всего 145 passed)
- ТЗ 0.35 (3.16), deploy.md: GAUTH_WEBHOOK_SECRET + настройка webhook (п. 3.1)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
1 day ago
|
Мультиюзерность: фронтенд и ТЗ (ТЗ 0.34, батч 3)
...
- userScope.ts: localStorage-ключи скоупятся по user_id (второй аккаунт
в том же браузере не видит чужих фильтров/дедупа тостов)
- realtime.ts (дедуп own-activity) и ProjectView.vue (фильтры проекта) —
через scopedKey
- App.vue: setStorageUserId из /auth/me
- SettingsView: раздел «Токены MCP» — генерация (plaintext один раз,
с копированием), список, отзыв; api.ts: типы + listMcpTokens/
createMcpToken/deleteMcpToken
- McpView: текст «токен в Настройках» (connectTokenText) в ru/en/uk
- Локали: ключи mcpToken* в ru/en/uk (в ru/en/uk попали литералы
ru_new/en_new/uk_new вместо блоков — исправлено)
- docs/TZ.md → 0.34: 1.2 (мультиюзерность + claim-on-first-login),
3.10 (per-user токены, MCP_TOKEN удалён), 5 (User, McpToken,
AppSetting/AppSettingGlobal)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
1 day ago
|

Мультиюзерность: изоляция данных, 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
1 day ago
|
docs/deploy.md — пошаговый деплой на VPS для агента
...
Предпосылки → .env (таблица переменных, генерация секретов) → SSO callback
(ручной шаг — остановиться и спросить пользователя) → compose up → внешний
TLS-прокси (пример nginx, критичность Host для /mcp) → чеклист проверки с
ожидаемыми ответами → MCP для агентов → обновление/бэкапы/диагностика.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
1 day 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
1 day ago
|
Сад: хват и фидбек при перемещении объектов (ТЗ 0.32)
...
- Хит-зона объекта — клетка с запасом, а не текстура: промахи мышью исключены
- Анимации «взял в руку» (масштаб + тень) и «приземление» (ease-out доводка)
- Подсветка целевой клетки по валидности: зелёная/красная, зеркало правил
бэка (растениям запрещён домик); за краем сада подсветка скрыта
- Недопустимый бросок (мимо сада, на домик) — анимированный возврат на место
без запроса к API; клик без движения больше не ломает состояние твинов
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
1 day ago
|
Страница-инструкция по MCP + ссылка в настройках (ТЗ 0.31)
...
- Новый вид McpView (/mcp-help): что реализует, инструменты, адрес сервера
(из location.origin, кнопка «Скопировать»), токен, примеры подключения
(Claude Code и универсальный JSON), раздел про контекст проекта.
- Карточка-ссылка «MCP для ИИ-агентов» в «Настройках».
- Тексты i18n ru/en/uk.
- vite-прокси: '/mcp' регэкспом ^/mcp(/|$) — путь страницы /mcp-help
не должен проксироваться в backend (префиксный матч ловил её).
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
1 day 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
1 day 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
1 day 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
1 day 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
1 day ago
|

Пачка 1 ревью: безопасность + порча данных (находки 1-5)
...
Бэкенд:
- DELETE /api/tags/{id} требовал сессии только фактически — добавлен UserDep;
регрессия-тест проверяет require_user на каждом /api-роуте (не пройдёт для
любого нового эндпоинта без UserDep).
- Вложения: SVG отклоняется (скриптуемый формат — inline-отдача = stored XSS),
лимит 10 МБ на файл, X-Content-Type-Options: nosniff на отдаче.
- Open redirect закрыт: return_to только внутренние пути (не //, не внешние).
- MCP-токен сравнивается constant-time (hmac.compare_digest).
- Дефолтный SESSION_SECRET валит старт валидатором — молчаливо подделываемая
кука вместо этого даёт явную ошибку конфигурации.
- backend/data/ (runtime-вложения) в .gitignore.
Фронтенд:
- Черновик инлайн-правки больше не переезжает между задачами: при смене
/tasks/:id сбрасываются descEditing/draft, заголовочный InlineField
перемонтируется по key=taskId (PATCH старого текста в новую задачу).
- Утечка SSE-подписок: onRealtime сам отписывается при dispose scope —
N визитов на страницу больше не оставляют N load() на мёртвых инстансах.
- Out-of-order: токен запроса в load() TaskView/ProjectView — поздний ответ
старого id не перетирает данные нового; ListView — то же на фильтрах.
- Смена фильтра сбрасывает пагинацию: watch(filters, {deep}) (ТЗ 3.6).
- Двойной submit не создаёт дубликаты: busy в TaskForm и quickAdd стека.
- Утечка Pixi: unmount во время init уничтожает рендерер после резолва.
- Оффлайн-старт PWA: /auth/me без сети не роняет onMounted молча.
Тесты: 103 passed (+6: auth-все-роуты, SVG, oversize, nosniff, return_to,
дефолтный секрет). ruff/mypy чисты.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
1 day ago
|
PWA: тёмный манифест, проверка установочности и оффлайн-оболочки (ТЗ 0.27, 3.15)
...
background_color/theme_color — палитра кита #16161e (белый фон мигал при
запуске установленного приложения, шапка окна была зелёной); добавлен id.
Проверено на прод-сборке (headful Chromium, чистый профиль): SW активен,
precache 21 запись, beforeinstallprompt приходит, оффлайн-навигация отдаёт
оболочку приложения. Поведение зафиксировано в ТЗ 3.15.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
1 day ago
|
«Новая задача» в шапке проекта: на мобильном — кнопка-иконка
...
size="sm" (плитка иконки 32px вместо 46px) + на ≤640px лейбл скрывается,
кнопка сжимается до компактной 54x38 — как «+» топбара.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
1 day ago
|
Чекбоксы списков задач в описании кликабельны и сохраняются (ТЗ 0.26)
...
Клик по чекбоксу в отображаемом описании переключает соответствующий
- [ ] / - [x] в сыром markdown (маркеры - * + и нумерованные списки)
и сохраняет PATCH'ем описания. marked рендерит чекбоксы с disabled —
атрибут снимается во view-режиме, иначе клики не всплывают вовсе;
повторный клик до ответа блокируется до перерендера.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
1 day ago
|
Пачка UI: полоска таймера тостов, мобильный «+», ширина md-редактора, мета-бейджи
...
- Тосты: у .toast-progress-bar кита анимация без duration мгновенно схлопывала
полоску таймера (forwards до scaleX(0) поверх inline transform адаптера);
отключаем селектором той же специфичности (.toast .toast-progress ...).
- Кнопка «Новая задача» на мобильном — компактная кнопка-иконка вместо
растянутого .btn с пустым хвостом после скрытия лейбла.
- Инлайн-редактор описания задачи на всю ширину контейнера (max-width .form-group).
- Ссылка на проект в мете страницы задачи — inline-flex, бейджи на одном базлайне.
- Detailing: зачистка HTML-тегов из markdown-ответов LLM (_clean_markdown).
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
1 day ago
|
Сад: реальный fullscreen на мобильных — вписывание по меньшей стороне
...
- fullscreen-бокс занимает весь экран (на вертикальном телефоне — всю высоту),
аспект сетки в fullscreen отключается
- рендерер вписывает сад по меньшей стороне и центрирует (базовый сдвиг
отделён от panOffset, учтён в зуме, панораме и клиентских координатах)
- земля/газон рисуются с запасом за края сетки — вокруг поля трава,
а не фон страницы
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
1 day ago
|
ИИ-детализация: короткий тайтл, шаги в описании, контекст проектов, валидация (ТЗ 0.25)
...
- LLM предлагает короткий заголовок для перегруженных тайтлов и описание
с нумерованными шагами, если они очевидны
- в контекст добавлены открытые проекты с описаниями — назначение по смыслу
- теги: разрешены новые (1-2 при отсутствии подходящих), до 3, не обязательно один
- валидация ответа: заглушки «NULL»/пробелы отбрасываются, дубли схлопываются,
new_project без валидного имени не протекает; несуществующие теги создаются
при утверждении
- фронт: строки «Новый заголовок»/«Описание с шагами» в карточке предложения
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
1 day ago
|
Пачка UI: fullscreen сада, отступ empty-state, шапка задачи, форма на всю ширину
...
- fullscreen сада: резерв 64px в ширине бокса — кнопки зума и инвентарь не уезжают за экран
- «Всё спокойно» на главной не слипается с блоком быстрого ввода
- на экранах ≥641px действия шапки страницы не переносятся под длинный заголовок
- форма редактирования на весь контейнер (form-group кита растянута с 600px)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
1 day 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
1 day ago
|
| 2026-09-20 |
Сад: изометрический домик, тени под объектами, пропорции растений
...
- Домик перестроен в изометрии 2:1 из полигонов (fillPoly/wall): две
видимые стены (свет/тень), скаты, фронтон, труба на дальнем скате,
дверь и окно с отблесками.
- Мягкая овальная тень (SHADOW) под растениями/декорациями и домиком,
ширина подгоняется под текстуру тела (fitShadow).
- Пропорции: ель/дуб/кактус выросли относительно цветов (дерево не
размером с цветок).
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
2 days ago
|
Сад: пиксель-арт сцена на PixiJS 8 — спрайты из кода, рендерер вне Vue-reactive
...
- PixiJS 8 (WebGL): nearest, roundPixels, нативный пиксель 16px×2 (клетка 32px),
динамический импорт — pixi в async-чанке (main не раздут, PWA в лимитах)
- src/game/pixelart.ts: пиксель-матрицы → canvas → CanvasSource(nearest) с кэшем
- src/game/sprites.ts: тайлы травы/дикой земли/изгороди, домик, 6 видов × 3
стадии растений, декорации, кольца rare/epic, блёстки — без внешних ассетов
- src/game/GardenRenderer.ts: слои terrain/house/items/fx, дифф items по id,
z-sort, drag на канвасе, grow-in/покачивание/блёстки, один тикер
- GardenScene.vue: renderer через shallowRef — deep-reactive-прокси Vue ломал
identity-проверку shared defaultScale в Pixi (TypeError при первом drag)
- ТЗ 0.16: 3.13 дополнен (отрисовка сцены), вопрос 8 закрыт
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
2 days ago
|