Files
Michele 4894e09707 docs(phase-1): complete Core Generation Pipeline phase
Phase 1 executed (4 plans, 3 waves), verified, gap fixed.
36 requirements marked Complete in traceability table.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 03:15:43 +01:00

15 KiB

phase, verified, status, score, gaps, human_verification
phase verified status score gaps human_verification
01-core-generation-pipeline 2026-03-08T01:41:51Z gaps_found 3/5 must-haves verified
truth status reason artifacts missing
L utente vede badge PN/Schwartz e il pulsante Riprova nella OutputReview failed result.slot e sempre undefined in PostCard: il backend PostResult non include CalendarSlot e OutputReview non esegue il merge dichiarato nel commento di types.ts
path issue
frontend/src/components/PostCard.tsx Riga 42: const slot = result.slot - sempre undefined. Badge PN, Schwartz, metadata e Riprova non funzionanti.
path issue
frontend/src/pages/OutputReview.tsx Passa raw results a PostCard senza merge con CalendarSlot. Campo slot nei PostResult rimane undefined.
Merge CalendarSlot in PostResult nel frontend dopo caricamento job results
Backend includere CalendarResponse nella GenerateResponse (gia salvata nel JSON del job)
truth status reason artifacts missing
Il CSV ha distribuzione PN e Schwartz corretta e fino a 13 righe di contenuto partial Distribuzione PN/Schwartz locked con assert a load-time. CSV puo avere meno di 13 righe se post falliscono (by design LLM-05)
path issue
backend/services/csv_builder.py Filtra solo post status=success - numero righe dipende dai successi, non fisso a 13
Success criteria #4 va inteso come: fino a 13 righe con distribuzione corretta tra le righe presenti
test expected why_human
Accedere a https://lab.mlhub.it/postgenerator/ dopo vps-lab-deploy Web UI si carica, sidebar visibile, Dashboard con banner API key App non ancora deployata sul VPS
test expected why_human
Generare calendario con API key reale e verificare ProgressIndicator Polling 2s, lista post con icone, barra progresso, navigazione a OutputReview Richiede API key Anthropic reale e deployment VPS
test expected why_human
Verificare badge PN e Schwartz nelle PostCard in OutputReview Ogni card mostra tipo (es. Valore) e livello (es. L3) con colori distinti Gap slot-merge causera badge mancanti - serve verifica visuale
test expected why_human
Scaricare CSV e aprire in Excel su Windows Caratteri italiani intatti, 33 colonne, header corretti Compatibilita Excel richiede test runtime reale

Phase 1: Core Generation Pipeline - Verification Report

Phase Goal: L'utente puo generare un calendario di 13 caroselli completi e scaricare un CSV valido per Canva Bulk Create con un click dalla Web UI deployata su VPS. Verified: 2026-03-08T01:41:51Z Status: gaps_found Re-verification: No - initial verification

Goal Achievement

Observable Truths

# Truth Status Evidence
1 La Web UI si carica su https://lab.mlhub.it/postgenerator/ ? HUMAN_NEEDED App non deployata. Dockerfile, docker-compose, SPAStaticFiles, subpath /postgenerator/ tutti cablati.
2 L'utente vede progress indicator e badge PN/Schwartz in OutputReview FAILED ProgressIndicator funziona (polling 2s). Gap critico: result.slot undefined in PostCard - badge e Riprova non funzionanti.
3 CSV scaricabile con caratteri italiani e header Canva corretti VERIFIED code / HUMAN_NEEDED Excel CSVBuilder usa utf-8-sig BOM. CANVA_FIELDS 33 colonne locked. Verifica Excel = human needed.
4 CSV con distribuzione PN corretta e livelli Schwartz assegnati VERIFIED distribution Assert a load-time in constants.py. CalendarService produce 13 slot ordinati per funnel.
5 Post falliti marcati come errore senza bloccare il batch VERIFIED try/except individuale per slot. PostResult status=failed con error. PostCard mostra card rossa.

Score: 3/5 truths verified

