| 2026-10-10 |

Напоминания: сроки, ритм, сводка, тихие часы (0.89)
...
Push из 0.88 доставлял события агента, но о сроке и о регулярном деле по-прежнему
напоминала только открытая вкладка. Теперь о них напоминает планировщик: строгий
дедлайн за день, в день и один раз о просрочке; «пора» регулярной задачи; утренняя
сводка. Нестрогий срок («в течение недели/месяца/года») не напоминает вовсе — в
модели у него нет дня отсчёта, а выдумывать якорь не стали. Задачи в done,
cancelled и deferred молчат: «сейчас не в приоритете» — решение владельца.
Правила — чистые функции (app/services/reminders.py): «сегодня» приходит
аргументом, поэтому календарные границы проверяются без часов и без сети, а
планировщик (app/services/scheduler.py) остаётся тонким. День ритма считается тем
же recurrence.next_date, что создаёт следующий экземпляр, — отдельного календаря
напоминаний нет, иначе правила разъехались бы.
Дедуп — журналом push_deliveries (unique(user_id, kind, ref_key)), и запись идёт
до отправки: тик 15-минутный, а поводы дневные, поэтому без журнала одна и та же
просрочка приходила бы сотню раз, а перезапуск контейнера рассылал бы дубли.
Обратный размен (падение между вставкой и отправкой) даёт пропуск, а не дубль —
для напоминания это правильная сторона ошибки.
Тихие часы — настройка quiet_hours («HH:MM-HH:MM», окно 22:00-09:00 в интерфейсе,
пересекает полночь). Попавшее в окно напоминание не отправляется и не
записывается: условие дневное, и следующий тик после окна отправит его сам. Работа
агента тихими часами не глушится — она ждёт решения владельца.
Планировщик живёт задачей в lifespan приложения: итерация уходит в
asyncio.to_thread (внутри синхронные SQLAlchemy и requests), цикл отменяется
вместе с приложением, сбой итерации логируется и не прекращает напоминания.
Сводка отправляется в окне 09:00-14:00 по REMINDER_TIMEZONE и молчит при нуле.
Заодно починен свой service worker: createHandlerBoundToURL('index.html')
бросал исключение при вычислении воркера в dev-режиме, где манифест precache пуст
(VITE_PWA_DEV=1), и регистрация падала целиком — отлаживать push было негде.
Маршрут теперь ставится только если index.html и правда в precache.
ТЗ 0.89: §3.21 дополнен подразделом «Напоминания», §5 — PushDelivery, §7 — строка
этапа, §8 — открытые вопросы про часовой пояс напоминаний и ретенцию журнала.
root
committed
9 hours ago
|

Системные уведомления: транспорт Web Push, события агента, настройки (0.88)
...
О работе агента владелец узнавал только из открытой вкладки: SSE-кадры
task.claimed/task.review живут ровно столько, сколько она открыта, а агент
работает как раз тогда, когда вкладки нет. Web Push — второй транспорт тех же
событий на той же шине; SSE остаётся за мгновенный refetch интерфейса.
Backend: pywebpush и пара ключей VAPID (app/vapid.py печатает готовые строки
для .env; пустые ключи — push тихо выключен, а не падение на старте),
таблица push_subscriptions (endpoint уникален глобально: тот же браузерный
профиль может войти другим аккаунтом — подписка перепривязывается),
app/api/push.py (config/subscribe/unsubscribe/subscriptions), тексты
уведомлений на ru/en/uk собирает сервер — у service worker локалей нет.
Отправка идёт вне HTTP-ответа (BackgroundTasks в REST, поток в MCP) со своей
сессией; мёртвые подписки (404/410, серия ошибок) удаляются лениво.
Frontend: свой src/sw.ts через strategies: 'injectManifest' — в generateSW
обработчик push вставить некуда; precache, SPA-fallback и CacheFirst переехали
из vite.config.ts в воркер, у SW отдельный tsconfig (WebWorker не уживается с
DOM). Подавление при видимой вкладке — по visibilityState клиента, иначе
системное уведомление дублировало бы тост. Разрешение спрашиваем при входе
(жеста нет — браузер вправе проигнорировать), надёжный путь — переключатель
в Настройках.
Тесты: подписка/отписка/перепривязка, отправка с подменённым webpush, связка
событий. Фоновую отправку в тестах глушим: она идёт в чужом потоке по общему
SQLite-соединению и перемешивала транзакции тестов мандата.
ТЗ 0.88: §3.21 «Системные уведомления», правки §3.14, §3.15, §5, §7.
root
committed
10 hours ago
|
| 2026-09-30 |
Сырые кастомные блоки — под визуальный язык кита 1.0.0
...
Дерево уровней, маркет, ачивки, график/heatmap статистики, инвентарь и
оверлеи сцены, полнотекстовые превью/миниатюры, tags-fieldset: бордеры
2px var(--gn-border-color-muted) вместо 1px, радиусы 6px (панели) и
3px (инсеты/контролы), поверхностные подложки поверх --gn-surface-panel.
Иконки в заголовках карточек — в цвете заголовка (было тёмные).
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
10 days ago
|
| 2026-09-21 |
Мобильные 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
19 days 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
19 days 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
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 |
feat(frontend): переименование в GNexus Tasks, тайтлы страниц
...
- Сервис «gntodo» → «GNexus Tasks»: brand топбара, kicker шапок видов,
subtitle навигации (ru/en/uk), index.html, PWA-манифест (short_name Tasks)
- taskui: APP_NAME + setPageTitle(); тайтлы через meta.title роутов
(afterEach в main.ts) — «{страница} — GNexus Tasks»
- TaskView/ProjectView уточняют тайтл после загрузки (watchEffect):
заголовок задачи / имя проекта
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
21 days ago
|
| 2026-09-19 |

