| 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
12 hours 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
|
Пачка 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-19 |
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
|