Required Artifacts

Artifact Status Details
backend/main.py VERIFIED 104 righe. SPAStaticFiles, lifespan, 4 router inclusi prima di SPA
backend/config.py VERIFIED 54 righe. DATA_PATH, PROMPTS_PATH, OUTPUTS_PATH, CAMPAIGNS_PATH, CONFIG_PATH
backend/constants.py VERIFIED 195 righe. CANVA_FIELDS(33), PERSUASION_DISTRIBUTION, SCHWARTZ_DISTRIBUTION con assert
backend/services/calendar_service.py VERIFIED 297 righe. _build_raw_slots, _sort_by_funnel, _distribute_niches, _generate_dates
backend/services/llm_service.py VERIFIED 285 righe. Retry loop, RateLimitError con retry-after, backoff esponenziale
backend/services/csv_builder.py VERIFIED 182 righe. utf-8-sig, BOM manuale, mapping 33 colonne CANVA_FIELDS
backend/services/generation_pipeline.py VERIFIED 572 righe. asyncio.create_task, try/except individuale per slot, persistenza JSON
backend/services/prompt_service.py VERIFIED 170 righe. compile_prompt, ValueError per variabili mancanti, prompt_exists
backend/routers/generate.py VERIFIED 247 righe. POST /bulk (202), GET /job/{id}/status, GET /job/{id}, POST /single
backend/routers/export.py VERIFIED 151 righe. GET FileResponse + POST con edits inline
backend/routers/settings.py VERIFIED 164 righe. api_key mascherata, merge preserva chiave esistente
backend/routers/calendar.py VERIFIED 60 righe. POST /api/calendar/generate thin router
backend/data/prompts/system_prompt.txt VERIFIED 34 righe. Italiano nativo, tono + regole + struttura 8 slide
backend/data/prompts/pas_valore.txt VERIFIED 76 righe. Variabili template, schema JSON output
backend/data/prompts/topic_generator.txt VERIFIED File presente con variabili per slot calendario
backend/data/prompts/bab_storytelling.txt VERIFIED File presente
backend/data/prompts/listicle_valore.txt VERIFIED File presente
backend/data/prompts/aida_promozione.txt VERIFIED File presente (con variabile call_to_action)
backend/data/prompts/dato_news.txt VERIFIED File presente
frontend/src/api/client.ts VERIFIED 110 righe. API_BASE=/postgenerator/api, tutti gli helper presenti
frontend/src/api/hooks.ts VERIFIED 187 righe. 11 hooks TanStack Query completi
frontend/src/types.ts VERIFIED 161 righe. Tutti gli interface TypeScript
frontend/src/App.tsx VERIFIED 38 righe. 5 route + BrowserRouter basename=/postgenerator
frontend/src/pages/GenerateCalendar.tsx VERIFIED 247 righe. Form + polling flow + navigate a OutputReview
frontend/src/components/ProgressIndicator.tsx VERIFIED 154 righe. useJobStatus, barra progresso, PostStatusRow
frontend/src/pages/OutputReview.tsx PARTIAL 168 righe. localResults, CSV download - manca merge slot
frontend/src/components/PostCard.tsx PARTIAL 180 righe. result.slot sempre undefined - badge e Riprova non funzionanti
frontend/src/components/SlideViewer.tsx VERIFIED 371 righe. Cover + 6 slide + CTA, EditableField, keyboard nav
Dockerfile VERIFIED 42 righe. node:22-slim + python:3.12-slim, --root-path /postgenerator in CMD
docker-compose.yml VERIFIED proxy_net external, postgenerator-data volume, NO porte esposte
From To Via Status Details
GenerateCalendar.tsx POST /api/generate/bulk useGenerateCalendar mutation WIRED apiPost /generate/bulk -> job_id
ProgressIndicator.tsx GET /api/generate/job/{id}/status useJobStatus hook WIRED refetchInterval 2s se status=running
OutputReview.tsx GET /api/generate/job/{id} useJobResults hook WIRED apiGet con jobId dal URL param
OutputReview.tsx POST /api/export/{id}/csv useDownloadEditedCsv WIRED apiDownload POST con localResults + campagna
PostCard.tsx result.slot CalendarSlot direct field access NOT_WIRED result.slot sempre undefined - merge non avviene
GenerationPipeline LLMService per ogni slot asyncio.to_thread WIRED Per-item isolation, try/except individuale
LLMService anthropic.Anthropic client _load_api_key() WIRED Carica da settings.json o env ANTHROPIC_API_KEY
CSVBuilder CANVA_FIELDS 33 colonne from constants.py WIRED DictWriter fieldnames=CANVA_FIELDS
main.py SPAStaticFiles montato dopo tutti i router WIRED Ordine corretto nel codice
Dockerfile CMD Uvicorn --root-path /postgenerator solo in CMD WIRED Mai nel costruttore FastAPI()

