diff --git a/PROJECT.md b/PROJECT.md index 66b0f05..3d862e5 100644 --- a/PROJECT.md +++ b/PROJECT.md @@ -117,6 +117,15 @@ - Для VK-постера user token нужно получать через VK ID Authorization Code Flow с PKCE: `/vk-oauth/start` -> `id.vk.ru/authorize` -> `/vk-oauth/callback`. Callback обменивает `code` через `id.vk.ru/oauth2/auth` на `access_token` + `refresh_token`, сохраняет `vk_poster_access_token`, `vk_poster_refresh_token`, `vk_poster_token_device_id`, `vk_poster_token_expires_at` и проверяет `wall.get` / `photos.getWallUploadServer`. Воркер обновляет access token через refresh token до истечения. Refresh token живёт 180 дней по документации VK ID; Redirect URI в VK ID-приложении: `https://sw.exostring.xyz/vk-oauth/callback`. - По документации VK API метод `photos.getWallUploadServer` требует пользовательское право `photos`, которое VK выдаёт в исключительных случаях через запрос в поддержку `devsupport@corp.vk.com`. Если token без `photos`, VK-постер пропускает upload редакторских/URL-фото, но всё равно публикует текст и существующие VK `photo...`/`video...` attachments. - VK-постер исключает из очереди video-only записи с `raw_post_media.status='link_only'`: VK API не разрешает прикреплять часть чужих видео без предварительной загрузки в целевое сообщество. Медиа `link_only` также не добавляются к смешанным постам, а публикации со статусом `publish_failed` не возвращаются автоматически в каждый следующий часовой слот и требуют явного ручного повтора. +- Админка на 2026-07-29: заголовок берётся из `ADMIN_APP_TITLE`, fallback `Редакторская`; старая молния рядом с названием удалена. Боковая навигация сворачиваемая и по умолчанию свёрнута до иконок. +- В редакторской фильтры на ПК сворачиваемые и по умолчанию свёрнуты; лента занимает освободившуюся ширину. На мобильных статусные вкладки скроллятся горизонтально, а `/sources` и `/raw` не должны давать page-level horizontal scroll. +- В карточке редакторской meta-блок поста находится над постом. `Оригинальный текст` расположен спойлером сразу над `Финальный текст`; `AI заметки / Резолюция` отдельным спойлером показывает заметки/резолюцию и ниже preview того, как AI написал пост после рерайта. +- `Финальный текст` должен полностью вмещать текст без внутреннего скролла. Текущая защита от регресса: autosize через Alpine `ResizeObserver`, trimming лишних хвостовых whitespace в браузере/template и `min-h-[150px]`; не заменять на фиксированную большую высоту. +- В редакторской восстановлено скрытие медиа: крестик на фото/видео добавляет `delete_media_ids`, backend помечает media `editor_hidden=TRUE`, и такие media не публикуются. +- Действие `Отклонить` выполняется без confirm/alert. Возврат поста на проверку идёт через `/editor/{post_id}/return`; кнопка должна быть доступна во вкладках `accepted` и `rejected`. +- Редакторские action-кнопки должны обновлять только нужные HTMX partials статуса/действий, чтобы открытые спойлеры и тело поста не схлопывались после `Сохранить`, `Сохранить и Опубликовать` или `Вернуть на проверку`. +- Светлая/тёмная тема реализована CSS-переменными. Tailwind `app.*` цвета заданы как RGB channels и используются через `rgb(var(--app-...)/)`; не возвращать hex-переменные, иначе `bg-app-bg/50` и похожие opacity utilities ломаются. В светлой теме hover не должен превращать текст в белый на светлом фоне. +- AI Writer на 2026-07-29 проверен с `ai_writer_model = anthropic/claude-sonnet-4-6`. Sonnet 4.6 иногда возвращает поле `rewrites` JSON-строкой, поэтому `validate_rewrites()` парсит stringified `rewrites` перед проверкой. ### 4.1. Секреты в `.env`, операционные настройки в БД @@ -1258,6 +1267,8 @@ local repo - Не выполнять `/opt/vk-parser`, `git pull` на VPS и `systemctl restart ...` без явного указания пользователя, что речь именно о старом VPS. - Основной deploy remote: `gitea`. +- Перед push/deploy обязательно делать `git pull --rebase gitea main`. +- Coolify app UUID: `n6cnr60anmruiwkiey0pukye` (`FN-8 admin`). API token хранится только в `D:\DEVELOPMENT\.infra.md`; не переносить секрет в репозиторий. - URL репозитория в Coolify должен резолвиться из build/helper container на deploy-сервере. Не использовать `http://coolify.lan:3000/...`, если это имя не настроено внутри LXC/Docker; рабочий локальный URL Gitea: @@ -1287,6 +1298,8 @@ git push gitea main `origin` остаётся GitHub/upstream/backup. Для deploy использовать `gitea`, потому что Gitea webhook запускает Coolify. +Перед каждым push не пропускать `git pull --rebase gitea main`: пользователь отдельно просил не забывать pull, потому что Coolify должен видеть свежий commit из Gitea. + ## 18. Контролируемый тест AI-райтера Важно: не включать AI writer обычным способом, если нужно проверить один пост. Иначе живой systemd service может начать брать очередь самостоятельно. diff --git a/STATE.md b/STATE.md index b089857..4e6f706 100644 --- a/STATE.md +++ b/STATE.md @@ -1,6 +1,6 @@ # N8 Parser: current state -Last updated: 2026-07-28 +Last updated: 2026-07-29 This file is the short handoff state for future Codex threads. Read this first before touching the project, so the whole chat history does not need to be carried forward. @@ -12,6 +12,7 @@ Current runtime is local infrastructure, not the old VPS. - Git deploy remote: `gitea` -> `http://192.168.1.135:3000/exostring/new_vk_parser.git`. - Deploy path: push to `gitea/main` -> Gitea webhook -> Coolify -> Docker build/deploy. - Coolify + Gitea LXC: `192.168.1.135` (CTID 102). +- Coolify app UUID: `n6cnr60anmruiwkiey0pukye` (`FN-8 admin`). API token is only in `D:\DEVELOPMENT\.infra.md`; do not copy it into repo docs. - Application LXC: `192.168.1.105` (CTID 105, `new-vk-parser`). - Public admin URL: `https://panel.f-n8.ru` (also `https://admin.f-n8.ru` when DNS is current). - Coolify repository URL must be reachable from the deployment container; use `http://192.168.1.135:3000/exostring/new_vk_parser.git` or another resolvable Gitea URL, not `http://coolify.lan:3000/...`. @@ -79,6 +80,29 @@ On 2026-06-17 the hashtag flow was fixed: - `/users`: admin users. - `/logs`: audit/log page if enabled. +## Recent Admin UI State + +As of 2026-07-29: + +- Admin title comes from env `ADMIN_APP_TITLE`; fallback is `Редакторская`. The old hardcoded `Parser Admin` title and lightning SVG are gone. +- Admin sidebar is collapsible and collapsed by default; collapsed state shows icons only. +- Theme toggle supports dark/light themes. Tailwind `app.*` colors use RGB-channel CSS variables (`rgb(var(--app-...)/)`), so do not revert them to hex variables or opacity utilities will break. Light-theme hover contrast is patched in base CSS. +- `/editor` desktop filter panel is collapsible and collapsed by default; the feed expands into the freed width. +- Mobile editor status tabs scroll horizontally instead of overflowing the viewport. `/sources` and `/raw` have mobile layout fixes to avoid page-level horizontal scroll. +- In editor cards, post meta/status/source info is above the post, not in a side column. +- `Оригинальный текст` is a spoiler directly above `Финальный текст`. +- `AI заметки / Резолюция` is a separate spoiler. It contains AI notes/resolution and an AI rewrite preview below it, so editors can compare their changes with the original AI rewrite. +- `Финальный текст` textarea must autosize to fully fit text without internal scroll. Current implementation uses Alpine `ResizeObserver`, trims trailing whitespace in the browser/template, and keeps `min-h-[150px]`. +- Media hiding is handled by the editor media X button: it adds hidden `delete_media_ids`; backend marks media `editor_hidden=TRUE`, so hidden media is not published. +- Reject action has no confirmation popup. +- Save/accept/return actions use targeted HTMX partial updates for status/actions where possible, so open spoilers and the post body should not collapse after clicking action buttons. +- `/editor/{post_id}/return` returns accepted/rejected posts to review. The return button should exist on both accepted and rejected tabs. + +## Recent AI Writer State + +- Current live writer model setting checked on 2026-07-29: `ai_writer_model = anthropic/claude-sonnet-4-6`. +- Sonnet 4.6 can return `rewrites` as a JSON string instead of a list. `validate_rewrites()` in `src/vk_parser_app/workers/ai_writer.py` now parses stringified `rewrites` before validation. + ## Prompt Architecture - Prompts are split into editable human part and technical contract part. @@ -97,6 +121,7 @@ On 2026-06-17 the hashtag flow was fixed: ## Working Rules For Future Codex Runs - Before any deploy/server operation, read `D:\DEVELOPMENT\.infra.md` first. +- Before pushing or deploying, run `git pull --rebase gitea main`. - For this project, push deployable changes to `gitea/main`; Coolify handles deployment. - Prefer small targeted file reads with `rg` and narrow ranges. - Avoid dumping long post texts from DB unless explicitly needed.