12 KiB
12 KiB
N8 Parser: current state
Last updated: 2026-08-03
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 inD:\DEVELOPMENT\.infra.md; do not copy it into repo docs. - Application LXC:
192.168.1.105(CTID 105,raa-fn8). - Public admin URL:
https://panel.f-n8.ru(alsohttps://admin.f-n8.ruwhen DNS is current). - Coolify repository URL must be reachable from the deployment container; use
http://192.168.1.135:3000/exostring/new_vk_parser.gitor another resolvable Gitea URL, nothttp://coolify.lan:3000/.... - Do not deploy this project through
sw.exostring.xyz,109.120.156.205,/opt/vk-parser, or manualsystemctlunless the user explicitly says the old VPS is being restored. - Old
sw.exostring.xyz/109.120.156.205notes 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
- VK parser:
- DB migrations:
db/migrations - Extended project documentation:
PROJECT.md
Pipeline
- Sources are configured in admin.
- VK parser reads enabled sources and stores raw posts.
- Media/storage uploader sends raw post copies to Telegram storage and stores media metadata.
- AI qualifier scores raw posts and marks accepted/rejected/maybe.
- AI writer rewrites accepted posts into editor-ready drafts.
- Editor page allows review, editing, category/source tag selection, media upload/removal, accept/reject.
- Site poster automatically publishes accepted media-ready posts to Ghost.
- As of 2026-08-03, site publishing is provider-based:
site_poster_provider=ghostfor FN-8, withsite_poster_base_urlandsite_poster_secret_filecopied from legacy Ghost settings by migration040_site_poster_provider_settings.sql. - New installs default
site-posterto disabled and must explicitly set provider, base URL, secret, andsite_poster_enabled=true.
- As of 2026-08-03, site publishing is provider-based:
RAA Deployment
As of 2026-08-03, RAA is a second Coolify app/database deployed from the same
canonical git repository as FN-8. Code work for both projects must happen in
D:\DEVELOPMENT\new_vk_parser.
- Canonical local workspace:
D:\DEVELOPMENT\new_vk_parser. - Canonical Gitea repo:
http://192.168.1.135:3000/exostring/new_vk_parser.git. - Old local copy
D:\DEVELOPMENT\raa-parser_posteris not the source of truth. - Coolify app UUID:
korokrhpoyqxf0nw2y8vk7lp(RAA admin). - Public admin URL:
https://raa.panel.f-n8.ru. - RAA Postgres container:
m9v14hzfh5mk9kelxzcqvhc6, DBraa_parser, userraa_parser_user. - Docker destination/LXC for both FN-8 and RAA: CTID
105, hostnameraa-fn8, IP192.168.1.105. - Raw Telegram media channel setting:
tg_media_channel_id=-1004312015562(VK RAW RAA). - Final Telegram publication chat setting:
tg_poster_chat_id=-1001303630155(Red Airsoft | Страйкбол). - VK publication owner:
vk_poster_owner_id=-36860851,vk_poster_from_group=true. TG_BOT_TOKEN,TELEGRAM_API_ID, andTELEGRAM_API_HASHwere copied from FN-8 Coolify env.- Local Bot API app setting:
local_bot_api_url=http://127.0.0.1:8081. - As last checked, RAA has
vk-parser=true,vk-storage-uploader=true. AI and publication workers are intentionally disabled until explicitly started:ai-qualifier=false,ai-writer=false,tg-poster=false,vk-poster=false,site-poster=false,tg_poster_enabled=false,vk_poster_enabled=false. - Detailed RAA notes live in
RAA.md. - CT
107(raa-parser-poster) was removed on 2026-08-04. CT104(raa-sender) remains a valid legacy VK reposting app and is not the shared RAA parser/writer/poster app.
Important Text Rules
- AI writer output text must be clean: no physical hashtags at the end.
raw_posts.final_textmust 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
- category tag:
- Publication preview may show hashtags by composing:
- clean text
- blank line
- optional project-wide common tags first, then
#category #source
- Project-wide common tags live in DB setting
publication_common_tags. FN-8 value:#новости_снаряжения. RAA value:#raa_news #страйкбол. - Optional per-platform header/footer settings:
tg_poster_header_text,tg_poster_footer_text,vk_poster_header_text,vk_poster_footer_text,max_poster_header_text,max_poster_footer_text. - MAX header/footer text is sent as HTML. For clickable text use:
<a href="https://example.com">Link text</a>. - HTML wrapper settings are normalized before publishing: safe
http/httpslinks and simple formatting stay, unsupported/broken tags are stripped while their readable text is kept. - The editor textarea must show only clean editable text.
- The list preview in
/editorshould show the publication preview, including composed hashtags. build_publication_text()insrc/vk_parser_app/text_utils.pyis display/composition helper only. Do not use it before writingfinal_textto DB./rawhas a manual checkbox action to send AI-rejected posts back to rewrite. It is intentionally limited toqualification_status='rejected'; editor-rejected posts that were AI-accepted are not selectable there.- VK/MAX successful publications also sync
raw_posts.publication_statusandeditorial_statustopublished; this keeps VK-only projects from leaving posts forever in the editor's accepted tab.
Recent Hotfix: Hashtags
On 2026-06-17 the hashtag flow was fixed:
ai_writer.pynow stores cleanfinal_text=$2, not text with hashtags.admin.pyprepares:review_text: clean text for textareapublication_preview_text: composed display text with hashtags
- editor accept/save store clean text.
- existing DB rows with trailing
#category #sourceinfinal_textwere 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 hardcodedParser Admintitle and lightning SVG are gone. - Browser/page title comes from env
ADMIN_SITE_TITLE; fallback isРедакторская. - 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. /editordesktop 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.
/sourcesand/rawhave 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 AlpineResizeObserver, trims trailing whitespace in the browser/template, and keepsmin-h-[150px].- Media hiding is handled by the editor media X button: it adds hidden
delete_media_ids; backend marks mediaeditor_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}/returnreturns 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
rewritesas a JSON string instead of a list.validate_rewrites()insrc/vk_parser_app/workers/ai_writer.pynow parses stringifiedrewritesbefore validation. - 2026-07-30 incident: post
2348was retried 983 times by AI writer because automatic claim includedrewrite_status='failed'; estimated internal cost was$16.465977. Live settingai_writer_enabledwas switched tofalsemanually to stop spend. Automatic AI qualifier/writer claims must not includefailed; failed posts require an explicit manual reset topending. 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. - Sonnet 4.6 may return
category_id=18(Не целевой контент) with emptytextand the explanation innotes. This is valid AI rejection, not a writer error;validate_rewrites()allows short/empty text only for non-target category. - AI qualifier has exactly one automatic retry: after the first failed qualification batch, affected posts are returned to
qualification_status='pending'; after the second failed batch for the same post, they stayfailedand are not claimed again automatically.
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.
.envshould contain only secrets and deploy-specific values.- Runtime settings that are not secrets should live in DB/admin settings.
- Dangerous FN-8 defaults were removed from runtime defaults on 2026-08-03: no default TG publication chat, no default VK storage group, no default Ghost URL/key path.
- Docker image now copies
db/migrations, anddocker-entrypoint.shrunspython /app/scripts/apply_migrations.pybefore starting the app. - 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.mdfirst. - Before pushing or deploying, run
git pull --rebase gitea main. - For this project, push deployable changes to
gitea/main; Coolify handles deployment. - FN-8 and RAA should deploy from the same
new_vk_parser.gitcommit SHA. Differences between projects belong in Coolify env variables and each project's DB settings. - Prefer small targeted file reads with
rgand narrow ranges. - Deployment status polling should be sparse. Coolify rebuilds can take 7-11 minutes because the Docker build currently runs without cache and reinstalls system deps.
- 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 --hardor revert user/server hotfixes.