Requirements Coverage

Requirement Status Note
INF-01 Backend FastAPI VERIFIED main.py + 4 router
INF-02 Frontend React + Tailwind VERIFIED Vite + Tailwind v4 + BrowserRouter
INF-03 Single container Docker multi-stage VERIFIED Dockerfile 2 stage
INF-04 Deploy VPS /postgenerator/ HUMAN_NEEDED Non ancora deployato
INF-05 Config via .env VERIFIED .env.example, config.py da env
INF-06 File-based storage VERIFIED prompts/, outputs/, data/
CAL-01 13 post distribuzione PN VERIFIED Constants + assert + CalendarService
CAL-02 Livelli Schwartz corretti VERIFIED SCHWARTZ_DISTRIBUTION + assert
CAL-03 Rotazione nicchie 50/50 VERIFIED _distribute_niches
CAL-04 Fasi campagna ordinate VERIFIED _sort_by_funnel
CAL-05 Date di pubblicazione VERIFIED _generate_dates con lun/mer/ven
CAL-06 Topic generation LLM VERIFIED LLMService.generate_topic + topic_generator.txt
CAL-07 Override topic manuale VERIFIED CalendarSlot.topic Optional
FMT-01 Mapping tipo x livello -> formato VERIFIED FormatSelector + format_mapping.json
FMT-02 Mapping configurabile JSON VERIFIED backend/data/format_mapping.json
LLM-01 8 slide in JSON strutturato VERIFIED GeneratedPost schema Pydantic
LLM-02 Validazione JSON VERIFIED model_validate_json in LLMService
LLM-03 Retry con istruzione correttiva VERIFIED validation_retry_done loop
LLM-04 Rate limiting e backoff VERIFIED RateLimitError + retry-after + backoff esponenziale
LLM-05 Per-item error isolation VERIFIED try/except individuale per slot
LLM-06 Provider LLM configurabile VERIFIED LLM_MODEL env var, Settings.llm_model
PRM-01 Prompt in file .txt VERIFIED 7 prompt .txt in backend/data/prompts/
PRM-02 Prompt Manager VERIFIED PromptService.compile_prompt
PRM-03 5 prompt base per MVP VERIFIED 5 prompt narrativi presenti
PRM-04 System prompt in italiano VERIFIED system_prompt.txt in italiano nativo
CSV-01 33 colonne Canva Bulk Create VERIFIED CANVA_FIELDS 33 elementi locked
CSV-02 Encoding utf-8-sig BOM VERIFIED encoding=utf-8-sig + BOM manuale
CSV-03 Campi metadato inclusi VERIFIED 8 metadati: campagna, fase, tipo, formato, funzione, livello, nicchia, data
CSV-04 Download CSV dalla Web UI VERIFIED useDownloadEditedCsv + triggerDownload
IMG-01 Keyword immagine per slide VERIFIED cover_image_keyword, slide.image_keyword, cta_image_keyword
IMG-04 Fallback keyword testuale VERIFIED CANVA_FIELDS usa _image_keyword non URL
UI-01 Dashboard con stato VERIFIED Dashboard.tsx con banner API key
UI-02 Form Genera Calendario VERIFIED GenerateCalendar.tsx completo
UI-03 Form Genera Singolo Post VERIFIED GenerateSingle.tsx
UI-04 Output Review con anteprima slide PARTIAL SlideViewer funzionale, badge mancanti per slot-merge gap
UI-07 Pagina Impostazioni VERIFIED Settings.tsx completo
UI-08 Progress indicator VERIFIED ProgressIndicator.tsx con polling 2s

