# nahimmora/news-auto-publisher-lavozriojana architecture

> Architecture diagram of the GitHub repository nahimmora/news-auto-publisher-lavozriojana, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-08-15). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/nahimmora/news-auto-publisher-lavozriojana
- Repository: https://github.com/nahimmora/news-auto-publisher-lavozriojana

## Overview

#### Purpose and execution surface
La Voz Riojana is a Windows-first Python automation system that ingests regional news, applies editorial validation/rewrite, generates social assets, and conditionally publishes to a Node CMS, Facebook, and Instagram. Operational state is local JSON, not a database. Primary entry points are `cli.py`, continuous supervision in `run_24x7.py`, batch execution in `run_all.py`, and section-specific runners such as `main_locales.py`.

#### Orchestration, safety, and runtime control
`cli.py` exposes operational commands: diagnostics, preflight, one-cycle execution, canary, queue cutover, backup, alerts, and reconciliation. Deployment modes constrain channel availability but cannot override kill switches. Result states and evidence are standardized for supervisor/automation use.
- `cli.py`
- `run_24x7.py`
- `utils/deployment.py`
- `utils/preflight.py`
- `utils/operation_result.py`

#### Ingestion and normalization
Section scrapers discover links and extract articles from Nueva Rioja and Tiempo Popular. A common runner coordinates sources; source contracts, URL normalization, deduplication, and filters form the boundary between unreliable external HTML and internal news candidates.
- `scraping/runner.py`
- `scraping/base_nuevarioja.py`
- `scraping/base_tiempopopular.py`
- `utils/scraper_contract.py`
- `utils/news_dedup.py`

#### Editorial processing and routing
Content is screened by policy and blocked-keyword rules, classified/prioritized, and may be rewritten or captioned through OpenAI-facing modules. Editorial routing can divert eligible items into a separate manual premium workflow; it is disabled by default to preserve automatic Instagram selection.
- `openIA/rewrite_news.py`
- `openIA/caption_generator.py`
- `utils/editorial_policy.py`
- `utils/editorial_router.py`
- `pipeline/node_webapp/editorial.py`

#### Media and rendering pipeline
The system obtains/processes images and creates cards, reels, and premium static assets. Python/Pillow-style rendering is the automatic default; a separate TypeScript/Remotion project renders premium studio artifacts. Video production depends on system `ffmpeg`/`ffprobe` and Python-installed `yt-dlp`.
- `layout/image_generator.py`
- `openIA/reel_generator.py`
- `utils/video_renderer.py`
- `utils/remotion_renderer.py`
- `remotion/src/Root.tsx`

#### Queues, durable state, and recovery
Local JSON-backed durable queues coordinate automatic social work, manual posts/videos, and premium submissions. They support events, throttling, dead-letter/recovery-oriented behavior, cutover archiving, and quarantine rather than a central database. Environment-configurable data/log/output paths enable isolated runs.
- `utils/durable_queue.py`
- `utils/social_queue.py`
- `utils/premium_post_queue.py`
- `utils/queue_cutover.py`
- `utils/manual_video_queue.py`

#### Publishing boundaries and external services
Web publication is isolated behind the Node webapp adapter; Meta clients manage Facebook Graph and Instagram calls, with token handling and stage-level results. Facebook has a pre-publication public-page/`og:image` verification boundary. R2-compatible object storage is used for media and reversible health checks. External publication requires enabled switches, authorization, capacity limits, and channel-specific validation.
- `pipeline/publish_web.py`
- `pipeline/node_webapp/publisher.py`
- `meta/fb_client.py`
- `meta/ig_client.py`
- `utils/r2_storage.py`

#### Operations and observability
The 24x7 profile runs under Windows PowerShell/task scheduling, guarded by supervisor diagnostics and idempotent process startup. Heartbeats, structured logging, alert detection/deduplication, and a durable alert outbox decouple monitoring from optional webhook delivery. CI runs on Windows and validates dry-run end-to-end contracts with external doubles.
- `scripts/start_24x7_production.ps1`
- `utils/heartbeat.py`
- `utils/alerts.py`
- `utils/logging_setup.py`
- `.github/workflows/reliability.yml`

Main entry points: [`utils/durable_queue.py`](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/durable_queue.py) (Durable Social Queues), [`utils/deployment.py`](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/deployment.py) (Deployment Guards), [`utils/editorial_router.py`](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/editorial_router.py) (Editorial Processing), [`utils/r2_storage.py`](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/r2_storage.py) (R2 Object Storage)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_control["Runtime Control"]
  node_cli["Operations CLI<br/>Python entry point<br/>[cli.py]"]
  node_supervisor["24x7 Supervisor<br/>Python runner<br/>[run_24x7.py]"]
  node_deployment["Deployment Guards<br/>runtime policy<br/>[deployment.py]"]
  node_preflight["Preflight Checks<br/>validation<br/>[preflight.py]"]
  node_windows_runtime["Windows Scheduled Runtime<br/>PowerShell launcher"]
