131 lines
7.8 KiB
Markdown
131 lines
7.8 KiB
Markdown
# N8 Parser: current state
|
|
|
|
Last updated: 2026-07-30
|
|
|
|
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.
|
|
|
|
## Runtime / Deploy
|
|
|
|
Current runtime is local infrastructure, not the old VPS.
|
|
|
|
- Infrastructure source of truth: `D:\DEVELOPMENT\.infra.md`.
|
|
- 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/...`.
|
|
- Do not deploy this project through `sw.exostring.xyz`, `109.120.156.205`, `/opt/vk-parser`, or manual `systemctl` unless the user explicitly says the old VPS is being restored.
|
|
- Old `sw.exostring.xyz` / `109.120.156.205` notes are stale for this project.
|
|
|
|
## Local Project
|
|
|
|
- Local workspace: `D:\DEVELOPMENT\new_vk_parser`
|
|
- Main app package: `src/vk_parser_app`
|
|
- Admin routes: `src/vk_parser_app/admin.py`
|
|
- Templates: `src/vk_parser_app/templates`
|
|
- Workers:
|
|
- VK parser: `src/vk_parser_app/workers/parser.py`
|
|
- Telegram media/storage uploader: `src/vk_parser_app/workers/vk_storage_uploader.py`
|
|
- AI qualifier: `src/vk_parser_app/workers/ai_qualifier.py`
|
|
- AI writer: `src/vk_parser_app/workers/ai_writer.py`
|
|
- DB migrations: `db/migrations`
|
|
- Extended project documentation: `PROJECT.md`
|
|
|
|
## Pipeline
|
|
|
|
1. Sources are configured in admin.
|
|
2. VK parser reads enabled sources and stores raw posts.
|
|
3. Media/storage uploader sends raw post copies to Telegram storage and stores media metadata.
|
|
4. AI qualifier scores raw posts and marks accepted/rejected/maybe.
|
|
5. AI writer rewrites accepted posts into editor-ready drafts.
|
|
6. Editor page allows review, editing, category/source tag selection, media upload/removal, accept/reject.
|
|
7. Site poster automatically publishes accepted media-ready posts to Ghost.
|
|
|
|
## Important Text Rules
|
|
|
|
- AI writer output text must be clean: no physical hashtags at the end.
|
|
- `raw_posts.final_text` must also stay clean.
|
|
- Category and source hashtags are separate fields:
|
|
- category tag: `final_category_tag` / `rewrite_category_tag`
|
|
- source tag: `final_source_tag` / `rewrite_source_tag` / `sources.tag`
|
|
- Publication preview may show hashtags by composing:
|
|
- clean text
|
|
- blank line
|
|
- `#category #source`
|
|
- The editor textarea must show only clean editable text.
|
|
- The list preview in `/editor` should show the publication preview, including composed hashtags.
|
|
- `build_publication_text()` in `src/vk_parser_app/text_utils.py` is display/composition helper only. Do not use it before writing `final_text` to DB.
|
|
|
|
## Recent Hotfix: Hashtags
|
|
|
|
On 2026-06-17 the hashtag flow was fixed:
|
|
|
|
- `ai_writer.py` now stores clean `final_text=$2`, not text with hashtags.
|
|
- `admin.py` prepares:
|
|
- `review_text`: clean text for textarea
|
|
- `publication_preview_text`: composed display text with hashtags
|
|
- editor accept/save store clean text.
|
|
- existing DB rows with trailing `#category #source` in `final_text` were cleaned.
|
|
- server check after fix: `remaining_hashtag_tail: 0`.
|
|
|
|
## Admin Pages
|
|
|
|
- `/sources`: source management.
|
|
- `/raw`: raw post feed.
|
|
- `/editor`: editor queue.
|
|
- `/workers`: worker controls and settings.
|
|
- `/prompt-test`: AI writer prompt test page.
|
|
- `/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-...)/<alpha-value>)`), 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.
|
|
- 2026-07-30 incident: post `2348` was retried 983 times by AI writer because automatic claim included `rewrite_status='failed'`; estimated internal cost was `$16.465977`. Live setting `ai_writer_enabled` was switched to `false` manually to stop spend. Automatic AI qualifier/writer claims must not include `failed`; failed posts require an explicit manual reset to `pending`. AI writer/qualifier keep running after a failed batch, show the error on `/workers`, and send a Telegram alert via daily-report/TG-poster bot recipients.
|
|
|
|
## Prompt Architecture
|
|
|
|
- Prompts are split into editable human part and technical contract part.
|
|
- User should be able to edit human prompt safely without breaking JSON schema.
|
|
- Contracts should contain JSON-only/output-schema requirements.
|
|
- Writer should return category ID, not free-form tag, where possible.
|
|
- Categories are managed in worker/admin settings and have stable IDs.
|
|
|
|
## Security Notes
|
|
|
|
- Secrets should not be committed.
|
|
- `.env` should contain only secrets and deploy-specific values.
|
|
- Runtime settings that are not secrets should live in DB/admin settings.
|
|
- Admin has login protection and server has firewall/fail2ban hardening from previous iterations.
|
|
|
|
## 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.
|
|
- For runtime checks, use the current Coolify/Gitea/LXC 105 path from `D:\DEVELOPMENT\.infra.md`.
|
|
- Do not `git reset --hard` or revert user/server hotfixes.
|