Anti-Patterns Found

File Line Pattern Severity Impact
frontend/src/components/PostCard.tsx 42 result.slot sempre undefined BLOCKER Badge PN, Schwartz, metadata non visibili; Riprova non funziona
frontend/src/pages/OutputReview.tsx 135-146 Raw results a PostCard senza merge slot BLOCKER Radice del problema: CalendarSlot mai aggiunto ai PostResult

Human Verification Required

1. Accesso Web UI su VPS

Test: Aprire https://lab.mlhub.it/postgenerator/ dopo vps-lab-deploy Expected: Pagina si carica, sidebar con navigazione, Dashboard mostra banner API key Why human: App non ancora deployata sul VPS

2. Flusso generazione completo

Test: Configurare API key, inserire obiettivo campagna (min 10 caratteri), cliccare Genera Calendario Expected: ProgressIndicator con polling 2s, lista post con icone individuali, navigazione automatica a OutputReview al completamento Why human: Richiede API key Anthropic reale e deployment VPS

3. Badge nella OutputReview (gap noto)

Test: Verificare PostCard con badge PN colorati e badge livello Schwartz Expected: Ogni card mostra tipo (es. Valore, Storytelling) e livello (es. L3) con colori distinti Why human: Il gap slot-merge causera badge mancanti - serve verifica visuale della gravita

4. CSV in Excel con caratteri italiani

Test: Scaricare il CSV e aprire in Microsoft Excel su Windows Expected: Caratteri italiani intatti, 33 colonne, header corretti Why human: Compatibilita Excel richiede test runtime reale

Gaps Summary

Il phase goal e quasi completamente implementato. L unico gap bloccante nel codice e la mancata propagazione dei dati CalendarSlot ai PostResult nel frontend.

Gap Critico: slot-merge mancante in OutputReview

Il backend PostResult contiene solo slot_index (intero), non l oggetto CalendarSlot completo. La GenerateResponse include i results ma non il calendar. Il file types.ts dichiara PostResult.slot?: CalendarSlot con il commento "viene aggiunto dal frontend dopo merge con CalendarSlot", ma questo merge non avviene mai in OutputReview.tsx.

In PostCard.tsx riga 42: const slot = result.slot e sempre undefined.

Conseguenze:

  1. BadgePN tipo={slot.tipo_contenuto} non renderizzato (slot undefined)
  2. BadgeSchwartz livello={slot.livello_schwartz} non renderizzato
  3. Metadati secondari (formato, nicchia, data) non visibili nella card
  4. handleRetry() ritorna immediatamente (if (!slot) return)

Fix raccomandato: Aggiungere calendar: Optional[CalendarResponse] alla GenerateResponse del backend (il calendario e gia salvato nel JSON del job), poi nel frontend aggiornare il useEffect di OutputReview.tsx:

// In OutputReview.tsx useEffect:
const slotMap = Object.fromEntries(
  (jobData.calendar?.slots ?? []).map(s => [s.indice, s])
)
setLocalResults(jobData.results.map(r => ({ ...r, slot: slotMap[r.slot_index] })))

Tutto il resto e implementato correttamente: pipeline LLM con retry e rate limiting, CalendarService con distribuzione locked, CSVBuilder con utf-8-sig BOM, 7 prompt italiani con schema JSON, form UI completo, polling ProgressIndicator, SlideViewer con edit inline, Docker multi-stage build, subpath /postgenerator/ configurato ovunque.


Verified: 2026-03-08T01:41:51Z Verifier: Claude Sonnet 4.6 (gsd-verifier)