end

subgraph group_ingestion["News Pipeline"]
  node_scrape_runner["Scraper Runner<br/>ingestion coordinator<br/>[runner.py]"]
  node_sources["Regional News Sources<br/>HTML scrapers<br/>[base_nuevarioja.py]"]
  node_scraper_contract["Source Contracts<br/>normalization"]
  node_dedup["Deduplication<br/>candidate filter<br/>[news_dedup.py]"]
end

subgraph group_content["Editorial &amp; Media"]
  node_editorial["Editorial Processing<br/>policy and routing"]
  node_rewrite["OpenAI Content Tools<br/>AI integration<br/>[rewrite_news.py]"]
  node_media["Automatic Media Renderer<br/>image and video generation<br/>[image_generator.py]"]
  node_premium_renderer["Premium Studio Renderer<br/>Remotion bridge"]
end

subgraph group_state["Durable State"]
  node_queues[("Durable Social Queues<br/>local JSON queues<br/>[durable_queue.py]")]
  node_cutover["Queue Cutover<br/>archive and recovery<br/>[queue_cutover.py]"]
end

subgraph group_delivery["Publishing &amp; Operations"]
  node_web_publish["Web Publishing Adapter<br/>Node CMS boundary<br/>[publish_web.py]"]
  node_facebook["Facebook Publisher<br/>Meta Graph client<br/>[fb_client.py]"]
  node_instagram["Instagram Publisher<br/>Meta client<br/>[ig_client.py]"]
  node_storage[("R2 Object Storage<br/>external media storage<br/>[r2_storage.py]")]
  node_observability["Monitoring &amp; Alerts<br/>operations telemetry<br/>[alerts.py]"]
end

node_windows_runtime -->|"starts"| node_supervisor
node_cli -->|"runs"| node_preflight
node_cli -->|"enforces"| node_deployment
node_supervisor -->|"executes cycles"| node_scrape_runner
node_supervisor -->|"emits health"| node_observability
node_deployment -.->|"gates"| node_web_publish
node_deployment -.->|"gates"| node_facebook
node_deployment -.->|"gates"| node_instagram
node_scrape_runner -->|"extracts"| node_sources
node_sources -->|"raw articles"| node_scraper_contract
node_scraper_contract -->|"normalized candidates"| node_dedup
node_dedup -->|"news candidates"| node_editorial
node_editorial -->|"rewrite or caption"| node_rewrite
node_rewrite -->|"approved content"| node_media
node_editorial -.->|"premium route"| node_premium_renderer
node_media -->|"media assets"| node_storage
node_premium_renderer -->|"premium assets"| node_storage
node_editorial -->|"queues approved work"| node_queues
node_media -->|"attaches assets"| node_queues
node_queues -.->|"archive or quarantine"| node_cutover
node_queues -->|"web jobs"| node_web_publish
node_queues -->|"Facebook jobs"| node_facebook
node_queues -->|"Instagram jobs"| node_instagram
node_storage -->|"hosted media"| node_facebook
node_storage -->|"hosted media"| node_instagram
node_web_publish -->|"stage results"| node_observability
node_facebook -->|"stage results"| node_observability
node_instagram -->|"stage results"| node_observability

