尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证IZZ.ro — Romanian anti-clickbait news aggregator. RSS sources → AI summaries + multi-source dedup → static site (SSG) → GitHub Actions → Cloudflare Workers. Human-moderated. Live: izz.ro
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
Agregator de știri românești construit pe o promisiune simplă: mai puțin zgomot, mai multă informație. Titlurile sunt reformulate faptic, fără cârlige emoționale. Rezumatele sunt scrise cu cuvinte proprii și duc întotdeauna la sursa originală. Când mai multe publicații relatează același eveniment, subiectul apare o singură dată, cu toate sursele enumerate. Imaginile sunt grafică generată pentru fiecare articol, nu fotografii preluate.查看完整 README ↗
Portalul știrilor tale · izz.ro
Agregator de știri românești construit pe o promisiune simplă: mai puțin zgomot, mai multă informație. Titlurile sunt reformulate faptic, fără cârlige emoționale. Rezumatele sunt scrise cu cuvinte proprii și duc întotdeauna la sursa originală. Când mai multe publicații relatează același eveniment, subiectul apare o singură dată, cu toate sursele enumerate. Imaginile sunt grafică generată pentru fiecare articol, nu fotografii preluate.
Site-ul este 100% static (SSG), publicat serverless: pipeline-ul rulează în GitHub Actions, publicarea se face prin Cloudflare Workers. Fără server propriu, fără baze de date gestionate, fără publicitate.
/calendar/) — calendarul evenimentelor care urmează în știri./cauta/) — index Pagefind construit la fiecare build: rezultate pe măsură ce tastezi, în titluri și în rezumate, cu diacritice opționale („inundatii” găsește „inundații”), termeni marcați în rezultat, filtre pe categorie și pe tip de anunț oficial. Fără serviciu extern, fără chei. RSS (/feed.xml).static/site.webmanifest, service worker la /sw.js) cu citire offline: shellul se precachează la instalare, iar articolele se servesc stale-while-revalidate — ce ai mai citit rămâne disponibil fără net. Butonul de instalare apare discret, jos-stânga, și dispare definitiv după instalare sau după refuz.infra/PUSH-SETUP.md.Surse RSS (SOURCES din generator/config.py)
│
├─ fetch.py descărcare fluxuri
├─ state.py stare, dedup, expirare → data/articles.json (comis în repo)
├─ cluster.py grupare multi-sursă
├─ select.py selecție editorială
├─ process.py sinteză AI (model B/C)
├─ covers.py grafică proprie per articol
├─ moderation.py filtrare editorială → moderation.yaml (om în buclă)
└─ render.py randare Jinja2 → output/
└─ pagefind_index.py index de căutare → output/_pagefind/ (52 fișiere, fără fragmente)
Modelul de conținut B+C corespunde celor două tipuri vizibile pe site: rezumat dintr-o sursă (B) și sinteză multi-sursă (C). Starea persistă între rulări prin data/articles.json, comis în repo — nu există bază de date externă.
pip install -r requirements.txt
# Pipeline complet (RSS → AI → HTML în output/) + salvează starea
python -m generator.main
# Doar test, fără salvare sau randare (afișează rezultatul + sursele RSS moarte)
python -m generator.main --dry-run
# Vizualizare locală
python -m http.server 8000 --directory output
# → http://localhost:8000
Fără cheie AI, pipeline-ul folosește un fallback determinist (rezumat din descrierea RSS) — util pentru testat structura. Pentru reformulare reală, pune GEMINI_API_KEY în .env (vezi .env.example).
generator/ pipeline-ul: fetch · state · cluster · select · process (AI B/C)
covers · moderation · render · main · providers/
templates/ Jinja2 (autoescape ON): base · index · article · category · legal
search · calendar · instrumente · calculator · ghid/ghiduri · surse
sectiuni · subject · _card
static/ styles.css (temă auriu-dark) · logo · favicon · og-image · pictograme
PWA · site.webmanifest · theme.js · search.js · calc-salariu.js
fonts/ · harta-stiri/
content/ pagini legale și metodologice (markdown): method (Cum devin ideile funcții),
terms, privacy, corrections, security, images, takedown,
accessibility, contact
data/ articles.json — starea comisă în repo
moderation.yaml control editorial (om în buclă) — vezi REVIEW.md
infra/ Workerul publicat (infra/worker.js): compune fallback-ul 404 -> oglinda
(infra/worker-404-mirror.js) cu rutele de alerte (infra/push.js — VAPID,
criptare aes128gcm, KV). Configurarea alertelor: infra/PUSH-SETUP.md
tools/ utilitare operaționale: qa_check, feed_check, verify_release,
title_quality_audit, build_harta*, indexnow_submit etc.
tests/ teste Python
.github/ workflows (build, tests, monitor, editorial-quality, security…)
Documente de proiect comise: CLAUDE.md și AGENTS.md (reguli pentru dezvoltare asistată de agenți AI), REVIEW.md (fluxul de moderare), REGULI-SINTEZA.md (regulile de sinteză), specs/, notes/, sessions/ (istoric de lucru intern).
generator/config.py.moderation.yaml (fluxul e descris în REVIEW.md)..env local / secrete GitHub — nu se comit niciodată.| Scenariu | Configurare |
|---|---|
| Implicit | GEMINI_API_KEY (secret GitHub sau .env) · fluxul Gemini → Ollama local fallback |
| Claude API | secret ANTHROPIC_API_KEY + AI_PROVIDER: anthropic în build.yml |
| Router multi-provider (opțional) | AI_ROUTER_MODE=multi + AI_FALLBACK_PROVIDERS=groq,cerebras,mistral,openrouter |
| Fără cheie | fallback determinist din descrierea RSS |
Routerul multi-provider este o cascadă: providerul principal configurat, apoi providerii din AI_FALLBACK_PROVIDERS în ordinea declarată (endpointuri OpenAI-compatible), apoi Ollama dacă e activ. Un provider fără cheie proprie este ignorat automat; implicit rămâne AI_PROVIDER=gemini. Exemplu local:
AI_ROUTER_MODE=multi
AI_FALLBACK_PROVIDERS=groq,cerebras,mistral,openrouter
Arhitectura separă munca grea de publicare:
GitHub Actions — .github/workflows/build.yml, cron 13 * * * *: rulează pipeline-ul (fetch + AI, cu buget per rulare) și comite data/articles.json în repo. Secret necesar: GEMINI_API_KEY.
Încearcă orar, publică la ~2h: un job de poartă taie rularea dacă ultimul conținut e mai proaspăt de 105 minute. Cron-ul orar dens acoperă firings-urile sărite de planificatorul GitHub; pragul ține și numărul de build-uri Cloudflare la ~12/zi. (Plafonul de 500 build-uri/lună era al lui Pages și nu se mai aplică — vezi IZZ-0305.)
Publicarea pe Worker — .github/workflows/deploy-worker.yml: randează render-only, verifică output-ul înainte de producție (minim 1.000 de fișiere, bugetul de redirecte) și publică prin wrangler deploy. Workers Builds (integrarea git din Cloudflare) nu mai e pe cale: factura minutele de build (7.407 minute peste plafon, 22 aug – 21 sep 2026, $37,04), iar randarea a fost mutată pe runnerul GitHub (IZZ-0326). Configurația versionată stă în wrangler.jsonc:
main: infra/worker.js — nu mai e proiect assets-only. Workerul răspunde la /push/* și /sw.js, iar un 404 de articol expirat cade pe oglinda gh-pages;assets.directory: ./output;not_found_handling: "404-page" — fără linia asta, output/404.html nu ar fi servit niciodată;preview_urls: true — preview per ramură.Variabilele de mediu ale randării se pun din workflow-uri, nu dintr-un ecran Cloudflare: SITE_BASE doar pentru preview-uri, BUILD_COMMIT_SHA / BUILD_BRANCH pentru amprenta servită la /build.json (citită de tools/verify_release.py), iar PYTHON_VERSION vine din actions/setup-python. GEMINI nu e necesar aici — render-only nu apelează AI.
Fluxul: Actions face fetch + AI și salvează starea → comite pe main → declanșează explicit deploy-worker.yml (workflow_dispatch e singurul eveniment care mai pornește workflow-uri din GITHUB_TOKEN) → jobul de deploy randează fără AI, publică pe izz.ro și compară /build.json cu commitul așteptat. Cronul :53 al lui deploy-worker rămâne plasă de siguranță, nu calea normală. (Migrat de pe Cloudflare Pages pe Workers în august 2026.)
Din 22 septembrie 2026 contul e pe Workers Free, unde o versiune de Worker poate avea cel mult 20.000 de fișiere statice (Paid: 100.000). Cererile către fișiere statice rămân gratuite și nelimitate, deci constrângerea e strict numărul de fișiere.
Consecințe, toate versionate în cod:
Arta articolului se desenează în pagină (templates/_art.html + static/styles.css), nu se
mai servește ca art.jpg/art.webp. Compozițiile sunt tipografie și geometrie, deci ies identic
(și mai clar) din CSS. Rămân fișiere doar fotografiile reale și imaginile din date.
og:image propriu doar pentru cele mai noi OG_COVER_MAX_ARTICLES articole; restul folosesc
coperta categoriei din output/og/<categorie>.jpg.
ARTICLE_TTL_DAYS = 11 (aprobat la 25 octombrie 2026 pentru refacerea marjei; precedent: IZZ-0421/0422).
Supapă de siguranță: dacă ingestul sare peste ce a fost măsurat, randarea publică doar câte
articole încap (OUTPUT_FILE_BUDGET) și taie de la cel mai vechi. Peste OUTPUT_FILE_CEILING
randarea moare zgomotos — altfel Cloudflare ar refuza deploy-ul tăcut și site-ul ar îngheța.
Indexul de căutare se publică fără fragmente (generator/pagefind_index.py). Pagefind
scrie un fișier de fragment per pagină, iar la 9.451 de pagini asta ar însemna 23.941 de
fișiere — cu 19,7% peste plafon. curata_bundle() le șterge după ce a citit din ele
legătura id→articol, deci bundle-ul rămâne la 52 de fișiere (1,7 MB). Prețul: rezultatele
arată titlul (cu termenii marcați), categoria și data, nu un fragment de text. Detaliile,
măsurătorile și variantele respinse: specs/cautare-pagefind.md.
Măsoară cu python tools/count_output.py după python -m generator.main --render-only.
Detaliile și cifrele: specs/cloudflare-free-2026-09.md.
Calitatea editorială și disponibilitatea nu depind de intervenția manuală. Verificările deterministe rulează în GitHub Actions; o execuție eșuată devine vizibilă în pagina Actions și prin notificările GitHub.
| Verificare | Declanșare | Ce verifică |
|---|---|---|
tests.yml | PR-uri și schimbări de cod pe main | lint (ruff), teste Python, contractul titlurilor, randare, integritate HTML |
QA check (în build.yml) | după fiecare actualizare de conținut | surse incoerente, categorii goale, titluri oficiale goale sau peste 110 caractere |
editorial-quality.yml | zilnic, 06:37 UTC + manual | audit independent al titlurilor, raport JSON reținut 30 de zile |
monitor.yml | periodic, independent de deploy | lipsa răspunsului pe domeniul public sau căderea simultană a ambelor origini |
release-probe (în build.yml) | după publicare | potrivirea commitului publicat cu manifestul /build.json servit pe izz.ro |
Repo-ul include și analiză statică de securitate (CodeQL, Semgrep), verificarea dependențelor (Dependabot) și sonde de fum/trafic (smoke, visual, probe, trafic).
tools/title_quality_audit.py verifică regula de lectură mobilă, fără apeluri AI și fără servicii externe:
python tools/title_quality_audit.py
python tools/title_quality_audit.py --report title-quality-report.json
Un rezultat reușit garantează că titlul de afișare al fiecărui anunț oficial este nevid și are cel mult 110 caractere. Titlul instituției rămâne neschimbat în data/articles.json; reducerea se aplică doar câmpului de afișare, calculat la randare. Dacă regula este încălcată, workflow-ul eșuează și raportul conține exemplele concrete care necesită corectare.
Programarea GitHub acoperă controalele zilnice de consistență; pentru detectare garantată la minut a indisponibilității externe ar fi necesar un serviciu de monitorizare dedicat, configurat separat la nivel de cont.
Nu este necesară nicio acțiune la rulările verzi. Dacă un workflow devine roșu: deschide execuția din GitHub Actions, descarcă artefactul title-quality-report când e disponibil și corectează articolul sau regula indicată. După un commit, testele și verificarea release-ului rulează din nou automat.