UI: ревью всех страниц (mobile+desktop), полный набор компонентов кита
...
- Root-фикс intrinsic-ограничений кита: .card max-width 340px → 100%,
overflow visible (иначе dropdown-меню обрезается).
- Все виды задач (стек/дерево/список) — двухстрочные карточки:
заголовок + меню «⋯» (GnDropdown c GnIconButton-триггером, статусы
с отметкой текущего, подзадача в дереве, удаление с подтверждением)
и строка бейджей (новый TaskBadges: статус, проект, P{n}, ≈время,
recurring, дедлайн, бюджет, теги).
- Редактирование задач/проектов перенесено в GnDrawer (детализация
в стеке, карточка — только просмотр).
- Удаления — через GnConfirmDialog (confirm-variant danger), промпты
создания проекта/тега/подзадачи — через модалку QuickPrompt вместо
window.prompt.
- Действия — тосты (useToast) вместо inline-алертов; при загрузке —
GnSkeleton; пустые состояния — GnEmptyState с CTA-кнопками.
- Список: фильтры в GnToolbar с авто-применением (компактные,
фиксированная ширина select-wrap).
- Настройки: GnRadioGroup для валюты и языка; «3 варианта» —
компактная форма времени.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
21 days ago
|
i18n: ru/en/uk, язык из gnexus auth + переопределение в настройках
...
- vue-i18n v11 (legacy:false, fallback ru); локали src/locales/{ru,en,uk}.ts,
en/uk типизированы как typeof ru — полнота проверяется vue-tsc
- резолюция: settings.language (override, ''=auto) → SSO profile.locale → ru
- backend: /auth/callback прокидывает profile.locale в сессию; /api/settings
получил поле language, PUT стал частичным (model_fields_set)
- taskui.ts и все views переведены на t(); дни недели и даты через Intl
- в Настройках — карточка «Язык интерфейса», переключение мгновенное
- тесты: test_settings.py (частичный PUT, 422), AUTH_USER += locale
- ТЗ 0.5: новый пункт 3.11 «Мультиязычность»
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
21 days ago
|
Правки по обратной связи: прогноз = LLM, валюта в настройках, «3 варианта» +50%
...
- прогноз длительности: убрана медиана истории и эндпоинт /predict —
оценка приходит только из LLM-детализации (или вручную)
- валюта бюджетов — глобальная настройка (app_settings): UAH/USD/EUR/GBP/PLN,
выбирается один раз и применяется всюду; UI — страница «Настройки»,
суммы через formatMoney (символ по настройке)
- «3 варианта»: допуск нестрогий — оценка может превышать доступное время
до +50%, короткие задачи подходят всегда; задачи без оценки — фолбэк
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
21 days ago
|