click node_cli "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/cli.py"
click node_supervisor "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/run_24x7.py"
click node_deployment "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/deployment.py"
click node_preflight "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/preflight.py"
click node_scrape_runner "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/scraping/runner.py"
click node_sources "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/scraping/base_nuevarioja.py"
click node_scraper_contract "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/scraper_contract.py"
click node_dedup "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/news_dedup.py"
click node_editorial "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/editorial_router.py"
click node_rewrite "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/openIA/rewrite_news.py"
click node_media "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/layout/image_generator.py"
click node_premium_renderer "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/remotion_renderer.py"
click node_queues "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/durable_queue.py"
click node_cutover "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/queue_cutover.py"
click node_web_publish "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/pipeline/publish_web.py"
click node_facebook "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/meta/fb_client.py"
click node_instagram "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/meta/ig_client.py"
click node_storage "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/r2_storage.py"
click node_observability "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/alerts.py"
click node_windows_runtime "https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/scripts/start_24x7_production.ps1"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_cli,node_supervisor,node_deployment,node_preflight,node_windows_runtime toneBlue
class node_scrape_runner,node_sources,node_scraper_contract,node_dedup toneAmber
class node_editorial,node_rewrite,node_media,node_premium_renderer toneMint
class node_queues,node_cutover toneRose
class node_web_publish,node_facebook,node_instagram,node_storage,node_observability toneIndigo
```

## Components

### Runtime Control

- [Operations CLI](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/cli.py): Python entry point · Runs diagnostics, preflight, cycles, cutover, backup, alerts, and reconciliation. · `cli.py`
- [24x7 Supervisor](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/run_24x7.py): Python runner · Continuously supervises idempotent automation cycles. · `run_24x7.py`
- [Deployment Guards](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/deployment.py): runtime policy · Deployment modes constrain channels alongside kill switches. · `utils/deployment.py`
- [Preflight Checks](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/preflight.py): validation · `utils/preflight.py`
- [Windows Scheduled Runtime](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/scripts/start_24x7_production.ps1): PowerShell launcher · Starts the production 24x7 profile under Windows scheduling. · `scripts/start_24x7_production.ps1`

### News Pipeline

- [Scraper Runner](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/scraping/runner.py): ingestion coordinator · `scraping/runner.py`
- [Regional News Sources](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/scraping/base_nuevarioja.py): HTML scrapers · Nueva Rioja and Tiempo Popular extraction boundary. · `scraping/base_nuevarioja.py`
- [Source Contracts](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/scraper_contract.py): normalization · Normalizes URLs and applies source-level candidate rules. · `utils/scraper_contract.py`
- [Deduplication](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/news_dedup.py): candidate filter · `utils/news_dedup.py`

### Editorial & Media

- [Editorial Processing](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/editorial_router.py): policy and routing · Screens, prioritizes, rewrites, captions, and routes candidates. · `utils/editorial_router.py`
- [OpenAI Content Tools](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/openIA/rewrite_news.py): AI integration · Generates rewritten news and social captions. · `openIA/rewrite_news.py`
- [Automatic Media Renderer](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/layout/image_generator.py): image and video generation · Produces images, cards, and reels using Python tooling. · `layout/image_generator.py`
- [Premium Studio Renderer](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/remotion_renderer.py): Remotion bridge · Renders premium static artifacts in a separate TypeScript project. · `utils/remotion_renderer.py`

### Durable State

- [Durable Social Queues](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/durable_queue.py): local JSON queues · Coordinates automatic, manual, video, and premium work with recovery behavior. · `utils/durable_queue.py`
- [Queue Cutover](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/queue_cutover.py): archive and recovery · Archives and quarantines queue work during cutover. · `utils/queue_cutover.py`

### Publishing & Operations

- [Web Publishing Adapter](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/pipeline/publish_web.py): Node CMS boundary · Isolates publication through the Node webapp adapter. · `pipeline/publish_web.py`
- [Facebook Publisher](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/meta/fb_client.py): Meta Graph client · Verifies public page and og:image before publication. · `meta/fb_client.py`
- [Instagram Publisher](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/meta/ig_client.py): Meta client · `meta/ig_client.py`
- [R2 Object Storage](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/r2_storage.py): external media storage · Stores media and supports reversible health checks. · `utils/r2_storage.py`
- [Monitoring & Alerts](https://github.com/nahimmora/news-auto-publisher-lavozriojana/blob/main/utils/alerts.py): operations telemetry · Provides heartbeats, structured logs, deduplicated alerts, and durable alert delivery. · `utils/alerts.py`

## Connections

- Windows Scheduled Runtime → 24x7 Supervisor: starts
- Operations CLI → Preflight Checks: runs
- Operations CLI → Deployment Guards: enforces
- 24x7 Supervisor → Scraper Runner: executes cycles
- 24x7 Supervisor → Monitoring & Alerts: emits health
- Deployment Guards → Web Publishing Adapter: gates
- Deployment Guards → Facebook Publisher: gates
- Deployment Guards → Instagram Publisher: gates
- Scraper Runner → Regional News Sources: extracts
- Regional News Sources → Source Contracts: raw articles
- Source Contracts → Deduplication: normalized candidates
- Deduplication → Editorial Processing: news candidates
- Editorial Processing → OpenAI Content Tools: rewrite or caption
- OpenAI Content Tools → Automatic Media Renderer: approved content
- Editorial Processing → Premium Studio Renderer: premium route
- Automatic Media Renderer → R2 Object Storage: media assets
- Premium Studio Renderer → R2 Object Storage: premium assets
- Editorial Processing → Durable Social Queues: queues approved work
- Automatic Media Renderer → Durable Social Queues: attaches assets
- Durable Social Queues → Queue Cutover: archive or quarantine
- Durable Social Queues → Web Publishing Adapter: web jobs
- Durable Social Queues → Facebook Publisher: Facebook jobs
- Durable Social Queues → Instagram Publisher: Instagram jobs
- R2 Object Storage → Facebook Publisher: hosted media
- R2 Object Storage → Instagram Publisher: hosted media
- Web Publishing Adapter → Monitoring & Alerts: stage results
- Facebook Publisher → Monitoring & Alerts: stage results
- Instagram Publisher → Monitoring & Alerts: stage results
